Skip to content

Add temporal / System Versioned tables support#65

Merged
arashi01 merged 3 commits intomainfrom
system-versioned-table-support
Dec 6, 2025
Merged

Add temporal / System Versioned tables support#65
arashi01 merged 3 commits intomainfrom
system-versioned-table-support

Conversation

@arashi01
Copy link
Copy Markdown
Contributor

@arashi01 arashi01 commented Dec 6, 2025

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive temporal/system-versioned table support to the ashtray-mssql module, enabling time-travel queries and historical state tracking for SQL Server databases. It also introduces opaque wrapper utilities and renames timestamp100Nanos to timestamp for V1 identifiers.

Key changes:

  • Complete temporal tables implementation with TemporalRepo, TemporalSchema, SystemTime, and Period abstractions supporting all SQL Server temporal query modes
  • Generic repository derivation supporting any primary key type (Long, Identifier, UUID, etc.)
  • IdentifierOps trait for reducing boilerplate in opaque type wrappers with selective export capability

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
TemporalRepo.scala Repository operations for temporal queries (asOf, history, diff, etc.) with critical bug in restoreTo
TemporalSchema.scala Schema metadata abstraction with inline fragment builders
Temporal.scala Entity wrapper with period columns and type-safe mode discrimination
SystemTime.scala ADT for FOR SYSTEM_TIME query modes (AsOf, FromTo, Between, ContainedIn, All)
Period.scala Period representation with MaxDateTime2 constant
TemporalMode.scala Phantom type markers for Standard vs SystemVersioned entities
IdentifierOps.scala Abstract classes for reducing opaque type boilerplate
Identifier.scala Renamed V1 method from timestamp100Nanos to timestamp
package.scala Added temporal[ID, A] extension method on Transactor and type aliases
README.md Comprehensive documentation of temporal tables and identifiers with minor error
temporal_*.scala (tests) Extensive unit and integration test coverage
identifier_*_tests.scala Tests for opaque wrapper utilities and encoding
build.sbt Whitespace cleanup

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +365 to +370
(Fragment.const(s"UPDATE ${schema.tableName} SET ") ++
Fragment.const(
schema.columns.toString.split(",").map(_.trim).map(col => s"$col = ?").mkString(", ")
) ++ // This is a simplified approach
Fragment.const(s" WHERE ${schema.idColumn} = ") ++ fr"$id").update.run
.transact(xa)
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The restoreTo method has a broken implementation. It parses schema.columns.toString to construct an UPDATE statement, but this doesn't bind the entity values from historical.entity. The generated SQL will have ? placeholders without corresponding parameters, causing the query to fail at runtime.

Consider implementing this method to properly use Write[A] to bind entity values, or document that this operation is not yet implemented and return F.raiseError with a descriptive message.

Suggested change
(Fragment.const(s"UPDATE ${schema.tableName} SET ") ++
Fragment.const(
schema.columns.toString.split(",").map(_.trim).map(col => s"$col = ?").mkString(", ")
) ++ // This is a simplified approach
Fragment.const(s" WHERE ${schema.idColumn} = ") ++ fr"$id").update.run
.transact(xa)
// Build the SET clause from schema.columns
val columns = schema.columns.toString.split(",").map(_.trim)
val setClause = columns.map(col => s"$col = ?").mkString(", ")
val sql = s"UPDATE ${schema.tableName} SET $setClause WHERE ${schema.idColumn} = ?"
Update[(A, ID)](sql).run((historical.entity, id)).transact(xa)

Copilot uses AI. Check for mistakes.
README.md Outdated
- `InvalidBatchCount(count)` — non-positive batch size

**Version-specific extensions**:
- **V7**: `timestampMillis`, `timestamp` (as `java.time.Instant`)
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states V7 has a timestamp method returning java.time.Instant, but looking at the code, V7 identifiers have timestampMillis: Long and instant: Instant methods. The method name timestamp is used for V1 identifiers instead. This should be corrected to instant to match the actual API.

Suggested change
- **V7**: `timestampMillis`, `timestamp` (as `java.time.Instant`)
- **V7**: `timestampMillis`, `instant` (as `java.time.Instant`)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@arashi01 arashi01 merged commit 6e90fc9 into main Dec 6, 2025
9 checks passed
@arashi01 arashi01 deleted the system-versioned-table-support branch December 6, 2025 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants