44package sqlbuilder
55
66import (
7+ "database/sql/driver"
78 "fmt"
9+ "reflect"
810 "strconv"
911 "time"
1012 "unicode"
@@ -389,83 +391,22 @@ func cqlInterpolate(query string, args ...interface{}) (string, error) {
389391 return mysqlLikeInterpolate (CQL , query , args ... )
390392}
391393
394+ func clickhouseInterpolate (query string , args ... interface {}) (string , error ) {
395+ return mysqlLikeInterpolate (ClickHouse , query , args ... )
396+ }
397+
392398func encodeValue (buf []byte , arg interface {}, flavor Flavor ) ([]byte , error ) {
393399 switch v := arg .(type ) {
394400 case nil :
395401 buf = append (buf , "NULL" ... )
396402
397- case bool :
398- if v {
399- buf = append ( buf , "TRUE" ... )
403+ case driver. Valuer :
404+ if val , err := v . Value (); err != nil {
405+ return nil , err
400406 } else {
401- buf = append (buf , "FALSE" ... )
407+ return encodeValue (buf , val , flavor )
402408 }
403409
404- case int :
405- buf = strconv .AppendInt (buf , int64 (v ), 10 )
406-
407- case int8 :
408- buf = strconv .AppendInt (buf , int64 (v ), 10 )
409-
410- case int16 :
411- buf = strconv .AppendInt (buf , int64 (v ), 10 )
412-
413- case int32 :
414- buf = strconv .AppendInt (buf , int64 (v ), 10 )
415-
416- case int64 :
417- buf = strconv .AppendInt (buf , v , 10 )
418-
419- case uint :
420- buf = strconv .AppendUint (buf , uint64 (v ), 10 )
421-
422- case uint8 :
423- buf = strconv .AppendUint (buf , uint64 (v ), 10 )
424-
425- case uint16 :
426- buf = strconv .AppendUint (buf , uint64 (v ), 10 )
427-
428- case uint32 :
429- buf = strconv .AppendUint (buf , uint64 (v ), 10 )
430-
431- case uint64 :
432- buf = strconv .AppendUint (buf , v , 10 )
433-
434- case float32 :
435- buf = strconv .AppendFloat (buf , float64 (v ), 'g' , - 1 , 32 )
436-
437- case float64 :
438- buf = strconv .AppendFloat (buf , v , 'g' , - 1 , 64 )
439-
440- case []byte :
441- if v == nil {
442- buf = append (buf , "NULL" ... )
443- break
444- }
445-
446- switch flavor {
447- case MySQL :
448- buf = append (buf , "_binary" ... )
449- buf = quoteStringValue (buf , * (* string )(unsafe .Pointer (& v )), flavor )
450-
451- case PostgreSQL :
452- buf = append (buf , "E'\\ \\ x" ... )
453- buf = appendHex (buf , v )
454- buf = append (buf , "'::bytea" ... )
455-
456- case SQLite :
457- buf = append (buf , "X'" ... )
458- buf = appendHex (buf , v )
459- buf = append (buf , '\'' )
460-
461- case SQLServer , CQL :
462- buf = append (buf , "0x" ... )
463- buf = appendHex (buf , v )
464- }
465-
466- case string :
467- buf = quoteStringValue (buf , v , flavor )
468-
469410 case time.Time :
470411 if v .IsZero () {
471412 buf = append (buf , "'0000-00-00'" ... )
@@ -492,6 +433,9 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
492433
493434 case CQL :
494435 buf = append (buf , v .Format ("2006-01-02 15:04:05.999999Z0700" )... )
436+
437+ case ClickHouse :
438+ buf = append (buf , v .Format ("2006-01-02 15:04:05.999999" )... )
495439 }
496440
497441 buf = append (buf , '\'' )
@@ -500,7 +444,108 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
500444 buf = quoteStringValue (buf , v .String (), flavor )
501445
502446 default :
503- return nil , ErrInterpolateUnsupportedArgs
447+ primative := reflect .ValueOf (arg )
448+
449+ switch k := primative .Kind (); k {
450+ case reflect .Bool :
451+ if primative .Bool () {
452+ buf = append (buf , "TRUE" ... )
453+ } else {
454+ buf = append (buf , "FALSE" ... )
455+ }
456+
457+ case reflect .Int :
458+ buf = strconv .AppendInt (buf , primative .Int (), 10 )
459+
460+ case reflect .Int8 :
461+ buf = strconv .AppendInt (buf , primative .Int (), 10 )
462+
463+ case reflect .Int16 :
464+ buf = strconv .AppendInt (buf , primative .Int (), 10 )
465+
466+ case reflect .Int32 :
467+ buf = strconv .AppendInt (buf , primative .Int (), 10 )
468+
469+ case reflect .Int64 :
470+ buf = strconv .AppendInt (buf , primative .Int (), 10 )
471+
472+ case reflect .Uint :
473+ buf = strconv .AppendUint (buf , primative .Uint (), 10 )
474+
475+ case reflect .Uint8 :
476+ buf = strconv .AppendUint (buf , primative .Uint (), 10 )
477+
478+ case reflect .Uint16 :
479+ buf = strconv .AppendUint (buf , primative .Uint (), 10 )
480+
481+ case reflect .Uint32 :
482+ buf = strconv .AppendUint (buf , primative .Uint (), 10 )
483+
484+ case reflect .Uint64 :
485+ buf = strconv .AppendUint (buf , primative .Uint (), 10 )
486+
487+ case reflect .Float32 :
488+ buf = strconv .AppendFloat (buf , primative .Float (), 'g' , - 1 , 32 )
489+
490+ case reflect .Float64 :
491+ buf = strconv .AppendFloat (buf , primative .Float (), 'g' , - 1 , 64 )
492+
493+ case reflect .String :
494+ buf = quoteStringValue (buf , primative .String (), flavor )
495+
496+ case reflect .Slice , reflect .Array :
497+ if k == reflect .Slice && primative .IsNil () {
498+ buf = append (buf , "NULL" ... )
499+ break
500+ }
501+
502+ if elem := primative .Type ().Elem (); elem .Kind () != reflect .Uint8 {
503+ return nil , ErrInterpolateUnsupportedArgs
504+ }
505+
506+ var data []byte
507+
508+ // Bytes() will panic if primative is an array and cannot be addressed.
509+ // Copy all bytes to data as a fallback.
510+ if k == reflect .Array && ! primative .CanAddr () {
511+ l := primative .Len ()
512+ data = make ([]byte , l )
513+
514+ for i := 0 ; i < l ; i ++ {
515+ data [i ] = byte (primative .Index (i ).Uint ())
516+ }
517+ } else {
518+ data = primative .Bytes ()
519+ }
520+
521+ switch flavor {
522+ case MySQL :
523+ buf = append (buf , "_binary" ... )
524+ buf = quoteStringValue (buf , * (* string )(unsafe .Pointer (& data )), flavor )
525+
526+ case PostgreSQL :
527+ buf = append (buf , "E'\\ \\ x" ... )
528+ buf = appendHex (buf , data )
529+ buf = append (buf , "'::bytea" ... )
530+
531+ case SQLite :
532+ buf = append (buf , "X'" ... )
533+ buf = appendHex (buf , data )
534+ buf = append (buf , '\'' )
535+
536+ case SQLServer , CQL :
537+ buf = append (buf , "0x" ... )
538+ buf = appendHex (buf , data )
539+
540+ case ClickHouse :
541+ buf = append (buf , "unhex('" ... )
542+ buf = appendHex (buf , data )
543+ buf = append (buf , "')" ... )
544+ }
545+
546+ default :
547+ return nil , ErrInterpolateUnsupportedArgs
548+ }
504549 }
505550
506551 return buf , nil
0 commit comments