@@ -134,6 +134,77 @@ describe("buildExpectedSchema — indexes + FKs", () => {
134134 } ) ;
135135} ) ;
136136
137+ describe ( "buildExpectedSchema — SQLite float normalization (R6)" , ( ) => {
138+ async function loadInline ( children : unknown [ ] ) {
139+ const json = JSON . stringify ( { "metadata.root" : { package : "test" , children } } ) ;
140+ const result = await new MetaDataLoader ( ) . load ( [ new InMemoryStringSource ( json ) ] ) ;
141+ if ( result . errors . length > 0 ) {
142+ throw new Error ( `Loader errors:\n${ result . errors . map ( ( e ) => e . message ) . join ( "\n" ) } ` ) ;
143+ }
144+ return result . root ;
145+ }
146+
147+ test ( "field.float → sqlType {kind:'real'} under sqlite (real4 collapsed, no phantom diff)" , async ( ) => {
148+ const root = await loadInline ( [
149+ {
150+ "object.entity" : {
151+ name : "Measurement" ,
152+ children : [
153+ { "source.rdb" : { "@table" : "measurements" } } ,
154+ { "field.long" : { name : "id" } } ,
155+ { "field.float" : { name : "score" } } ,
156+ { "identity.primary" : { "@fields" : "id" } } ,
157+ ] ,
158+ } ,
159+ } ,
160+ ] ) ;
161+ const snapshot = buildExpectedSchema ( root , { dialect : "sqlite" } ) ;
162+ const scoreCol = snapshot . tables [ 0 ] ?. columns . find ( ( c ) => c . name === "score" ) ;
163+ // SQLite has one float storage class; real4 must be collapsed to real so the
164+ // expected schema matches what the SQLite introspector produces ({kind:"real"}).
165+ expect ( scoreCol ?. sqlType ) . toEqual ( { kind : "real" } ) ;
166+ } ) ;
167+
168+ test ( "field.double → sqlType {kind:'real'} under sqlite (already real, unaffected)" , async ( ) => {
169+ const root = await loadInline ( [
170+ {
171+ "object.entity" : {
172+ name : "Measurement" ,
173+ children : [
174+ { "source.rdb" : { "@table" : "measurements" } } ,
175+ { "field.long" : { name : "id" } } ,
176+ { "field.double" : { name : "value" } } ,
177+ { "identity.primary" : { "@fields" : "id" } } ,
178+ ] ,
179+ } ,
180+ } ,
181+ ] ) ;
182+ const snapshot = buildExpectedSchema ( root , { dialect : "sqlite" } ) ;
183+ const valueCol = snapshot . tables [ 0 ] ?. columns . find ( ( c ) => c . name === "value" ) ;
184+ expect ( valueCol ?. sqlType ) . toEqual ( { kind : "real" } ) ;
185+ } ) ;
186+
187+ test ( "field.float → sqlType {kind:'real4'} under postgres (Postgres fidelity preserved)" , async ( ) => {
188+ const root = await loadInline ( [
189+ {
190+ "object.entity" : {
191+ name : "Measurement" ,
192+ children : [
193+ { "source.rdb" : { "@table" : "measurements" } } ,
194+ { "field.long" : { name : "id" } } ,
195+ { "field.float" : { name : "score" } } ,
196+ { "identity.primary" : { "@fields" : "id" } } ,
197+ ] ,
198+ } ,
199+ } ,
200+ ] ) ;
201+ const snapshot = buildExpectedSchema ( root , { dialect : "postgres" } ) ;
202+ const scoreCol = snapshot . tables [ 0 ] ?. columns . find ( ( c ) => c . name === "score" ) ;
203+ // Postgres can distinguish REAL (single) from DOUBLE PRECISION; real4 must not be collapsed.
204+ expect ( scoreCol ?. sqlType ) . toEqual ( { kind : "real4" } ) ;
205+ } ) ;
206+ } ) ;
207+
137208describe ( "buildExpectedSchema — identity.reference @enforce" , ( ) => {
138209 async function loadInline ( children : unknown [ ] ) {
139210 const json = JSON . stringify ( { "metadata.root" : { package : "test" , children } } ) ;
0 commit comments