@@ -2,7 +2,7 @@ import { SqlParameter } from "aws-sdk/clients/rdsdataservice";
22import { MysqlQueryCompiler , PostgresQueryCompiler } from "kysely" ;
33
44export class PostgresDataApiQueryCompiler extends PostgresQueryCompiler {
5- protected override appendValue ( value : any ) {
5+ protected override appendValue ( value : unknown ) {
66 const name = this . numParameters ;
77 this . append ( this . getCurrentParameterPlaceholder ( ) ) ;
88 this . addParameter ( {
@@ -17,7 +17,7 @@ export class PostgresDataApiQueryCompiler extends PostgresQueryCompiler {
1717}
1818
1919export class MysqlDataApiQueryCompiler extends MysqlQueryCompiler {
20- protected override appendValue ( value : any ) {
20+ protected override appendValue ( value : unknown ) {
2121 const name = this . numParameters ;
2222 this . append ( this . getCurrentParameterPlaceholder ( ) ) ;
2323 this . addParameter ( {
@@ -31,74 +31,105 @@ export class MysqlDataApiQueryCompiler extends MysqlQueryCompiler {
3131 }
3232}
3333
34- function serialize ( value : any ) : SqlParameter {
35- if ( value == null ) return { value : { isNull : true } } ;
34+ function serialize ( value : unknown ) : Pick < SqlParameter , "typeHint" | "value" > {
3635 switch ( typeof value ) {
37- case "number" :
38- if ( Number . isInteger ( value ) )
39- return {
40- value : {
41- longValue : value ,
42- } ,
43- } ;
44- else
45- return {
46- value : {
47- doubleValue : value ,
48- }
49- } ;
50- case "bigint" :
36+ case "bigint" :
37+ return { value : { doubleValue : Number ( value ) } } ;
38+ case "boolean" :
39+ return { value : { booleanValue : value } } ;
40+ case "number" :
41+ if ( Number . isInteger ( value ) )
42+ return { value : { longValue : value } } ;
43+ else
44+ return { value : { doubleValue : value } } ;
45+ case "object" :
46+ if ( value == null )
47+ return { value : { isNull : true } } ;
48+ else if ( Buffer . isBuffer ( value ) )
49+ return { value : { blobValue : value } } ;
50+ else if ( value instanceof Date )
5151 return {
52- value : {
53- doubleValue : Number ( value ) ,
54- }
52+ typeHint : "TIMESTAMP" ,
53+ value : { stringValue : fixISOString ( value . toISOString ( ) ) } ,
5554 } ;
56- case "string" :
57- return {
58- value : {
59- stringValue : value ,
60- }
61- } ;
62- case "boolean" :
63- return {
64- value : {
65- booleanValue : value ,
66- }
67- } ;
68- case "object" :
69- if ( Buffer . isBuffer ( value ) )
70- return {
71- value : {
72- blobValue : value ,
73- }
74- } ;
55+ else if ( ( value as RSU ) ?. value && isValueObject ( ( value as RSU ) . value as RSU ) ) {
56+ if (
57+ ( value as RSU ) . typeHint && ( ( value as RSU ) . value as RSU ) . stringValue
58+ && typeof ( ( value as RSU ) . value as RSU ) . stringValue === "string"
59+ )
60+ ( ( value as RSU ) . value as RSU ) . stringValue = fixStringValue (
61+ ( value as RSS ) . typeHint ,
62+ ( ( value as RSU ) . value as RSS ) . stringValue ,
63+ ) ;
64+ return value ;
65+ }
66+ else
67+ break ;
68+ case "string" :
69+ return {
70+ value : { stringValue : value } ,
71+ } ;
72+ }
7573
76- if ( Array . isArray ( value ) ) {
77- return {
78- value : {
79- arrayValue : {
80- stringValues : value ,
81- }
82- }
83- }
84- }
74+ throw new QueryCompilerError ( "Could not serialize value" ) ;
75+ }
8576
86- if ( value instanceof Date )
87- return {
88- typeHint : "TIMESTAMP" ,
89- value : { stringValue : serializeDate ( value ) } ,
90- }
77+ function fixStringValue ( typeHint : SqlParameter [ "typeHint" ] , value : string ) {
78+ switch ( typeHint ) {
79+ case "DATE" :
80+ return parseToISOString ( value ) . slice ( 0 , 10 ) ;
81+ case "TIME" :
82+ if ( value . match ( / ^ \d { 4 } - \d { 2 } - \d { 2 } / ) ) {
83+ return parseToISOString ( value ) . slice ( 11 , 23 ) ;
84+ }
85+ return fixTimeString ( value ) ;
86+ case "TIMESTAMP" :
87+ return fixISOString ( parseToISOString ( value ) ) ;
88+ }
89+ return value ;
90+ }
9191
92- return {
93- value : {
94- stringValue : JSON . stringify ( value ) ,
95- }
96- }
92+ function fixTimeString ( s : string ) {
93+ const elements = ( s || "00:00:00" ) . split ( ":" ) ;
94+ while ( elements . length < 3 ) {
95+ elements . push ( "00" ) ;
9796 }
97+ return elements . join ( ":" ) . slice ( 0 , 12 ) ;
98+ }
99+
100+ function fixISOString ( s : string ) {
101+ return s . replace ( "T" , " " ) . slice ( 0 , 23 ) ;
102+ }
98103
99- throw new Error ( `Unsupported type: ${ value } ` ) ;
104+ function parseToISOString ( s : string ) {
105+ return new Date ( Date . parse ( s ) ) . toISOString ( ) ;
100106}
101107
102- function serializeDate ( input : Date ) {
103- return input . toISOString ( ) . replace ( "T" , " " ) . substring ( 0 , 23 ) ;
108+ function isValueObject ( value : Record < string , unknown > ) {
109+ for ( const key of primitiveKeys ) {
110+ if ( value [ key ] ) {
111+ return true ;
112+ }
113+ }
114+ if ( value . arrayValue ) {
115+ for ( const key of arrayKeys ) {
116+ if ( ( value . arrayValue as Record < string , unknown > ) ?. [ key ] ) {
117+ return true ;
118+ }
119+ }
120+ }
121+ return false ;
104122}
123+
124+ class QueryCompilerError extends Error {
125+ constructor ( message : string ) {
126+ super ( message ) ;
127+ this . name = QueryCompilerError . name ;
128+ }
129+ }
130+
131+ const arrayKeys = [ "booleanValues" , "doubleValues" , "longValues" , "stringValues" ] ;
132+ const primitiveKeys = [ "blobValue" , "booleanValue" , "doubleValue" , "isNull" , "longValue" , "stringValue" ] ;
133+
134+ type RSS = Record < string , string > ;
135+ type RSU = Record < string , unknown > ;
0 commit comments