From d8a6511f3f3ae04a8563772f6831929cc8672696 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Wed, 30 Dec 2020 16:01:41 +0100 Subject: [PATCH] wip --- .circleci/config.yml | 61 +++++++++++ .gitignore | 2 +- fiddle.go | 46 ++++++++ pod/main.go | 244 +++++++++++++++++++++++++------------------ 4 files changed, 253 insertions(+), 100 deletions(-) create mode 100644 .circleci/config.yml create mode 100644 fiddle.go diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..9ab6a55 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,61 @@ +version: 2.1 + +jobs: + build: + docker: + - image: circleci/golang:1.15 + steps: + - checkout + - restore_cache: + keys: + - pod-babashka-sqlite3-{{ checksum "go.sum" }}-{{ checksum ".circleci/config.yml" }} + - run: + name: Build linux binary + command: go build -o linux-amd64/pod-babashka-sqlite3 main.go + - run: + name: Build mac binary + environment: + GOOS: darwin + GOARCH: amd64 + command: go build -o macos-amd64/pod-babashka-sqlite3 main.go + - run: + name: Build windows binary + environment: + GOOS: windows + GOARCH: amd64 + command: go build -o windows-amd64/pod-babashka-sqlite3.exe main.go + # - run: + # name: Install bb for test + # command: | + # mkdir bb + # bash <(curl -sL https://raw.githubusercontent.com/borkdude/babashka/master/install) \ + # --dir bb --download-dir bb + # - run: + # name: Run test + # command: cp linux-amd64/pod-babashka-fswatcher . && PATH=$PATH:bb script/test + - run: + name: Test fiddle + command: | + go run fiddle.go + - save_cache: + key: pod-babashka-sqlite3-{{ checksum "go.sum" }}-{{ checksum ".circleci/config.yml" }} + paths: + - "/go/pkg/mod" + # - run: + # name: Release + # command: | + # VERSION=$(cat resources/POD_BABASHKA_FSWATCHER_VERSION) + # mkdir release + + # zip -j "release/pod-babashka-fswatcher-$VERSION-linux-amd64.zip" linux-amd64/pod-babashka-fswatcher + # zip -j "release/pod-babashka-fswatcher-$VERSION-macos-amd64.zip" macos-amd64/pod-babashka-fswatcher + # zip -j "release/pod-babashka-fswatcher-$VERSION-windows-amd64.zip" windows-amd64/pod-babashka-fswatcher.exe + # - store_artifacts: + # path: release + # destination: release + +workflows: + version: 2 + ci: + jobs: + - build diff --git a/.gitignore b/.gitignore index 6bbb3ad..8f53525 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,5 @@ # Dependency directories (remove the comment below to include it) # vendor/ main -test-pod +fiddle pod-babashka-sqlite3 diff --git a/fiddle.go b/fiddle.go new file mode 100644 index 0000000..caf3984 --- /dev/null +++ b/fiddle.go @@ -0,0 +1,46 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/babashka/pod-babashka-sqlite3/babashka" + "github.com/babashka/pod-babashka-sqlite3/pod" + "log" +) + +func execQuery(query string, exec bool, args ...string) { + elts := len(args) + 1 + argsArray := make([]string, elts) + argsArray[0] = query + for i := range args { + argsArray[i+1] = args[i] + } + log.Printf("args: %q", argsArray) + q, err := json.Marshal(argsArray) + var theVar string + if exec { + theVar = "pod.babashka.sqlite3/execute!" + } else { + theVar = "pod.babashka.sqlite3/query!" + } + message := &babashka.Message{ + Op: "invoke", + Var: theVar, + Id: "123", + Args: fmt.Sprintf(`{"db":"/tmp/pod.db", + "query": %s}`, q)} + res, err := pod.ProcessMessage(message) + if err != nil { + log.Println("err", err) + } + log.Println("res", res) +} + +func main() { + execQuery("select sqlite_version()", false) + execQuery("select sqlite_source_id()", false) + execQuery("create table if not exists foo (col1 TEXT, col2 TEXT)", true) + execQuery("delete from foo", true) + execQuery("insert into foo values (?,?)", true, "1", "2") + execQuery("select * from foo", false) +} diff --git a/pod/main.go b/pod/main.go index e18d4fc..3e95ea4 100644 --- a/pod/main.go +++ b/pod/main.go @@ -1,120 +1,166 @@ package pod import ( - "database/sql" - "encoding/json" - "log" - _ "os" - "fmt" - "strings" - "github.com/babashka/pod-babashka-sqlite3/babashka" - _ "github.com/mattn/go-sqlite3" // Import go-sqlite3 library + "database/sql" + "encoding/json" + "fmt" + "github.com/babashka/pod-babashka-sqlite3/babashka" + _ "github.com/mattn/go-sqlite3" // Import go-sqlite3 library + "log" + "strings" ) -type Opts struct { - DelayMs uint64 `json:"delay-ms"` - Recursive bool `json:"recursive"` +type Query struct { + Database string `json:"db"` + Query []string `json:"query"` } -type Response struct { - Type string `json:"type"` - Path string `json:"path"` - Dest *string `json:"dest,omitempty"` - Error *string `json:"error,omitempty"` +type ExecResult struct { + RowsAffected int64 `json:"rows-affected"` + LastInsertedId int64 `json:"last-inserted-id"` } -type WatcherInfo struct { - WatcherId int `json:"watcher/id"` -} -func Jsonify(rows *sql.Rows) ([]string) { - columns, err := rows.Columns() - if err != nil { - panic(err.Error()) - } - - values := make([]interface{}, len(columns)) - - scanArgs := make([]interface{}, len(values)) - for i := range values { - scanArgs[i] = &values[i] - } - - c := 0 - results := make(map[string]interface{}) - data := []string{} - - for rows.Next() { - if c > 0 { - data = append(data, ",") - } - - err = rows.Scan(scanArgs...) - if err != nil { - panic(err.Error()) - } - - for i, value := range values { - results[columns[i]] = value - // switch value.(type) { - // case nil: - // results[columns[i]] = nil - - // case []byte: - // s := string(value.([]byte)) - // x, err := strconv.Atoi(s) - - // if err != nil { - // results[columns[i]] = s - // } else { - // results[columns[i]] = x - // } - - - // default: - // results[columns[i]] = value - // } - } - - b, _ := json.Marshal(results) - data = append(data, strings.TrimSpace(string(b))) - c++ - } - - return data +// type Response struct { +// Type string `json:"type"` +// Path string `json:"path"` +// Dest *string `json:"dest,omitempty"` +// Error *string `json:"error,omitempty"` +// } + +// type WatcherInfo struct { +// WatcherId int `json:"watcher/id"` +// } + +func JsonifyRows(rows *sql.Rows) []string { + columns, err := rows.Columns() + if err != nil { + panic(err.Error()) + } + + values := make([]interface{}, len(columns)) + + scanArgs := make([]interface{}, len(values)) + for i := range values { + scanArgs[i] = &values[i] + } + + c := 0 + results := make(map[string]interface{}) + data := []string{} + + for rows.Next() { + if c > 0 { + data = append(data, ",") + } + + err = rows.Scan(scanArgs...) + if err != nil { + panic(err.Error()) + } + + for i, value := range values { + results[columns[i]] = value + // switch value.(type) { + // case nil: + // results[columns[i]] = nil + + // case []byte: + // s := string(value.([]byte)) + // x, err := strconv.Atoi(s) + + // if err != nil { + // results[columns[i]] = s + // } else { + // results[columns[i]] = x + // } + + // default: + // results[columns[i]] = value + // } + } + + b, _ := json.Marshal(results) + data = append(data, strings.TrimSpace(string(b))) + c++ + } + + return data } +func JsonifyResult(result sql.Result) (string, error) { + rowsAffected, err := result.RowsAffected() + lastInsertedId, err := result.LastInsertId() + res := ExecResult{ + RowsAffected: rowsAffected, + LastInsertedId: lastInsertedId, + } + json, err := json.Marshal(res) + return string(json), err +} func ProcessMessage(message *babashka.Message) (interface{}, error) { - switch message.Op { - case "describe": - return &babashka.DescribeResponse{ - Format: "json", - Namespaces: []babashka.Namespace{ - { - Name: "pod.babashka.sqlite3", - Vars: []babashka.Var{ - { - Name: "execute!", - }, - }, - }, - }, - }, nil - case "invoke": - switch message.Var { + switch message.Op { + case "describe": + return &babashka.DescribeResponse{ + Format: "json", + Namespaces: []babashka.Namespace{ + { + Name: "pod.babashka.sqlite3", + Vars: []babashka.Var{ + { + Name: "execute!", + }, + }, + }, + }, + }, nil + case "invoke": + switch message.Var { case "pod.babashka.sqlite3/execute!": - args := []string{} - if err := json.Unmarshal([]byte(message.Args), &args); err != nil { + + var q Query + if err := json.Unmarshal([]byte(message.Args), &q); err != nil { + return nil, err + } + log.Printf("json args %q", q) + conn, _ := sql.Open("sqlite3", q.Database) + defer conn.Close() + args := make([]interface{}, len(q.Query) - 1) + for i := range q.Query[1:] { + args[i] = q.Query[i + 1] + } + res, err := conn.Exec(q.Query[0], args...) + if err != nil { + return nil, err + } + json, err := JsonifyResult(res) + log.Println("json", json) + return nil, nil + case "pod.babashka.sqlite3/query!": + var q Query + if err := json.Unmarshal([]byte(message.Args), &q); err != nil { + return nil, err + } + log.Printf("json args %q", q) + conn, _ := sql.Open("sqlite3", q.Database) + defer conn.Close() + args := make([]interface{}, len(q.Query) - 1) + for i := range q.Query[1:] { + args[i] = q.Query[i + 1] + } + res, err := conn.Query(q.Query[0], args...) + if err != nil { return nil, err } - log.Println("args", args) + json := JsonifyRows(res) + log.Println("json", json) return nil, nil default: - return nil, fmt.Errorf("Unknown var %s", message.Var) - } - default: - return nil, fmt.Errorf("Unknown op %s", message.Op) - } + return nil, fmt.Errorf("Unknown var %s", message.Var) + } + default: + return nil, fmt.Errorf("Unknown op %s", message.Op) + } }