@@ -288,6 +288,18 @@ func (h *DoltgresHandler) InitSessionParameterDefault(ctx context.Context, c *my
288288// convertBindParameters handles the conversion from bind parameters to variable values.
289289func (h * DoltgresHandler ) convertBindParameters (ctx * sql.Context , types []uint32 , formatCodes []int16 , values [][]byte ) (map [string ]sqlparser.Expr , error ) {
290290 bindings := make (map [string ]sqlparser.Expr , len (values ))
291+ // It's valid to send just one format code that should be used by all values, so we extend the slice in that case
292+ if len (formatCodes ) > 0 && len (formatCodes ) < len (values ) {
293+ if len (formatCodes ) > 1 {
294+ return nil , errors .Errorf (`format codes have length "%d" but values have length "%d"` , len (formatCodes ), len (values ))
295+ }
296+ formatCode := formatCodes [0 ]
297+ formatCodes = make ([]int16 , len (values ))
298+ formatCodes [0 ] = formatCode
299+ for i := 1 ; i < len (values ); i ++ {
300+ formatCodes [i ] = formatCode
301+ }
302+ }
291303 for i := range values {
292304 formatCode := int16 (0 )
293305 if formatCodes != nil {
@@ -542,7 +554,8 @@ func schemaToFieldDescriptions(ctx *sql.Context, s sql.Schema, isPrepared bool)
542554 typmod = doltgresType .GetAttTypMod () // pg_attribute.atttypmod
543555 if isPrepared {
544556 switch doltgresType .ID {
545- case pgtypes .Bytea .ID , pgtypes .Int16 .ID , pgtypes .Int32 .ID , pgtypes .Int64 .ID , pgtypes .Uuid .ID :
557+ case pgtypes .Bytea .ID , pgtypes .Date .ID , pgtypes .Int16 .ID , pgtypes .Int32 .ID , pgtypes .Int64 .ID ,
558+ pgtypes .Timestamp .ID , pgtypes .TimestampTZ .ID , pgtypes .Uuid .ID :
546559 formatCode = 1
547560 }
548561 }
@@ -805,6 +818,22 @@ func rowToBytes(ctx *sql.Context, s sql.Schema, row sql.Row, isExecute bool) ([]
805818 binary .BigEndian .PutUint16 (buf , uint16 (v .(int16 )))
806819 o [i ] = buf
807820 continue
821+ case pgtypes .Timestamp .ID , pgtypes .TimestampTZ .ID :
822+ postgresEpoch := time .UnixMilli (946684800000 ).UTC () // Jan 1, 2000 @ Midnight
823+ deltaInMicroseconds := v .(time.Time ).UTC ().UnixMicro () - postgresEpoch .UnixMicro ()
824+ buf := make ([]byte , 8 )
825+ binary .BigEndian .PutUint64 (buf , uint64 (deltaInMicroseconds ))
826+ o [i ] = buf
827+ continue
828+ case pgtypes .Date .ID :
829+ postgresEpoch := time .UnixMilli (946684800000 ).UTC () // Jan 1, 2000 @ Midnight
830+ deltaInMilliseconds := v .(time.Time ).UTC ().UnixMilli () - postgresEpoch .UnixMilli ()
831+ buf := make ([]byte , 4 )
832+ const millisecondsPerDay = 86400000
833+ days := deltaInMilliseconds / millisecondsPerDay
834+ binary .BigEndian .PutUint32 (buf , uint32 (days ))
835+ o [i ] = buf
836+ continue
808837 case pgtypes .Uuid .ID :
809838 buf , err := v .(uuid.UUID ).MarshalBinary ()
810839 if err != nil {
0 commit comments