Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support experimental access to ast #108

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup TinyGo
uses: acifani/setup-tinygo@v1
with:
tinygo-version: '0.27.0'
tinygo-version: '0.28.1'

- name: Version 👍
id: version-bump
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
- name: Setup 🐹
uses: acifani/setup-tinygo@v1
with:
tinygo-version: 0.27.0
tinygo-version: 0.28.1

- name: Install 🔧
run: npm install
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.vscode
.vscode
.DS_Store
diagrams*
20 changes: 19 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,22 @@ generate:
# requires java
generate-diagrams:
go run ebnf/main.go grammar.y | java -jar rr/rr.war -suppressebnf -color:#FFFFFF -out:diagrams.xhtml -
.PHONY: generate-diagrams
.PHONY: generate-diagrams


types:
struct2ts --interface --no-helpers \
sqlparser.CreateTable \
sqlparser.ColumnConstraintPrimaryKey \
sqlparser.ColumnConstraintNotNull \
sqlparser.ColumnConstraintUnique \
sqlparser.ColumnConstraintCheck \
sqlparser.ColumnConstraintDefault \
sqlparser.ColumnConstraintGenerated \
sqlparser.TableConstraintPrimaryKey \
sqlparser.TableConstraintUnique \
sqlparser.TableConstraintCheck \
> js/go-types.d.ts
echo "export type ColumnConstraint = ColumnConstraintPrimaryKey | ColumnConstraintNotNull | ColumnConstraintUnique | ColumnConstraintCheck | ColumnConstraintDefault | ColumnConstraintGenerated;" >> js/go-types.d.ts
echo "export type TableConstraint = TableConstraintPrimaryKey | TableConstraintUnique | TableConstraintCheck;" >> js/go-types.d.ts
.PHONY: types
89 changes: 80 additions & 9 deletions cmd/wasm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package main

import (
"encoding/json"
"regexp"
"strings"
"syscall/js"
Expand Down Expand Up @@ -30,6 +31,22 @@ type EnclosingType struct {
close string
}

var (
Console js.Value
JSON js.Value
Error js.Value
TypeError js.Value
Promise js.Value
)

func init() {
Console = js.Global().Get("console")
TypeError = js.Global().Get("TypeError")
Error = js.Global().Get("Error")
Promise = js.Global().Get("Promise")
JSON = js.Global().Get("JSON")
}

func getEnclosures() []EnclosingType {
return []EnclosingType{
{open: "`", close: "`"},
Expand Down Expand Up @@ -65,9 +82,65 @@ func UpdateTableNames(node sqlparser.Node, nameMapper func(string) (string, bool
return node, nil
}

func createStatementFromObject(this js.Value, args []js.Value) interface{} {
if len(args) < 1 {
return Promise.Call("reject", Error.New("missing required argument: ast"))
}
astObject := args[0]
if astObject.Type() != js.TypeObject {
return Promise.Call("reject", TypeError.New("invalid argument: object expected"))
}
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
resolve := args[0]
reject := args[1]
go func() interface{} {
jsonString := JSON.Call("stringify", astObject).String()
var create sqlparser.CreateTable
if err := json.Unmarshal([]byte(jsonString), &create); err != nil {
return reject.Invoke(Error.New("Error unmarshaling into struct: " + err.Error()))
}
var response interface{} = create.String()
return resolve.Invoke(js.ValueOf(response))
}()
return nil
})
return Promise.New(handler)
}

func createStatementToObject(this js.Value, args []js.Value) interface{} {
if len(args) < 1 {
return Promise.Call("reject", Error.New("missing required argument: statement"))
}
statement := args[0].String()
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
resolve := args[0]
reject := args[1]
go func() interface{} {
ast, err := sqlparser.Parse(statement)
if err != nil {
return reject.Invoke(Error.New("error parsing statement: " + err.Error()))
}
if len(ast.Statements) == 0 {
return reject.Invoke(Error.New("error parsing statement: empty string"))
}
if len(ast.Statements) > 1 {
return reject.Invoke(Error.New("expected single create statement"))
}
create, ok := ast.Statements[0].(sqlparser.CreateTableStatement)
if !ok {
return reject.Invoke(Error.New("expected single create statement"))
}
b, _ := json.Marshal(&create)
var response map[string]interface{}
_ = json.Unmarshal(b, &response)
return resolve.Invoke(js.ValueOf(response))
}()
return nil
})
return Promise.New(handler)
}

func validateTableName(this js.Value, args []js.Value) interface{} {
Error := js.Global().Get("Error")
Promise := js.Global().Get("Promise")
if len(args) < 1 {
return Promise.Call("reject", Error.New("missing required argument: tableName"))
}
Expand Down Expand Up @@ -108,8 +181,6 @@ func validateTableName(this js.Value, args []js.Value) interface{} {
}

func getUniqueTableNames(this js.Value, args []js.Value) interface{} {
Error := js.Global().Get("Error")
Promise := js.Global().Get("Promise")
if len(args) < 1 {
return Promise.Call("reject", Error.New("missing required argument: statement"))
}
Expand All @@ -135,8 +206,6 @@ func getUniqueTableNames(this js.Value, args []js.Value) interface{} {
}

func normalize(this js.Value, args []js.Value) interface{} {
Error := js.Global().Get("Error")
Promise := js.Global().Get("Promise")
if len(args) < 1 {
return Promise.Call("reject", Error.New("missing required argument: statement"))
}
Expand Down Expand Up @@ -236,9 +305,11 @@ func getEnclosedName(name string) (string, EnclosingType, bool) {
func main() {
// Outer object is exported globally and contains these keys
js.Global().Set(GLOBAL_NAME, js.ValueOf(map[string]interface{}{
"normalize": js.FuncOf(normalize),
"validateTableName": js.FuncOf(validateTableName),
"getUniqueTableNames": js.FuncOf(getUniqueTableNames),
"normalize": js.FuncOf(normalize),
"validateTableName": js.FuncOf(validateTableName),
"getUniqueTableNames": js.FuncOf(getUniqueTableNames),
"createStatementFromObject": js.FuncOf(createStatementFromObject),
"createStatementToObject": js.FuncOf(createStatementToObject),
}))

<-make(chan bool)
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ require (
)

require (
github.com/OneOfOne/struct2ts v1.0.6 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
github.com/OneOfOne/struct2ts v1.0.6 h1:kLFEisG4K43k1thctN9BNZP4Y/RxRbO8tPyi3G5qPl4=
github.com/OneOfOne/struct2ts v1.0.6/go.mod h1:GbIenlFXroS2wRhpYXHEq7y7HWsY3SFBIKxkqzbnAsU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -14,12 +22,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.0.0-20190213135902-6bedcd10978a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3 changes: 2 additions & 1 deletion js/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"ecmaVersion": 12
},
"rules": {
"import/order": "warn"
"import/order": "warn",
"no-use-before-define": "off"
}
}
7 changes: 5 additions & 2 deletions js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,20 @@ To get started clone this repo.

## Install tinygo

We require tinygo version `0.28.1` or greater

```
brew tap tinygo-org/tools
brew install tinygo
```

## Fetch wasm helpers

Use the corresponding tinygo version
Use the corresponding tinygo version.
**Warning** this will overwrite any existing `wasm_exec.js` file, which has Tableland specific modifications.

```
wget https://raw.githubusercontent.com/tinygo-org/tinygo/v0.23.0/targets/wasm_exec.js
wget https://raw.githubusercontent.com/tinygo-org/tinygo/v0.28.1/targets/wasm_exec.js
```

## Build with tinygo
Expand Down
94 changes: 94 additions & 0 deletions js/go-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// this file was automatically generated, DO NOT EDIT
// structs
// struct2ts:github.com/tablelandnetwork/sqlparser.Table
export interface Table {
Name: string;
IsTarget: boolean;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.Column
export interface Column {
Name: string;
TableRef: Table | null;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnDef
export interface ColumnDef {
Column: Column | null;
Type: string;
Constraints: ColumnConstraint[] | null;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.CreateTable
export interface CreateTable {
Table: Table | null;
ColumnsDef: ColumnDef[] | null;
Constraints: TableConstraint[] | null;
StrictMode: boolean;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintPrimaryKey
export interface ColumnConstraintPrimaryKey {
Name: string;
Order: string;
AutoIncrement: boolean;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintNotNull
export interface ColumnConstraintNotNull {
Name: string;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintUnique
export interface ColumnConstraintUnique {
Name: string;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintCheck
export interface ColumnConstraintCheck {
Name: string;
Expr: any;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintDefault
export interface ColumnConstraintDefault {
Name: string;
Expr: any;
Parenthesis: boolean;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.ColumnConstraintGenerated
export interface ColumnConstraintGenerated {
Name: string;
Expr: any;
GeneratedAlways: boolean;
IsStored: boolean;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.IndexedColumn
export interface IndexedColumn {
Column: Column | null;
CollationName: string;
Order: string;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.TableConstraintPrimaryKey
export interface TableConstraintPrimaryKey {
Name: string;
Columns: IndexedColumn[] | null;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.TableConstraintUnique
export interface TableConstraintUnique {
Name: string;
Columns: Column[] | null;
}

// struct2ts:github.com/tablelandnetwork/sqlparser.TableConstraintCheck
export interface TableConstraintCheck {
Name: string;
Expr: any;
}

export type ColumnConstraint = ColumnConstraintPrimaryKey | ColumnConstraintNotNull | ColumnConstraintUnique | ColumnConstraintCheck | ColumnConstraintDefault | ColumnConstraintGenerated;
export type TableConstraint = TableConstraintPrimaryKey | TableConstraintUnique | TableConstraintCheck;
7 changes: 4 additions & 3 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// @ts-check
/* global Go */

// Need to optionally shim `crypto.getRandomValues` and esbuild needs the
// import to come before importing `wasm_exec.js`
import "./polyfills/crypto.js";

// @ts-check
/* global Go */
import "./wasm_exec.js";
// @ts-ignore
import mainWasm from "./main.wasm";

// @ts-ignore
Expand Down
Binary file modified js/main.wasm
Binary file not shown.
5 changes: 3 additions & 2 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@
"wasm:go": "tinygo build -gc=leaking -no-debug -o main.wasm -target wasm ../cmd/wasm/main.go",
"wasm:opt": "npx wasm-opt -O main.wasm -o main.wasm",
"fixup": "echo '{\n \"type\": \"commonjs\"\n}' > cjs/package.json",
"build:go-types": "cd ..; make types; cd js",
"build:cjs": "node ./cjs-build.js && npm run fixup",
"build:esm": "node ./esm-build.js",
"build:wasm": "npm run wasm:go && npm run wasm:opt",
"build": "npm run build:wasm && npm run build:cjs && npm run build:esm",
"clean": "rm -rf main.wasm cjs",
"build": "npm run build:wasm && npm run build:go-types && npm run build:cjs && npm run build:esm",
"clean": "rm -rf main.wasm cjs go-types.d.ts",
"prepublishOnly": "npm run build"
},
"tsd": {
Expand Down
Loading