Skip to content

Instantly share code, notes, and snippets.

@maxhawkins
Created August 2, 2021 20:05
Show Gist options
  • Save maxhawkins/f162eaacddabbe380c7fb75791d85a56 to your computer and use it in GitHub Desktop.
Save maxhawkins/f162eaacddabbe380c7fb75791d85a56 to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"fmt"
"log"
"unsafe"
"modernc.org/libc"
"modernc.org/libc/sys/types"
sqlite3 "modernc.org/sqlite/lib"
)
func main() {
flag.Parse()
if flag.NArg() == 0 {
log.Fatal(`usage: parse "<sql string>"`)
}
sql := flag.Arg(0)
err := Parse(sql)
if err == nil {
fmt.Println("valid sql")
} else {
log.Fatal(err)
}
}
func Parse(sql string) error {
tls := libc.NewTLS()
csql, err := libc.CString(sql)
if err != nil {
return err
}
filename, err := libc.CString(":memory:")
if err != nil {
return err
}
ptrSize := unsafe.Sizeof(uintptr(0))
dbP := libc.Xmalloc(tls, types.Size_t(ptrSize))
defer func() {
if dbP != 0 {
libc.Xfree(tls, dbP)
}
}()
db := (*sqlite3.Sqlite3)(unsafe.Pointer(dbP))
defer sqlite3.Xsqlite3_close_v2(tls, dbP)
result := sqlite3.Xsqlite3_open_v2(tls, filename, dbP, sqlite3.SQLITE_OPEN_READWRITE, 0)
if err := sqliteErr(tls, result); err != nil {
return fmt.Errorf("open failed: %w", err)
}
db.FaLimit = [12]int32{
sqlite3.SQLITE_MAX_LENGTH,
sqlite3.SQLITE_MAX_SQL_LENGTH,
sqlite3.SQLITE_MAX_COLUMN,
sqlite3.SQLITE_MAX_EXPR_DEPTH,
sqlite3.SQLITE_MAX_COMPOUND_SELECT,
sqlite3.SQLITE_MAX_VDBE_OP,
sqlite3.SQLITE_MAX_FUNCTION_ARG,
sqlite3.SQLITE_MAX_ATTACHED,
sqlite3.SQLITE_MAX_LIKE_PATTERN_LENGTH,
sqlite3.SQLITE_MAX_VARIABLE_NUMBER, // IMP: R-38091-32352
sqlite3.SQLITE_MAX_TRIGGER_DEPTH,
sqlite3.SQLITE_MAX_WORKER_THREADS,
}
parse := sqlite3.Parse{
Fdb: dbP,
}
parseP := uintptr(unsafe.Pointer(&parse))
errMsgP := libc.Xmalloc(tls, types.Size_t(ptrSize))
defer func() {
if errMsgP != 0 {
libc.Xfree(tls, errMsgP)
}
}()
sqlite3.Xsqlite3RunParser(tls, parseP, csql, errMsgP)
errMsg := *(*uintptr)(unsafe.Pointer(errMsgP))
if errMsg != 0 {
return fmt.Errorf("parse error: %s", libc.GoString(errMsg))
}
return nil
}
func sqliteErr(tls *libc.TLS, rc int32) error {
if rc == sqlite3.SQLITE_OK {
return nil
}
cstr := sqlite3.Xsqlite3ErrStr(tls, rc)
return fmt.Errorf(libc.GoString(cstr))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment