88 "fmt"
99 "log"
1010 "os"
11+ "strconv"
1112 "strings"
1213 "time"
1314
@@ -94,6 +95,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
9495 active BIT,
9596 created_at DATETIME2,
9697 data VARBINARY(100),
98+ price DECIMAL(10,2),
9799 PRIMARY KEY (id)
98100 )` , tableName ),
99101 DropTable : fmt .Sprintf ("DROP TABLE %s" , tableName ),
@@ -109,6 +111,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
109111 active BOOLEAN,
110112 created_at TIMESTAMP,
111113 data BYTEA,
114+ price DECIMAL(10,2),
112115 PRIMARY KEY (id)
113116 )` , tableName ),
114117 DropTable : fmt .Sprintf ("DROP TABLE IF EXISTS %s" , tableName ),
@@ -124,6 +127,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
124127 active TINYINT(1),
125128 created_at DATETIME(3),
126129 data VARBINARY(100),
130+ price DECIMAL(10,2),
127131 PRIMARY KEY (id)
128132 )` , tableName ),
129133 DropTable : fmt .Sprintf ("DROP TABLE IF EXISTS %s" , tableName ),
@@ -139,6 +143,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
139143 active INTEGER,
140144 created_at TEXT,
141145 data BLOB,
146+ price DECIMAL(10,2),
142147 PRIMARY KEY (id)
143148 )` , tableName ),
144149 DropTable : fmt .Sprintf ("DROP TABLE IF EXISTS %s" , tableName ),
@@ -154,6 +159,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
154159 active NUMBER(1),
155160 created_at TIMESTAMP,
156161 data RAW(100),
162+ price NUMBER(10,2),
157163 PRIMARY KEY (id)
158164 )` , tableName ),
159165 DropTable : fmt .Sprintf ("DROP TABLE %s" , tableName ),
@@ -170,6 +176,7 @@ func getDDLTemplates(dbType DBType, tableName string) DDLTemplates {
170176 active SMALLINT,
171177 created_at TIMESTAMP,
172178 data VARBINARY(100),
179+ price DECIMAL(10,2),
173180 PRIMARY KEY (id)
174181 )` , tableName ),
175182 DropTable : fmt .Sprintf ("DROP TABLE %s" , tableName ),
@@ -251,21 +258,22 @@ func runTest(db *sql.DB, _ DBType, tableName string, ddl DDLTemplates) error {
251258 active bool
252259 createdAt time.Time
253260 data []byte
261+ price string // DECIMAL as string to preserve precision
254262 }{
255- {1 , "Alice" , 123.45 , true , time .Date (2024 , 1 , 15 , 10 , 30 , 0 , 0 , time .UTC ), []byte {0x01 , 0x02 , 0x03 }},
256- {2 , "Bob" , 678.90 , false , time .Date (2024 , 2 , 20 , 14 , 45 , 0 , 0 , time .UTC ), []byte {0x04 , 0x05 , 0x06 }},
257- {3 , "Charlie" , 0.0 , true , time .Date (2024 , 3 , 25 , 9 , 0 , 0 , 0 , time .UTC ), nil },
263+ {1 , "Alice" , 123.45 , true , time .Date (2024 , 1 , 15 , 10 , 30 , 0 , 0 , time .UTC ), []byte {0x01 , 0x02 , 0x03 }, "12345.67" },
264+ {2 , "Bob" , 678.90 , false , time .Date (2024 , 2 , 20 , 14 , 45 , 0 , 0 , time .UTC ), []byte {0x04 , 0x05 , 0x06 }, "9999.99" },
265+ {3 , "Charlie" , 0.0 , true , time .Date (2024 , 3 , 25 , 9 , 0 , 0 , 0 , time .UTC ), nil , "0.01" },
258266 }
259267
260- insertSQL := fmt .Sprintf ("INSERT INTO %s (id, name, value, active, created_at, data) VALUES (?, ?, ?, ?, ?, ?)" , tableName )
268+ insertSQL := fmt .Sprintf ("INSERT INTO %s (id, name, value, active, created_at, data, price ) VALUES (?, ?, ?, ?, ?, ?, ?)" , tableName )
261269 stmt , err := db .Prepare (insertSQL )
262270 if err != nil {
263271 return fmt .Errorf ("failed to prepare insert: %w" , err )
264272 }
265273 defer stmt .Close ()
266274
267275 for _ , row := range testRows {
268- result , err := stmt .Exec (row .id , row .name , row .value , row .active , row .createdAt , row .data )
276+ result , err := stmt .Exec (row .id , row .name , row .value , row .active , row .createdAt , row .data , row . price )
269277 if err != nil {
270278 return fmt .Errorf ("failed to insert row %d: %w" , row .id , err )
271279 }
@@ -275,7 +283,7 @@ func runTest(db *sql.DB, _ DBType, tableName string, ddl DDLTemplates) error {
275283
276284 // Select and validate rows
277285 log .Println ("Selecting rows back..." )
278- selectSQL := fmt .Sprintf ("SELECT id, name, value, active, created_at, data FROM %s ORDER BY id" , tableName )
286+ selectSQL := fmt .Sprintf ("SELECT id, name, value, active, created_at, data, price FROM %s ORDER BY id" , tableName )
279287 rows , err := db .Query (selectSQL )
280288 if err != nil {
281289 return fmt .Errorf ("failed to query rows: %w" , err )
@@ -289,6 +297,28 @@ func runTest(db *sql.DB, _ DBType, tableName string, ddl DDLTemplates) error {
289297 }
290298 log .Printf ("Columns: %v" , columns )
291299
300+ // Validate DECIMAL precision/scale metadata
301+ colTypes , err := rows .ColumnTypes ()
302+ if err != nil {
303+ return fmt .Errorf ("failed to get column types: %w" , err )
304+ }
305+ for _ , col := range colTypes {
306+ if col .Name () == "price" {
307+ prec , scale , ok := col .DecimalSize ()
308+ if ! ok {
309+ return fmt .Errorf ("price column: DecimalSize() returned ok=false, expected ok=true" )
310+ }
311+ log .Printf (" Column 'price': DECIMAL(%d,%d)" , prec , scale )
312+ if prec != 10 {
313+ return fmt .Errorf ("price column: expected precision=10, got %d" , prec )
314+ }
315+ if scale != 2 {
316+ return fmt .Errorf ("price column: expected scale=2, got %d" , scale )
317+ }
318+ log .Println (" ✓ DECIMAL precision/scale metadata validated" )
319+ }
320+ }
321+
292322 // Fetch and validate rows
293323 rowCount := 0
294324 for rows .Next () {
@@ -298,13 +328,14 @@ func runTest(db *sql.DB, _ DBType, tableName string, ddl DDLTemplates) error {
298328 var active sql.NullBool
299329 var createdAt sql.NullTime
300330 var data []byte
331+ var price sql.NullString // DECIMAL scanned as string to preserve precision
301332
302- if err := rows .Scan (& id , & name , & value , & active , & createdAt , & data ); err != nil {
333+ if err := rows .Scan (& id , & name , & value , & active , & createdAt , & data , & price ); err != nil {
303334 return fmt .Errorf ("failed to scan row: %w" , err )
304335 }
305336
306- log .Printf (" Row %d: id=%d, name=%v, value=%v, active=%v, created_at=%v, data=%v" ,
307- rowCount + 1 , id , name .String , value .Float64 , active .Bool , createdAt .Time , data )
337+ log .Printf (" Row %d: id=%d, name=%v, value=%v, active=%v, created_at=%v, data=%v, price=%v " ,
338+ rowCount + 1 , id , name .String , value .Float64 , active .Bool , createdAt .Time , data , price . String )
308339
309340 // Validate against expected values
310341 expected := testRows [rowCount ]
@@ -343,6 +374,13 @@ func runTest(db *sql.DB, _ DBType, tableName string, ddl DDLTemplates) error {
343374 }
344375 }
345376 }
377+ // Compare DECIMAL price - parse as float for comparison since string format may vary
378+ // (e.g., ".01" vs "0.01" depending on database)
379+ expectedPrice , _ := strconv .ParseFloat (expected .price , 64 )
380+ gotPrice , _ := strconv .ParseFloat (price .String , 64 )
381+ if expectedPrice != gotPrice {
382+ return fmt .Errorf ("row %d: expected price=%q (%v), got %q (%v)" , rowCount + 1 , expected .price , expectedPrice , price .String , gotPrice )
383+ }
346384
347385 log .Printf (" Row %d: ✓ all values match expected" , rowCount + 1 )
348386 rowCount ++
0 commit comments