1- import { SQLITE_TRUE , SqliteInputRow } from '@powersync/service-sync-rules' ;
1+ import {
2+ applyRowContext ,
3+ CompatibilityContext ,
4+ SQLITE_TRUE ,
5+ SqliteInputRow ,
6+ TimeValuePrecision
7+ } from '@powersync/service-sync-rules' ;
28import { afterAll , beforeEach , describe , expect , test } from 'vitest' ;
39import { clearTestDb , createUpperCaseUUID , TEST_CONNECTION_OPTIONS , waitForPendingCDCChanges } from './util.js' ;
410import { CDCToSqliteRow , toSqliteInputRow } from '@module/common/mssqls-to-sqlite.js' ;
@@ -43,10 +49,10 @@ describe('MSSQL Data Types Tests', () => {
4349
4450 date_col DATE,
4551 datetime_col DATETIME,
46- datetime2_col DATETIME2(6 ),
52+ datetime2_col DATETIME2(7 ),
4753 smalldatetime_col SMALLDATETIME,
4854 datetimeoffset_col DATETIMEOFFSET(3),
49- time_col TIME(6 ),
55+ time_col TIME(7 ),
5056
5157 char_col CHAR(10),
5258 varchar_col VARCHAR(255),
@@ -214,7 +220,14 @@ describe('MSSQL Data Types Tests', () => {
214220
215221 test ( 'Date types mappings' , async ( ) => {
216222 const beforeLSN = await getLatestLSN ( connectionManager ) ;
217- const testDate = new Date ( '2023-03-06T15:47:00.000Z' ) ;
223+ const testDate = new Date ( '2023-03-06T15:47:00.123Z' ) ;
224+ // This adds 0.4567 milliseconds to the JS date, see https://github.com/tediousjs/tedious/blob/0c256f186600d7230aec05553ebad209bed81acc/src/data-types/datetime2.ts#L74.
225+ // Note that there's a typo in tedious there. When reading dates, the property is actually called nanosecondsDelta.
226+ // This is only relevant when binding datetime values, so only in this test.
227+ Object . defineProperty ( testDate , 'nanosecondDelta' , {
228+ enumerable : false ,
229+ value : 0.0004567
230+ } ) ;
218231 await connectionManager . query (
219232 `
220233 INSERT INTO ${ escapeIdentifier ( connectionManager . schema ) } .test_data(
@@ -235,9 +248,9 @@ describe('MSSQL Data Types Tests', () => {
235248 [
236249 { name : 'date_col' , type : sql . Date , value : testDate } ,
237250 { name : 'datetime_col' , type : sql . DateTime , value : testDate } ,
238- { name : 'datetime2_col' , type : sql . DateTime2 ( 6 ) , value : testDate } ,
251+ { name : 'datetime2_col' , type : sql . DateTime2 ( 7 ) , value : testDate } ,
239252 { name : 'smalldatetime_col' , type : sql . SmallDateTime , value : testDate } ,
240- { name : 'time_col' , type : sql . Time ( 6 ) , value : testDate }
253+ { name : 'time_col' , type : sql . Time ( 7 ) , value : testDate }
241254 ]
242255 ) ;
243256 await waitForPendingCDCChanges ( beforeLSN , connectionManager ) ;
@@ -246,14 +259,32 @@ describe('MSSQL Data Types Tests', () => {
246259 const replicatedRows = await getReplicatedRows ( connectionManager , 'test_data' ) ;
247260 const expectedResult = {
248261 date_col : '2023-03-06' ,
249- datetime_col : '2023-03-06T15:47:00.000Z ' ,
250- datetime2_col : '2023-03-06T15:47:00.000Z ' ,
251- smalldatetime_col : '2023-03-06T15:47:00.000Z ' ,
252- time_col : '15:47:00.000 '
262+ datetime_col : '2023-03-06T15:47:00.123000000Z ' ,
263+ datetime2_col : '2023-03-06T15:47:00.123456700Z ' ,
264+ smalldatetime_col : '2023-03-06T15:47:00.000000000Z ' ,
265+ time_col : '15:47:00.123456700 '
253266 } ;
254267
255- expect ( databaseRows [ 0 ] ) . toMatchObject ( expectedResult ) ;
256- expect ( replicatedRows [ 0 ] ) . toMatchObject ( expectedResult ) ;
268+ expect ( applyRowContext ( databaseRows [ 0 ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
269+ expectedResult
270+ ) ;
271+ expect ( applyRowContext ( replicatedRows [ 0 ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
272+ expectedResult
273+ ) ;
274+
275+ const restrictedPrecisionResult = {
276+ date_col : '2023-03-06' ,
277+ datetime_col : '2023-03-06T15:47:00.123000Z' ,
278+ datetime2_col : '2023-03-06T15:47:00.123456Z' ,
279+ smalldatetime_col : '2023-03-06T15:47:00.000000Z' ,
280+ time_col : '15:47:00.123456'
281+ } ;
282+ const restrictedPrecision = new CompatibilityContext ( {
283+ edition : 2 ,
284+ maxTimeValuePrecision : TimeValuePrecision . microseconds
285+ } ) ;
286+ expect ( applyRowContext ( databaseRows [ 0 ] , restrictedPrecision ) ) . toMatchObject ( restrictedPrecisionResult ) ;
287+ expect ( applyRowContext ( replicatedRows [ 0 ] , restrictedPrecision ) ) . toMatchObject ( restrictedPrecisionResult ) ;
257288 } ) ;
258289
259290 test ( 'Date types edge cases mappings' , async ( ) => {
@@ -277,18 +308,22 @@ describe('MSSQL Data Types Tests', () => {
277308 await waitForPendingCDCChanges ( beforeLSN , connectionManager ) ;
278309
279310 const expectedResults = [
280- { datetime2_col : '0001-01-01T00:00:00.000Z ' } ,
281- { datetime2_col : '9999-12-31T23:59:59.999Z ' } ,
282- { datetime_col : '1753-01-01T00:00:00.000Z ' } ,
283- { datetime_col : '9999-12-31T23:59:59.997Z ' }
311+ { datetime2_col : '0001-01-01T00:00:00.000000000Z ' } ,
312+ { datetime2_col : '9999-12-31T23:59:59.999000000Z ' } ,
313+ { datetime_col : '1753-01-01T00:00:00.000000000Z ' } ,
314+ { datetime_col : '9999-12-31T23:59:59.997000000Z ' }
284315 ] ;
285316
286317 const databaseRows = await getDatabaseRows ( connectionManager , 'test_data' ) ;
287318 const replicatedRows = await getReplicatedRows ( connectionManager , 'test_data' ) ;
288319
289320 for ( let i = 0 ; i < expectedResults . length ; i ++ ) {
290- expect ( databaseRows [ i ] ) . toMatchObject ( expectedResults [ i ] ) ;
291- expect ( replicatedRows [ i ] ) . toMatchObject ( expectedResults [ i ] ) ;
321+ expect ( applyRowContext ( databaseRows [ i ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
322+ expectedResults [ i ]
323+ ) ;
324+ expect ( applyRowContext ( replicatedRows [ i ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
325+ expectedResults [ i ]
326+ ) ;
292327 }
293328 } ) ;
294329
@@ -302,15 +337,19 @@ describe('MSSQL Data Types Tests', () => {
302337 await waitForPendingCDCChanges ( beforeLSN , connectionManager ) ;
303338
304339 const expectedResult = {
305- datetimeoffset_col : '2023-03-06T10:47:00.000Z ' // Converted to UTC
340+ datetimeoffset_col : '2023-03-06T10:47:00.000000000Z ' // Converted to UTC
306341 } ;
307342
308343 const databaseRows = await getDatabaseRows ( connectionManager , 'test_data' ) ;
309344 const replicatedRows = await getReplicatedRows ( connectionManager , 'test_data' ) ;
310345
311346 // Note: The driver converts DateTimeOffset to Date, which incorporates the timezone offset which is then represented in UTC.
312- expect ( databaseRows [ 0 ] ) . toMatchObject ( expectedResult ) ;
313- expect ( replicatedRows [ 0 ] ) . toMatchObject ( expectedResult ) ;
347+ expect ( applyRowContext ( databaseRows [ 0 ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
348+ expectedResult
349+ ) ;
350+ expect ( applyRowContext ( replicatedRows [ 0 ] , CompatibilityContext . FULL_BACKWARDS_COMPATIBILITY ) ) . toMatchObject (
351+ expectedResult
352+ ) ;
314353 } ) ;
315354
316355 test ( 'UniqueIdentifier type mapping' , async ( ) => {
0 commit comments