github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/quote.go (about) 1 package sqlite3 2 3 import ( 4 "bytes" 5 "math" 6 "strconv" 7 "strings" 8 "time" 9 "unsafe" 10 11 "github.com/ncruces/go-sqlite3/internal/util" 12 ) 13 14 // Quote escapes and quotes a value 15 // making it safe to embed in SQL text. 16 func Quote(value any) string { 17 switch v := value.(type) { 18 case nil: 19 return "NULL" 20 case bool: 21 if v { 22 return "1" 23 } else { 24 return "0" 25 } 26 27 case int: 28 return strconv.Itoa(v) 29 case int64: 30 return strconv.FormatInt(v, 10) 31 case float64: 32 switch { 33 case math.IsNaN(v): 34 return "NULL" 35 case math.IsInf(v, 1): 36 return "9.0e999" 37 case math.IsInf(v, -1): 38 return "-9.0e999" 39 } 40 return strconv.FormatFloat(v, 'g', -1, 64) 41 case time.Time: 42 return "'" + v.Format(time.RFC3339Nano) + "'" 43 44 case string: 45 if strings.IndexByte(v, 0) >= 0 { 46 break 47 } 48 49 buf := make([]byte, 2+len(v)+strings.Count(v, "'")) 50 buf[0] = '\'' 51 i := 1 52 for _, b := range []byte(v) { 53 if b == '\'' { 54 buf[i] = b 55 i += 1 56 } 57 buf[i] = b 58 i += 1 59 } 60 buf[i] = '\'' 61 return unsafe.String(&buf[0], len(buf)) 62 63 case []byte: 64 buf := make([]byte, 3+2*len(v)) 65 buf[0] = 'x' 66 buf[1] = '\'' 67 i := 2 68 for _, b := range v { 69 const hex = "0123456789ABCDEF" 70 buf[i+0] = hex[b/16] 71 buf[i+1] = hex[b%16] 72 i += 2 73 } 74 buf[i] = '\'' 75 return unsafe.String(&buf[0], len(buf)) 76 77 case ZeroBlob: 78 if v > ZeroBlob(1e9-3)/2 { 79 break 80 } 81 82 buf := bytes.Repeat([]byte("0"), int(3+2*int64(v))) 83 buf[0] = 'x' 84 buf[1] = '\'' 85 buf[len(buf)-1] = '\'' 86 return unsafe.String(&buf[0], len(buf)) 87 } 88 89 panic(util.ValueErr) 90 } 91 92 // QuoteIdentifier escapes and quotes an identifier 93 // making it safe to embed in SQL text. 94 func QuoteIdentifier(id string) string { 95 if strings.IndexByte(id, 0) >= 0 { 96 panic(util.ValueErr) 97 } 98 99 buf := make([]byte, 2+len(id)+strings.Count(id, `"`)) 100 buf[0] = '"' 101 i := 1 102 for _, b := range []byte(id) { 103 if b == '"' { 104 buf[i] = b 105 i += 1 106 } 107 buf[i] = b 108 i += 1 109 } 110 buf[i] = '"' 111 return unsafe.String(&buf[0], len(buf)) 112 }