@@ -494,11 +494,14 @@ func TestFloat64ColumnBinary(t *testing.T) {
494494 }
495495}
496496
497- func TestDecimalColumnText (t * testing.T ) {
497+ func TestDecimalColumnScaled (t * testing.T ) {
498+ negative , err := qdb .NewDecimal (big .NewInt (- 12345 ), 3 )
499+ assert .NoError (t , err )
500+
498501 prefix := []byte (testTable + " price==" )
499502 testCases := []struct {
500503 name string
501- value any
504+ value qdb. ScaledDecimal
502505 expected []byte
503506 }{
504507 {
@@ -508,37 +511,140 @@ func TestDecimalColumnText(t *testing.T) {
508511 },
509512 {
510513 name : "negative" ,
511- value : qdb . NewDecimal ( big . NewInt ( - 12345 ), 3 ) ,
514+ value : negative ,
512515 expected : append (prefix , 0x17 , 0x03 , 0x02 , 0xCF , 0xC7 , 0x0A ),
513516 },
514517 {
515518 name : "zero with scale" ,
516519 value : qdb .NewDecimalFromInt64 (0 , 4 ),
517520 expected : append (prefix , 0x17 , 0x04 , 0x01 , 0x0 , 0x0A ),
518521 },
522+ }
523+
524+ for _ , tc := range testCases {
525+ t .Run (tc .name , func (t * testing.T ) {
526+ buf := newTestBuffer ()
527+ err := buf .Table (testTable ).DecimalColumnScaled ("price" , tc .value ).At (time.Time {}, false )
528+ assert .NoError (t , err )
529+ assert .Equal (t , tc .expected , buf .Messages ())
530+ })
531+ }
532+ }
533+
534+ func TestDecimalColumnScaledTrimmingAndPadding (t * testing.T ) {
535+ prefix := []byte (testTable + " price==" )
536+
537+ testCases := []struct {
538+ name string
539+ value qdb.ScaledDecimal
540+ expectedBytes []byte
541+ }{
542+ {
543+ name : "127 boundary" ,
544+ value : qdb .NewDecimalFromInt64 (127 , 0 ),
545+ expectedBytes : []byte {0x17 , 0x00 , 0x01 , 0x7F },
546+ },
547+ {
548+ name : "128 sign extension" ,
549+ value : qdb .NewDecimalFromInt64 (128 , 0 ),
550+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0x00 , 0x80 },
551+ },
552+ {
553+ name : "255 sign extension" ,
554+ value : qdb .NewDecimalFromInt64 (255 , 0 ),
555+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0x00 , 0xFF },
556+ },
557+ {
558+ name : "32768 sign extension" ,
559+ value : qdb .NewDecimalFromInt64 (32768 , 0 ),
560+ expectedBytes : []byte {0x17 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 },
561+ },
519562 {
520- name : "null decimal " ,
521- value : qdb .NullDecimal ( ),
522- expected : append ( prefix , 0x17 , 0x0 , 0x0 , 0x0A ) ,
563+ name : "-1 " ,
564+ value : qdb .NewDecimalFromInt64 ( - 1 , 0 ),
565+ expectedBytes : [] byte { 0x17 , 0x00 , 0x01 , 0xFF } ,
523566 },
524567 {
525- name : "shopspring compatible " ,
526- value : fakeShopspringDecimal { coeff : big . NewInt ( 123456 ), exp : - 4 } ,
527- expected : append ( prefix , 0x17 , 0x04 , 0x03 , 0x01 , 0xE2 , 0x40 , 0x0A ) ,
568+ name : "-2 " ,
569+ value : qdb . NewDecimalFromInt64 ( - 2 , 0 ) ,
570+ expectedBytes : [] byte { 0x17 , 0x00 , 0x01 , 0xFE } ,
528571 },
529572 {
530- name : "nil pointer treated as null" ,
531- value : (* fakeShopspringDecimal )(nil ),
532- expected : append (prefix , 0x17 , 0x0 , 0x0 , 0x0A ),
573+ name : "-127" ,
574+ value : qdb .NewDecimalFromInt64 (- 127 , 0 ),
575+ expectedBytes : []byte {0x17 , 0x00 , 0x01 , 0x81 },
576+ },
577+ {
578+ name : "-128" ,
579+ value : qdb .NewDecimalFromInt64 (- 128 , 0 ),
580+ expectedBytes : []byte {0x17 , 0x00 , 0x01 , 0x80 },
581+ },
582+ {
583+ name : "-129" ,
584+ value : qdb .NewDecimalFromInt64 (- 129 , 0 ),
585+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0xFF , 0x7F },
586+ },
587+ {
588+ name : "-256 sign extension" ,
589+ value : qdb .NewDecimalFromInt64 (- 256 , 0 ),
590+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0xFF , 0x00 },
533591 },
534592 }
535593
536594 for _ , tc := range testCases {
537595 t .Run (tc .name , func (t * testing.T ) {
538596 buf := newTestBuffer ()
539- err := buf .Table (testTable ).DecimalColumn ("price" , tc .value ).At (time.Time {}, false )
597+
598+ err := buf .Table (testTable ).DecimalColumnScaled ("price" , tc .value ).At (time.Time {}, false )
540599 assert .NoError (t , err )
541- assert .Equal (t , tc .expected , buf .Messages ())
600+
601+ expected := append (append ([]byte {}, prefix ... ), tc .expectedBytes ... )
602+ expected = append (expected , '\n' )
603+ assert .Equal (t , expected , buf .Messages ())
604+ })
605+ }
606+ }
607+
608+ func TestDecimalColumnShopspring (t * testing.T ) {
609+ prefix := []byte (testTable + " price==" )
610+
611+ testCases := []struct {
612+ name string
613+ value fakeShopspringDecimal
614+ expectedBytes []byte
615+ }{
616+ {
617+ name : "negative exponent scales value" ,
618+ value : fakeShopspringDecimal {coeff : big .NewInt (12345 ), exp : - 2 },
619+ expectedBytes : []byte {0x17 , 0x02 , 0x02 , 0x30 , 0x39 },
620+ },
621+ {
622+ name : "positive exponent multiplies coefficient" ,
623+ value : fakeShopspringDecimal {coeff : big .NewInt (123 ), exp : 2 },
624+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0x30 , 0x0C },
625+ },
626+ {
627+ name : "positive value sign extension" ,
628+ value : fakeShopspringDecimal {coeff : big .NewInt (128 ), exp : 0 },
629+ expectedBytes : []byte {0x17 , 0x00 , 0x02 , 0x00 , 0x80 },
630+ },
631+ {
632+ name : "negative value sign extension" ,
633+ value : fakeShopspringDecimal {coeff : big .NewInt (- 12345 ), exp : - 3 },
634+ expectedBytes : []byte {0x17 , 0x03 , 0x02 , 0xCF , 0xC7 },
635+ },
636+ }
637+
638+ for _ , tc := range testCases {
639+ t .Run (tc .name , func (t * testing.T ) {
640+ buf := newTestBuffer ()
641+
642+ err := buf .Table (testTable ).DecimalColumnShopspring ("price" , tc .value ).At (time.Time {}, false )
643+ assert .NoError (t , err )
644+
645+ expected := append (append ([]byte {}, prefix ... ), tc .expectedBytes ... )
646+ expected = append (expected , '\n' )
647+ assert .Equal (t , expected , buf .Messages ())
542648 })
543649 }
544650}
@@ -561,7 +667,7 @@ func TestDecimalColumnStringValidation(t *testing.T) {
561667 for _ , tc := range testCases {
562668 t .Run (tc .name , func (t * testing.T ) {
563669 buf := newTestBuffer ()
564- err := buf .Table (testTable ).DecimalColumn ("price" , tc .value ).At (time.Time {}, false )
670+ err := buf .Table (testTable ).DecimalColumnString ("price" , tc .value ).At (time.Time {}, false )
565671 assert .NoError (t , err )
566672 expected := []byte (testTable + " price=" + tc .expected + "\n " )
567673 assert .Equal (t , expected , buf .Messages ())
@@ -585,7 +691,7 @@ func TestDecimalColumnStringValidation(t *testing.T) {
585691 for _ , tc := range testCases {
586692 t .Run (tc .name , func (t * testing.T ) {
587693 buf := newTestBuffer ()
588- err := buf .Table (testTable ).DecimalColumn ("price" , tc .value ).At (time.Time {}, false )
694+ err := buf .Table (testTable ).DecimalColumnString ("price" , tc .value ).At (time.Time {}, false )
589695 assert .Error (t , err )
590696 assert .Contains (t , err .Error (), "decimal" )
591697 assert .Empty (t , buf .Messages ())
@@ -598,30 +704,20 @@ func TestDecimalColumnErrors(t *testing.T) {
598704 t .Run ("invalid scale" , func (t * testing.T ) {
599705 buf := newTestBuffer ()
600706 dec := qdb .NewDecimalFromInt64 (1 , 100 )
601- err := buf .Table (testTable ).DecimalColumn ("price" , dec ).At (time.Time {}, false )
707+ err := buf .Table (testTable ).DecimalColumnScaled ("price" , dec ).At (time.Time {}, false )
602708 assert .ErrorContains (t , err , "decimal scale" )
603709 assert .Empty (t , buf .Messages ())
604710 })
605711
606712 t .Run ("overflow" , func (t * testing.T ) {
607- buf := newTestBuffer ()
608713 bigVal := new (big.Int ).Lsh (big .NewInt (1 ), 2100 )
609- dec := qdb .NewDecimal (bigVal , 0 )
610- err := buf .Table (testTable ).DecimalColumn ("price" , dec ).At (time.Time {}, false )
611- assert .ErrorContains (t , err , "exceeds 127-bytes limit" )
612- assert .Empty (t , buf .Messages ())
613- })
614-
615- t .Run ("unsupported type" , func (t * testing.T ) {
616- buf := newTestBuffer ()
617- err := buf .Table (testTable ).DecimalColumn ("price" , struct {}{}).At (time.Time {}, false )
618- assert .ErrorContains (t , err , "unsupported decimal column value type" )
619- assert .Empty (t , buf .Messages ())
714+ _ , err := qdb .NewDecimal (bigVal , 0 )
715+ assert .ErrorContains (t , err , "exceeds 32 bytes" )
620716 })
621717
622718 t .Run ("no column" , func (t * testing.T ) {
623719 buf := newTestBuffer ()
624- err := buf .Table (testTable ).DecimalColumn ("price" , qdb . NullDecimal () ).At (time.Time {}, false )
720+ err := buf .Table (testTable ).DecimalColumnShopspring ("price" , nil ).At (time.Time {}, false )
625721 assert .ErrorContains (t , err , "no symbols or columns were provided: invalid message" )
626722 assert .Empty (t , buf .Messages ())
627723 })
0 commit comments