From c841ff8626a8256eb001c76d2694c043834bd66b Mon Sep 17 00:00:00 2001 From: reshke Date: Mon, 24 Jul 2023 13:02:47 +0500 Subject: [PATCH] Enhance spqrparser (#242) * Enhance spqrparser * Fix tests * Fix tests * Add unit test * Enhance lexel-parser more * Fix kill client stmt * Fix * No lint gen file * Fix nolint * no lint yacc/console --------- Co-authored-by: denchick --- .github/workflows/linters.yaml | 2 +- Makefile | 2 +- pkg/clientinteractor/interactor.go | 2 +- yacc/console/Makefile | 7 + yacc/console/console_test.go | 70 --- yacc/console/{sql.go => gram.go} | 690 ++++++++++++------------- yacc/console/{sql.y => gram.y} | 158 ++---- yacc/console/lex.go | 779 ++++++++++++++++++++++++----- yacc/console/lex.rl | 105 ++++ yacc/console/lx_test.go | 69 +++ yacc/console/reserved_keyword.go | 84 ++-- yacc/console/util.go | 59 +++ yacc/console/yx_test.go | 243 +++++++++ 13 files changed, 1547 insertions(+), 723 deletions(-) create mode 100644 yacc/console/Makefile delete mode 100644 yacc/console/console_test.go rename yacc/console/{sql.go => gram.go} (62%) rename yacc/console/{sql.y => gram.y} (81%) create mode 100644 yacc/console/lex.rl create mode 100644 yacc/console/lx_test.go create mode 100644 yacc/console/util.go create mode 100644 yacc/console/yx_test.go diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml index 49b6f48db..a514a879a 100644 --- a/.github/workflows/linters.yaml +++ b/.github/workflows/linters.yaml @@ -23,7 +23,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: latest - args: --timeout=10m --out-format=colored-line-number + args: --timeout=10m --out-format=colored-line-number --skip-dirs=yacc/console goimports: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 9ade88619..83b141576 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ feature_test: build_images (cd test/feature; go test -timeout 150m) lint: - golangci-lint run --timeout=10m --out-format=colored-line-number + golangci-lint run --timeout=10m --out-format=colored-line-number --skip-dirs=yacc/console ####################### GENERATE ####################### diff --git a/pkg/clientinteractor/interactor.go b/pkg/clientinteractor/interactor.go index 4436a5bce..50fb43022 100644 --- a/pkg/clientinteractor/interactor.go +++ b/pkg/clientinteractor/interactor.go @@ -328,7 +328,7 @@ func MatchRow(row []string, nameToIndex map[string]int, condition spqrparser.Whe case spqrparser.WhereClauseEmpty: return true, nil case spqrparser.WhereClauseOp: - switch where.Op { + switch strings.ToLower(where.Op) { case "and": left, err := MatchRow(row, nameToIndex, where.Left) if err != nil { diff --git a/yacc/console/Makefile b/yacc/console/Makefile new file mode 100644 index 000000000..1bd14ffc9 --- /dev/null +++ b/yacc/console/Makefile @@ -0,0 +1,7 @@ +lexgen: + ragel -Z -G2 -o lex.go lex.rl + +yaccgen: + goyacc -o gram.go -p yy gram.y + +gen: lexgen yaccgen \ No newline at end of file diff --git a/yacc/console/console_test.go b/yacc/console/console_test.go deleted file mode 100644 index 70b7e9930..000000000 --- a/yacc/console/console_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package spqrparser_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - spqrparser "github.com/pg-sharding/spqr/yacc/console" -) - -func TestSimpleWhere(t *testing.T) { - assert := assert.New(t) - - stmt, err := spqrparser.Parse("SHOW clients where user = usr1;") - assert.NoError(err) - show, ok := stmt.(*spqrparser.Show) - assert.True(ok) - whereClause, ok := show.Where.(spqrparser.WhereClauseLeaf) - assert.True(ok) - assert.Equal(spqrparser.WhereClauseLeaf{ - Op: "=", - ColRef: spqrparser.ColumnRef{ColName: "user"}, - Value: "usr1", - }, whereClause) -} - -func TestNestedeWhere(t *testing.T) { - assert := assert.New(t) - - stmt, err := spqrparser.Parse("SHOW clients where user = usr1 or dbname = db1 and 1 = 1;") - assert.NoError(err) - show, ok := stmt.(*spqrparser.Show) - assert.True(ok) - whereClause, ok := show.Where.(spqrparser.WhereClauseOp) - assert.True(ok) - - expected := spqrparser.WhereClauseOp{ - Op: "or", - Left: spqrparser.WhereClauseLeaf{ - Op: "=", - ColRef: spqrparser.ColumnRef{ColName: "user"}, - Value: "usr1", - }, - Right: spqrparser.WhereClauseOp{ - Op: "and", - Left: spqrparser.WhereClauseLeaf{ - Op: "=", - ColRef: spqrparser.ColumnRef{ColName: "dbname"}, - Value: "db1", - }, - Right: spqrparser.WhereClauseLeaf{ - Op: "=", - ColRef: spqrparser.ColumnRef{ColName: "1"}, - Value: "1", - }, - }, - } - assert.Equal(expected, whereClause) -} - -func TestNoWhere(t *testing.T) { - assert := assert.New(t) - - stmt, err := spqrparser.Parse("SHOW clients;") - assert.NoError(err) - show, ok := stmt.(*spqrparser.Show) - assert.True(ok) - _, ok = show.Where.(spqrparser.WhereClauseEmpty) - assert.True(ok) -} diff --git a/yacc/console/sql.go b/yacc/console/gram.go similarity index 62% rename from yacc/console/sql.go rename to yacc/console/gram.go index e95d0f650..ecb5c75cc 100644 --- a/yacc/console/sql.go +++ b/yacc/console/gram.go @@ -1,15 +1,16 @@ -// Code generated by goyacc -o yacc/console/sql.go -p yy yacc/console/sql.y. DO NOT EDIT. +// Code generated by goyacc -o gram.go -p yy gram.y. DO NOT EDIT. -//line yacc/console/sql.y:3 +//line gram.y:3 package spqrparser import __yyfmt__ "fmt" -//line yacc/console/sql.y:3 +//line gram.y:3 import ( "crypto/rand" "encoding/hex" + "strings" ) func randomHex(n int) (string, error) { @@ -20,7 +21,7 @@ func randomHex(n int) (string, error) { return hex.EncodeToString(bytes), nil } -//line yacc/console/sql.y:22 +//line gram.y:23 type yySymType struct { yys int str string @@ -65,7 +66,7 @@ type yySymType struct { where WhereClauseNode } -const STRING = 57346 +const IDENT = 57346 const COMMAND = 57347 const SHOW = 57348 const KILL = 57349 @@ -73,61 +74,56 @@ const WHERE = 57350 const OR = 57351 const AND = 57352 const TEQ = 57353 -const TSEMICOLON = 57354 -const TOPENBR = 57355 -const TCLOSEBR = 57356 -const POOLS = 57357 -const STATS = 57358 -const LISTS = 57359 -const SERVERS = 57360 -const CLIENTS = 57361 -const DATABASES = 57362 -const BACKEND_CONNECTIONS = 57363 -const SHUTDOWN = 57364 -const LISTEN = 57365 -const REGISTER = 57366 -const UNREGISTER = 57367 -const ROUTER = 57368 -const ROUTE = 57369 -const CREATE = 57370 -const ADD = 57371 -const DROP = 57372 -const LOCK = 57373 -const UNLOCK = 57374 -const SPLIT = 57375 -const MOVE = 57376 -const COMPOSE = 57377 -const SHARDING = 57378 -const COLUMN = 57379 -const TABLE = 57380 -const HASH = 57381 -const FUNCTION = 57382 -const KEY = 57383 -const RANGE = 57384 -const DATASPACE = 57385 -const SHARDS = 57386 -const KEY_RANGES = 57387 -const ROUTERS = 57388 -const SHARD = 57389 -const HOST = 57390 -const SHARDING_RULES = 57391 -const RULE = 57392 -const COLUMNS = 57393 -const VERSION = 57394 -const BY = 57395 -const FROM = 57396 -const TO = 57397 -const WITH = 57398 -const UNITE = 57399 -const ALL = 57400 -const ADDRESS = 57401 -const CLIENT = 57402 +const SCONST = 57354 +const TSEMICOLON = 57355 +const TOPENBR = 57356 +const TCLOSEBR = 57357 +const SHUTDOWN = 57358 +const LISTEN = 57359 +const REGISTER = 57360 +const UNREGISTER = 57361 +const ROUTER = 57362 +const ROUTE = 57363 +const CREATE = 57364 +const ADD = 57365 +const DROP = 57366 +const LOCK = 57367 +const UNLOCK = 57368 +const SPLIT = 57369 +const MOVE = 57370 +const COMPOSE = 57371 +const SHARDING = 57372 +const COLUMN = 57373 +const TABLE = 57374 +const HASH = 57375 +const FUNCTION = 57376 +const KEY = 57377 +const RANGE = 57378 +const DATASPACE = 57379 +const SHARDS = 57380 +const KEY_RANGES = 57381 +const ROUTERS = 57382 +const SHARD = 57383 +const HOST = 57384 +const SHARDING_RULES = 57385 +const RULE = 57386 +const COLUMNS = 57387 +const VERSION = 57388 +const BY = 57389 +const FROM = 57390 +const TO = 57391 +const WITH = 57392 +const UNITE = 57393 +const ALL = 57394 +const ADDRESS = 57395 +const CLIENT = 57396 +const OP = 57397 var yyToknames = [...]string{ "$end", "error", "$unk", - "STRING", + "IDENT", "COMMAND", "SHOW", "KILL", @@ -135,16 +131,10 @@ var yyToknames = [...]string{ "OR", "AND", "TEQ", + "SCONST", "TSEMICOLON", "TOPENBR", "TCLOSEBR", - "POOLS", - "STATS", - "LISTS", - "SERVERS", - "CLIENTS", - "DATABASES", - "BACKEND_CONNECTIONS", "SHUTDOWN", "LISTEN", "REGISTER", @@ -184,18 +174,18 @@ var yyToknames = [...]string{ "ALL", "ADDRESS", "CLIENT", + "OP", } - var yyStatenames = [...]string{} const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line yacc/console/sql.y:617 +//line gram.y:557 //line yacctab:1 -var yyExca = [...]int8{ +var yyExca = [...]int{ -1, 1, 1, -1, -2, 0, @@ -203,144 +193,124 @@ var yyExca = [...]int8{ const yyPrivate = 57344 -const yyLast = 241 - -var yyAct = [...]uint8{ - 103, 125, 118, 122, 106, 109, 117, 69, 96, 111, - 115, 80, 100, 65, 80, 91, 161, 160, 64, 80, - 53, 58, 154, 56, 55, 54, 63, 80, 147, 80, - 90, 124, 89, 137, 120, 83, 76, 127, 101, 78, - 84, 82, 36, 77, 81, 49, 80, 37, 121, 57, - 59, 60, 153, 38, 61, 111, 47, 66, 143, 65, - 97, 45, 159, 79, 107, 62, 53, 58, 104, 56, - 55, 54, 63, 102, 158, 92, 93, 95, 98, 99, - 97, 94, 36, 75, 105, 74, 44, 37, 32, 43, - 112, 113, 114, 38, 110, 57, 59, 60, 135, 86, - 61, 80, 35, 66, 116, 136, 126, 48, 50, 128, - 34, 62, 133, 71, 72, 73, 123, 52, 68, 33, - 141, 42, 130, 140, 144, 145, 146, 132, 131, 41, - 70, 130, 150, 139, 149, 148, 132, 131, 40, 152, - 151, 88, 31, 141, 1, 138, 87, 16, 15, 155, - 14, 13, 12, 10, 11, 6, 157, 156, 65, 7, - 142, 162, 163, 64, 119, 53, 58, 39, 56, 55, - 54, 63, 4, 3, 5, 9, 8, 67, 51, 46, - 2, 108, 134, 129, 85, 0, 0, 0, 0, 22, - 23, 0, 0, 0, 57, 59, 60, 0, 0, 61, - 0, 0, 66, 0, 0, 25, 24, 29, 30, 0, - 62, 18, 17, 19, 20, 21, 26, 27, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 28, +const yyLast = 160 + +var yyAct = [...]int{ + + 95, 55, 102, 92, 82, 99, 101, 22, 23, 67, + 67, 67, 86, 77, 67, 142, 141, 25, 24, 29, + 30, 135, 128, 18, 17, 19, 20, 21, 26, 27, + 67, 76, 107, 75, 119, 104, 70, 63, 109, 65, + 87, 47, 36, 36, 68, 71, 45, 37, 37, 105, + 43, 69, 28, 38, 38, 74, 64, 90, 88, 80, + 66, 134, 78, 79, 81, 84, 49, 124, 67, 83, + 89, 91, 89, 140, 85, 139, 96, 97, 98, 62, + 61, 35, 67, 34, 106, 32, 100, 108, 112, 110, + 73, 33, 93, 114, 113, 57, 83, 115, 44, 131, + 42, 120, 41, 56, 122, 125, 126, 121, 112, 127, + 40, 129, 67, 114, 113, 130, 117, 54, 132, 48, + 50, 133, 52, 118, 122, 58, 59, 60, 31, 1, + 136, 16, 15, 14, 13, 137, 12, 138, 10, 11, + 6, 7, 143, 144, 123, 103, 39, 4, 3, 5, + 9, 8, 53, 51, 46, 2, 94, 116, 111, 72, } - -var yyPact = [...]int16{ - 183, -1000, 76, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 6, 46, 20, - 4, 4, 150, 150, 126, -1000, 4, 4, 4, 59, - 57, -1000, -1000, -1000, -1000, -1000, -14, 1, 7, -1000, - -1000, -1000, -1000, 97, -1000, -1, -1000, -15, -1000, -2, - -1000, 91, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 137, -1000, -1000, - -1000, -22, -25, -41, 97, 23, 42, 25, -44, -10, - -1000, -1000, 15, 10, 97, -1000, 51, -1000, -1000, 97, - 97, 97, -49, -1000, -1000, 22, -3, 112, -23, 102, - -11, 126, -1000, -1000, -1000, -1000, 127, 51, 94, -1000, - -1000, -1000, -20, -1000, -1000, 129, -3, -3, -1000, 19, - 112, 112, -1000, -1000, 102, -27, -1000, 126, -1000, 51, - -1000, -1000, -1000, 118, 5, -1000, -1000, 102, -1000, -1000, - -3, -1000, -1000, 12, -1000, -1000, -33, 102, -1000, 127, - -1000, -1000, -1000, 112, 102, 47, -1000, 35, -38, -39, - 97, 97, -1000, -1000, +var yyPact = [...]int{ + + 1, -1000, 72, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 12, 13, 11, + 31, 31, 118, 113, 91, -1000, 31, 31, 31, 60, + 59, -1000, -1000, -1000, -1000, -1000, -7, 20, 10, -1000, + -1000, -1000, -1000, 108, -1000, 15, -1000, -8, -1000, 9, + -1000, 82, -1000, 91, -1000, -1000, -1000, -1000, -15, -18, + -37, 108, 7, 64, 26, -38, -2, -1000, -1000, 6, + 5, 108, -1000, 78, -1000, 108, 108, 108, -48, -1000, + -1000, 37, 4, 108, -16, 91, -4, 91, -1000, -1000, + -1000, -1000, 104, 78, 112, -1000, -13, -1000, -1000, 91, + 4, 4, -1000, 34, 108, 108, -1000, 91, -27, 91, + -1000, 78, -1000, -1000, -1000, 84, 91, -1000, -1000, 91, + -1000, 4, -1000, -1000, 27, -1000, -1000, -28, 91, -1000, + 104, -1000, -1000, -1000, 108, 91, 54, -1000, 52, -33, + -34, 108, 108, -1000, -1000, } +var yyPgo = [...]int{ -var yyPgo = [...]uint8{ - 0, 184, 4, 183, 182, 181, 5, 180, 179, 86, - 178, 177, 176, 175, 174, 173, 172, 167, 119, 110, - 102, 6, 2, 8, 164, 160, 159, 155, 154, 153, - 152, 151, 150, 148, 147, 94, 7, 1, 0, 146, - 145, 3, 144, 142, + 0, 159, 3, 158, 157, 156, 1, 0, 155, 154, + 98, 153, 152, 151, 150, 149, 148, 147, 146, 91, + 83, 81, 6, 2, 4, 145, 144, 141, 140, 139, + 138, 136, 134, 133, 132, 131, 129, 128, } - -var yyR1 = [...]int8{ - 0, 42, 43, 43, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 6, 6, 3, 3, 3, 4, 4, 5, - 2, 2, 2, 1, 1, 10, 11, 14, 14, 14, - 14, 15, 15, 15, 16, 16, 16, 16, 12, 41, - 37, 38, 39, 36, 27, 17, 18, 18, 21, 21, - 22, 23, 23, 24, 24, 25, 25, 19, 19, 20, - 20, 26, 8, 9, 30, 13, 31, 32, 29, 28, - 40, 33, 34, 34, +var yyR1 = [...]int{ + + 0, 36, 37, 37, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, + 7, 3, 3, 3, 4, 4, 5, 2, 2, 2, + 1, 1, 11, 12, 15, 15, 15, 15, 16, 16, + 16, 17, 17, 17, 17, 13, 28, 18, 19, 19, + 22, 22, 23, 24, 24, 25, 25, 26, 26, 20, + 20, 21, 21, 27, 9, 10, 31, 14, 32, 33, + 30, 29, 34, 35, 35, } +var yyR2 = [...]int{ -var yyR2 = [...]int8{ 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 3, 3, 0, 2, 1, 1, 2, 4, 2, - 4, 2, 2, 2, 2, 2, 2, 2, 3, 1, - 1, 1, 1, 1, 2, 2, 5, 4, 1, 2, - 2, 2, 0, 2, 2, 3, 0, 10, 9, 5, - 4, 2, 3, 3, 6, 3, 4, 4, 2, 1, - 1, 5, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 0, 2, 1, 1, 2, 4, 2, 4, 2, 2, + 2, 2, 2, 2, 2, 3, 2, 2, 5, 4, + 1, 2, 2, 2, 0, 2, 2, 3, 0, 10, + 9, 5, 4, 2, 3, 3, 6, 3, 4, 4, + 2, 1, 5, 3, 3, } - -var yyChk = [...]int16{ - -1000, -42, -7, -15, -16, -14, -27, -26, -12, -13, - -29, -28, -30, -31, -32, -33, -34, 29, 28, 30, - 31, 32, 6, 7, 23, 22, 33, 34, 57, 24, - 25, -43, 12, -18, -19, -20, 36, 41, 47, -17, - -18, -19, -20, 43, -9, 41, -8, 36, -9, 41, - -9, -10, -35, 15, 20, 19, 18, 44, 16, 45, - 46, 49, 60, 21, 13, 8, 52, -11, -35, -36, - 4, -9, -9, -9, 26, 26, 50, 42, -38, 56, - 4, -38, 42, 50, 42, -1, 8, -39, 4, 54, - 55, 56, -38, -38, 58, -38, -23, 38, -38, 54, - 56, 48, 58, -38, 58, -38, -2, 13, -5, -6, - -35, 4, -38, -38, -38, 59, -23, -21, -22, -24, - 37, 51, -41, 4, 54, -37, 4, 48, -36, -3, - 4, 10, 9, -2, -4, 4, 11, 53, -40, 4, - -21, -22, -25, 39, -41, -41, -37, 55, -36, -2, - 14, -6, -37, 40, 55, -37, -41, -37, 27, 27, - 55, 55, -38, -38, +var yyChk = [...]int{ + + -1000, -36, -8, -16, -17, -15, -28, -27, -13, -14, + -30, -29, -31, -32, -33, -34, -35, 23, 22, 24, + 25, 26, 6, 7, 17, 16, 27, 28, 51, 18, + 19, -37, 13, -19, -20, -21, 30, 35, 41, -18, + -19, -20, -21, 37, -10, 35, -9, 30, -10, 35, + -10, -11, 4, -12, 4, -6, 12, 4, -10, -10, + -10, 20, 20, 44, 36, -7, 50, 4, -7, 36, + 44, 36, -1, 8, -6, 48, 49, 50, -7, -7, + 52, -7, -24, 32, -7, 48, 50, 42, 52, -7, + 52, -7, -2, 14, -5, -7, -7, -7, -7, 53, + -24, -22, -23, -25, 31, 45, -7, 48, -6, 42, + -6, -3, 4, 10, 9, -2, -4, 4, 11, 47, + -6, -22, -23, -26, 33, -7, -7, -6, 49, -6, + -2, 15, -6, -6, 34, 49, -6, -7, -6, 21, + 21, 49, 49, -7, -7, } +var yyDef = [...]int{ -var yyDef = [...]int8{ 0, -2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, - 0, 1, 3, 51, 52, 53, 0, 0, 0, 54, - 55, 56, 57, 0, 47, 0, 49, 0, 64, 0, - 81, 43, 45, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 0, 46, 88, - 63, 0, 0, 0, 0, 0, 72, 0, 0, 0, - 61, 65, 0, 0, 0, 58, 0, 85, 62, 0, - 0, 0, 0, 92, 93, 72, 0, 0, 0, 0, - 0, 0, 48, 83, 50, 82, 44, 29, 0, 39, - 32, 33, 0, 86, 87, 0, 0, 67, 68, 76, - 0, 0, 71, 59, 0, 0, 60, 0, 80, 0, - 34, 35, 36, 0, 0, 37, 38, 0, 91, 90, - 66, 69, 70, 0, 73, 74, 0, 0, 79, 42, - 40, 41, 84, 0, 0, 0, 75, 0, 0, 0, - 0, 0, 78, 77, + 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, + 0, 1, 3, 38, 39, 40, 0, 0, 0, 41, + 42, 43, 44, 0, 34, 0, 36, 0, 46, 0, + 63, 30, 32, 0, 33, 70, 18, 19, 0, 0, + 0, 0, 0, 54, 0, 0, 0, 20, 47, 0, + 0, 0, 45, 0, 67, 0, 0, 0, 0, 73, + 74, 54, 0, 0, 0, 0, 0, 0, 35, 65, + 37, 64, 31, 0, 0, 26, 0, 68, 69, 0, + 0, 49, 50, 58, 0, 0, 53, 0, 0, 0, + 62, 0, 21, 22, 23, 0, 0, 24, 25, 0, + 72, 48, 51, 52, 0, 55, 56, 0, 0, 61, + 29, 27, 28, 66, 0, 0, 0, 57, 0, 0, + 0, 0, 0, 60, 59, } +var yyTok1 = [...]int{ -var yyTok1 = [...]int8{ 1, } +var yyTok2 = [...]int{ -var yyTok2 = [...]int8{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, + 52, 53, 54, 55, } - -var yyTok3 = [...]int8{ +var yyTok3 = [...]int{ 0, } @@ -422,9 +392,9 @@ func yyErrorMessage(state, lookAhead int) string { expected := make([]int, 0, 4) // Look for shiftable tokens. - base := int(yyPact[state]) + base := yyPact[state] for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { - if n := base + tok; n >= 0 && n < yyLast && int(yyChk[int(yyAct[n])]) == tok { + if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok { if len(expected) == cap(expected) { return res } @@ -434,13 +404,13 @@ func yyErrorMessage(state, lookAhead int) string { if yyDef[state] == -2 { i := 0 - for yyExca[i] != -1 || int(yyExca[i+1]) != state { + for yyExca[i] != -1 || yyExca[i+1] != state { i += 2 } // Look for tokens that we accept or reduce. for i += 2; yyExca[i] >= 0; i += 2 { - tok := int(yyExca[i]) + tok := yyExca[i] if tok < TOKSTART || yyExca[i+1] == 0 { continue } @@ -471,30 +441,30 @@ func yylex1(lex yyLexer, lval *yySymType) (char, token int) { token = 0 char = lex.Lex(lval) if char <= 0 { - token = int(yyTok1[0]) + token = yyTok1[0] goto out } if char < len(yyTok1) { - token = int(yyTok1[char]) + token = yyTok1[char] goto out } if char >= yyPrivate { if char < yyPrivate+len(yyTok2) { - token = int(yyTok2[char-yyPrivate]) + token = yyTok2[char-yyPrivate] goto out } } for i := 0; i < len(yyTok3); i += 2 { - token = int(yyTok3[i+0]) + token = yyTok3[i+0] if token == char { - token = int(yyTok3[i+1]) + token = yyTok3[i+1] goto out } } out: if token == 0 { - token = int(yyTok2[1]) /* unknown char */ + token = yyTok2[1] /* unknown char */ } if yyDebug >= 3 { __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) @@ -549,7 +519,7 @@ yystack: yyS[yyp].yys = yystate yynewstate: - yyn = int(yyPact[yystate]) + yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } @@ -560,8 +530,8 @@ yynewstate: if yyn < 0 || yyn >= yyLast { goto yydefault } - yyn = int(yyAct[yyn]) - if int(yyChk[yyn]) == yytoken { /* valid shift */ + yyn = yyAct[yyn] + if yyChk[yyn] == yytoken { /* valid shift */ yyrcvr.char = -1 yytoken = -1 yyVAL = yyrcvr.lval @@ -574,7 +544,7 @@ yynewstate: yydefault: /* default state action */ - yyn = int(yyDef[yystate]) + yyn = yyDef[yystate] if yyn == -2 { if yyrcvr.char < 0 { yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) @@ -583,18 +553,18 @@ yydefault: /* look through exception table */ xi := 0 for { - if yyExca[xi+0] == -1 && int(yyExca[xi+1]) == yystate { + if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { - yyn = int(yyExca[xi+0]) + yyn = yyExca[xi+0] if yyn < 0 || yyn == yytoken { break } } - yyn = int(yyExca[xi+1]) + yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } @@ -616,10 +586,10 @@ yydefault: /* find a state where "error" is a legal shift action */ for yyp >= 0 { - yyn = int(yyPact[yyS[yyp].yys]) + yyErrCode + yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { - yystate = int(yyAct[yyn]) /* simulate a shift of "error" */ - if int(yyChk[yystate]) == yyErrCode { + yystate = yyAct[yyn] /* simulate a shift of "error" */ + if yyChk[yystate] == yyErrCode { goto yystack } } @@ -655,7 +625,7 @@ yydefault: yypt := yyp _ = yypt // guard against "declared and not used" - yyp -= int(yyR2[yyn]) + yyp -= yyR2[yyn] // yyp is now the index of $0. Perform the default action. Iff the // reduced production is ε, $1 is possibly out of range. if yyp+1 >= len(yyS) { @@ -666,16 +636,16 @@ yydefault: yyVAL = yyS[yyp+1] /* consult goto table to find next state */ - yyn = int(yyR1[yyn]) - yyg := int(yyPgo[yyn]) + yyn = yyR1[yyn] + yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { - yystate = int(yyAct[yyg]) + yystate = yyAct[yyg] } else { - yystate = int(yyAct[yyj]) - if int(yyChk[yystate]) != -yyn { - yystate = int(yyAct[yyg]) + yystate = yyAct[yyj] + if yyChk[yystate] != -yyn { + yystate = yyAct[yyg] } } // dummy call; replaced with literal code @@ -683,157 +653,163 @@ yydefault: case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line yacc/console/sql.y:165 +//line gram.y:159 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:166 +//line gram.y:160 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:171 +//line gram.y:165 { setParseTree(yylex, yyDollar[1].create) } case 5: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:175 +//line gram.y:169 { setParseTree(yylex, yyDollar[1].create) } case 6: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:179 +//line gram.y:173 { setParseTree(yylex, yyDollar[1].drop) } case 7: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:183 +//line gram.y:177 { setParseTree(yylex, yyDollar[1].lock) } case 8: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:187 +//line gram.y:181 { setParseTree(yylex, yyDollar[1].unlock) } case 9: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:191 +//line gram.y:185 { setParseTree(yylex, yyDollar[1].show) } case 10: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:195 +//line gram.y:189 { setParseTree(yylex, yyDollar[1].kill) } case 11: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:199 +//line gram.y:193 { setParseTree(yylex, yyDollar[1].listen) } case 12: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:203 +//line gram.y:197 { setParseTree(yylex, yyDollar[1].shutdown) } case 13: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:207 +//line gram.y:201 { setParseTree(yylex, yyDollar[1].split) } case 14: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:211 +//line gram.y:205 { setParseTree(yylex, yyDollar[1].move) } case 15: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:215 +//line gram.y:209 { setParseTree(yylex, yyDollar[1].unite) } case 16: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:219 +//line gram.y:213 { setParseTree(yylex, yyDollar[1].register_router) } case 17: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:223 +//line gram.y:217 { setParseTree(yylex, yyDollar[1].unregister_router) } - case 32: + case 18: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:244 +//line gram.y:222 { - yyVAL.str = yyDollar[1].str + yyVAL.str = string(yyDollar[1].str) } - case 33: + case 19: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:248 +//line gram.y:226 { yyVAL.str = string(yyDollar[1].str) } - case 34: + case 20: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:231 + { + yyVAL.str = string(yyDollar[1].str) + } + case 21: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:253 +//line gram.y:237 { yyVAL.str = yyDollar[1].str } - case 35: + case 22: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:255 +//line gram.y:239 { yyVAL.str = "AND" } - case 36: + case 23: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:257 +//line gram.y:241 { yyVAL.str = "OR" } - case 37: + case 24: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:262 +//line gram.y:246 { yyVAL.str = yyDollar[1].str } - case 38: + case 25: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:264 +//line gram.y:248 { yyVAL.str = "=" } - case 39: + case 26: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:270 +//line gram.y:254 { yyVAL.colref = ColumnRef{ ColName: yyDollar[1].str, } } - case 40: + case 27: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:278 +//line gram.y:262 { yyVAL.where = yyDollar[2].where } - case 41: + case 28: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:281 +//line gram.y:265 { yyVAL.where = WhereClauseLeaf{ ColRef: yyDollar[1].colref, @@ -841,9 +817,9 @@ yydefault: Value: yyDollar[3].str, } } - case 42: + case 29: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:289 +//line gram.y:273 { yyVAL.where = WhereClauseOp{ Op: yyDollar[2].str, @@ -851,32 +827,32 @@ yydefault: Right: yyDollar[3].where, } } - case 43: + case 30: yyDollar = yyS[yypt-0 : yypt+1] -//line yacc/console/sql.y:299 +//line gram.y:283 { yyVAL.where = WhereClauseEmpty{} } - case 44: + case 31: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:303 +//line gram.y:287 { yyVAL.where = yyDollar[2].where } - case 45: + case 32: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:310 +//line gram.y:294 { - switch v := string(yyDollar[1].str); v { + switch v := strings.ToLower(string(yyDollar[1].str)); v { case DatabasesStr, RoutersStr, PoolsStr, ShardsStr, BackendConnectionsStr, KeyRangesStr, ShardingRules, ClientsStr, StatusStr, VersionStr: yyVAL.str = v default: yyVAL.str = UnsupportedStr } } - case 46: + case 33: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:321 +//line gram.y:305 { switch v := string(yyDollar[1].str); v { case ClientStr: @@ -885,129 +861,99 @@ yydefault: yyVAL.str = "unsupp" } } - case 47: + case 34: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:332 +//line gram.y:316 { yyVAL.drop = &Drop{Element: yyDollar[2].key_range_selector} } - case 48: + case 35: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:337 +//line gram.y:321 { yyVAL.drop = &Drop{Element: &KeyRangeSelector{KeyRangeID: `*`}} } - case 49: + case 36: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:341 +//line gram.y:325 { yyVAL.drop = &Drop{Element: yyDollar[2].sharding_rule_selector} } - case 50: + case 37: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:346 +//line gram.y:330 { yyVAL.drop = &Drop{Element: &ShardingRuleSelector{ID: `*`}} } - case 51: + case 38: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:352 +//line gram.y:336 { yyVAL.create = &Create{Element: yyDollar[2].sharding_rule} } - case 52: + case 39: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:357 +//line gram.y:341 { yyVAL.create = &Create{Element: yyDollar[2].kr} } - case 53: + case 40: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:361 +//line gram.y:345 { yyVAL.create = &Create{Element: yyDollar[2].shard} } - case 54: + case 41: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:368 +//line gram.y:352 { yyVAL.create = &Create{Element: yyDollar[2].ds} } - case 55: + case 42: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:373 +//line gram.y:357 { yyVAL.create = &Create{Element: yyDollar[2].sharding_rule} } - case 56: + case 43: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:378 +//line gram.y:362 { yyVAL.create = &Create{Element: yyDollar[2].kr} } - case 57: + case 44: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:382 +//line gram.y:366 { yyVAL.create = &Create{Element: yyDollar[2].shard} } - case 58: + case 45: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:389 +//line gram.y:373 { yyVAL.show = &Show{Cmd: yyDollar[2].str, Where: yyDollar[3].where} } - case 59: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:395 - { - yyVAL.str = string(yyDollar[1].str) - } - case 60: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:402 - { - yyVAL.bytes = []byte(yyDollar[1].str) - } - case 61: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:408 - { - yyVAL.str = string(yyDollar[1].str) - } - case 62: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:414 - { - yyVAL.str = string(yyDollar[1].str) - } - case 63: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:420 - { - yyVAL.str = string(yyDollar[1].str) - } - case 64: + case 46: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:426 +//line gram.y:379 { yyVAL.lock = &Lock{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID} } - case 65: + case 47: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:434 +//line gram.y:387 { yyVAL.ds = &DataspaceDefinition{ID: yyDollar[2].str} } - case 66: + case 48: yyDollar = yyS[yypt-5 : yypt+1] -//line yacc/console/sql.y:446 +//line gram.y:393 { yyVAL.sharding_rule = &ShardingRuleDefinition{ID: yyDollar[3].str, TableName: yyDollar[4].str, Entries: yyDollar[5].entrieslist} } - case 67: + case 49: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:451 +//line gram.y:398 { str, err := randomHex(6) if err != nil { @@ -1015,89 +961,89 @@ yydefault: } yyVAL.sharding_rule = &ShardingRuleDefinition{ID: "shrule" + str, TableName: yyDollar[3].str, Entries: yyDollar[4].entrieslist} } - case 68: + case 50: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:460 +//line gram.y:407 { yyVAL.entrieslist = make([]ShardingRuleEntry, 0) yyVAL.entrieslist = append(yyVAL.entrieslist, yyDollar[1].shruleEntry) } - case 69: + case 51: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:466 +//line gram.y:413 { yyVAL.entrieslist = append(yyDollar[1].entrieslist, yyDollar[2].shruleEntry) } - case 70: + case 52: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:472 +//line gram.y:419 { yyVAL.shruleEntry = ShardingRuleEntry{ Column: yyDollar[1].str, HashFunction: yyDollar[2].str, } } - case 71: + case 53: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:481 +//line gram.y:428 { yyVAL.str = yyDollar[2].str } - case 72: + case 54: yyDollar = yyS[yypt-0 : yypt+1] -//line yacc/console/sql.y:484 +//line gram.y:431 { yyVAL.str = "" } - case 73: + case 55: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:488 +//line gram.y:435 { yyVAL.str = yyDollar[2].str } - case 74: + case 56: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:493 +//line gram.y:440 { yyVAL.str = yyDollar[2].str } - case 75: + case 57: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:499 +//line gram.y:446 { yyVAL.str = yyDollar[3].str } - case 76: + case 58: yyDollar = yyS[yypt-0 : yypt+1] -//line yacc/console/sql.y:502 +//line gram.y:449 { yyVAL.str = "" } - case 77: + case 59: yyDollar = yyS[yypt-10 : yypt+1] -//line yacc/console/sql.y:507 +//line gram.y:454 { - yyVAL.kr = &KeyRangeDefinition{LowerBound: yyDollar[5].bytes, UpperBound: yyDollar[7].bytes, ShardID: yyDollar[10].str, KeyRangeID: yyDollar[3].str} + yyVAL.kr = &KeyRangeDefinition{LowerBound: []byte(yyDollar[5].str), UpperBound: []byte(yyDollar[7].str), ShardID: yyDollar[10].str, KeyRangeID: yyDollar[3].str} } - case 78: + case 60: yyDollar = yyS[yypt-9 : yypt+1] -//line yacc/console/sql.y:512 +//line gram.y:459 { str, err := randomHex(6) if err != nil { panic(err) } - yyVAL.kr = &KeyRangeDefinition{LowerBound: yyDollar[4].bytes, UpperBound: yyDollar[6].bytes, ShardID: yyDollar[9].str, KeyRangeID: "kr" + str} + yyVAL.kr = &KeyRangeDefinition{LowerBound: []byte(yyDollar[4].str), UpperBound: []byte(yyDollar[6].str), ShardID: yyDollar[9].str, KeyRangeID: "kr" + str} } - case 79: + case 61: yyDollar = yyS[yypt-5 : yypt+1] -//line yacc/console/sql.y:523 +//line gram.y:470 { yyVAL.shard = &ShardDefinition{Id: yyDollar[2].str, Hosts: []string{yyDollar[5].str}} } - case 80: + case 62: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:528 +//line gram.y:475 { str, err := randomHex(6) if err != nil { @@ -1105,81 +1051,75 @@ yydefault: } yyVAL.shard = &ShardDefinition{Id: "shard" + str, Hosts: []string{yyDollar[4].str}} } - case 81: + case 63: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:539 +//line gram.y:486 { yyVAL.unlock = &Unlock{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID} } - case 82: + case 64: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:545 +//line gram.y:492 { yyVAL.sharding_rule_selector = &ShardingRuleSelector{ID: yyDollar[3].str} } - case 83: + case 65: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:551 +//line gram.y:498 { yyVAL.key_range_selector = &KeyRangeSelector{KeyRangeID: yyDollar[3].str} } - case 84: + case 66: yyDollar = yyS[yypt-6 : yypt+1] -//line yacc/console/sql.y:557 +//line gram.y:504 { - yyVAL.split = &SplitKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeFromID: yyDollar[4].str, Border: yyDollar[6].bytes} + yyVAL.split = &SplitKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeFromID: yyDollar[4].str, Border: []byte(yyDollar[6].str)} } - case 85: + case 67: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:563 +//line gram.y:510 { yyVAL.kill = &Kill{Cmd: yyDollar[2].str, Target: yyDollar[3].str} } - case 86: + case 68: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:569 +//line gram.y:516 { yyVAL.move = &MoveKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, DestShardID: yyDollar[4].str} } - case 87: + case 69: yyDollar = yyS[yypt-4 : yypt+1] -//line yacc/console/sql.y:575 +//line gram.y:522 { yyVAL.unite = &UniteKeyRange{KeyRangeIDL: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeIDR: yyDollar[4].str} } - case 88: + case 70: yyDollar = yyS[yypt-2 : yypt+1] -//line yacc/console/sql.y:581 +//line gram.y:528 { yyVAL.listen = &Listen{addr: yyDollar[2].str} } - case 89: + case 71: yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:587 +//line gram.y:534 { yyVAL.shutdown = &Shutdown{} } - case 90: - yyDollar = yyS[yypt-1 : yypt+1] -//line yacc/console/sql.y:595 - { - yyVAL.str = string(yyDollar[1].str) - } - case 91: + case 72: yyDollar = yyS[yypt-5 : yypt+1] -//line yacc/console/sql.y:602 +//line gram.y:542 { yyVAL.register_router = &RegisterRouter{ID: yyDollar[3].str, Addr: yyDollar[5].str} } - case 92: + case 73: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:608 +//line gram.y:548 { yyVAL.unregister_router = &UnregisterRouter{ID: yyDollar[3].str} } - case 93: + case 74: yyDollar = yyS[yypt-3 : yypt+1] -//line yacc/console/sql.y:613 +//line gram.y:553 { yyVAL.unregister_router = &UnregisterRouter{ID: `*`} } diff --git a/yacc/console/sql.y b/yacc/console/gram.y similarity index 81% rename from yacc/console/sql.y rename to yacc/console/gram.y index 26d5a26b3..986bcef6c 100644 --- a/yacc/console/sql.y +++ b/yacc/console/gram.y @@ -5,6 +5,7 @@ package spqrparser import ( "crypto/rand" "encoding/hex" + "strings" ) @@ -67,7 +68,7 @@ func randomHex(n int) (string, error) { //%type expr number // same for terminals -%token STRING COMMAND +%token IDENT COMMAND // DDL %token SHOW KILL @@ -80,6 +81,9 @@ func randomHex(n int) (string, error) { // '=' %token TEQ +/* any const */ +%token SCONST + // ';' %token TSEMICOLON @@ -90,13 +94,11 @@ func randomHex(n int) (string, error) { %type ColRef -%type any_val +%type any_val any_id // CMDS %type command -%token POOLS STATS LISTS SERVERS CLIENTS DATABASES BACKEND_CONNECTIONS - // routers %token SHUTDOWN LISTEN REGISTER UNREGISTER ROUTER ROUTE @@ -107,6 +109,10 @@ func randomHex(n int) (string, error) { %token CLIENT +/* any operator */ +%token OP + + %type sharding_rule_stmt %type key_range_stmt @@ -141,18 +147,6 @@ func randomHex(n int) (string, error) { %type unite_key_range_stmt %type register_router_stmt %type unregister_router_stmt - -%type reserved_keyword - -%type address -%type key_range_spec_bound - -%type internal_id -%type target - -%type router_addr -%type ref_name - %start any_command %% @@ -224,33 +218,23 @@ command: setParseTree(yylex, $1) } -reserved_keyword: -POOLS -| DATABASES -| CLIENTS -| SERVERS -| SHARDS -| STATS -| KEY_RANGES -| ROUTERS -| SHARDING_RULES -| CLIENT -| BACKEND_CONNECTIONS -| TOPENBR -| WHERE -| VERSION - -any_val: - reserved_keyword { - $$ = $1 - } - | STRING +any_val: SCONST + { + $$ = string($1) + } | + IDENT + { + $$ = string($1) + } + +any_id: IDENT { $$ = string($1) } + operator: - STRING { + IDENT { $$ = $1 } | AND { $$ = "AND" @@ -259,7 +243,7 @@ operator: } where_operator: - STRING { + IDENT { $$ = $1 } | TEQ { $$ = "=" @@ -267,7 +251,7 @@ where_operator: ColRef: - any_val { + any_id { $$ = ColumnRef{ ColName: $1, } @@ -306,9 +290,9 @@ where_clause: show_statement_type: - reserved_keyword + IDENT { - switch v := string($1); v { + switch v := strings.ToLower(string($1)); v { case DatabasesStr, RoutersStr, PoolsStr, ShardsStr,BackendConnectionsStr, KeyRangesStr, ShardingRules, ClientsStr, StatusStr, VersionStr: $$ = v default: @@ -317,7 +301,7 @@ show_statement_type: } kill_statement_type: - reserved_keyword + IDENT { switch v := string($1); v { case ClientStr: @@ -390,37 +374,6 @@ show_stmt: $$ = &Show{Cmd: $2, Where: $3} } -ref_name: - STRING - { - $$ = string($1) - } - - -key_range_spec_bound: - STRING - { - $$ = []byte($1) - } - -internal_id: - STRING - { - $$ = string($1) - } - -target: - STRING - { - $$ = string($1) - } - -address: - STRING - { - $$ = string($1) - } - lock_stmt: LOCK key_range_stmt { @@ -430,19 +383,13 @@ lock_stmt: dataspace_define_stmt: - DATASPACE internal_id + DATASPACE any_id { $$ = &DataspaceDefinition{ID: $2} } -//alter_dataspace_stmt: -// ALTER DATASPACE dataspace_id ADD SHARDING RULE shrule_id -// { -// $$ = &Alter{Element: &AlterDataspace{ID: $3}} -// } - sharding_rule_define_stmt: - SHARDING RULE internal_id sharding_rule_table_clause sharding_rule_argument_list + SHARDING RULE any_id sharding_rule_table_clause sharding_rule_argument_list { $$ = &ShardingRuleDefinition{ID: $3, TableName: $4, Entries: $5} } @@ -477,25 +424,25 @@ sharding_rule_entry: } sharding_rule_table_clause: - TABLE ref_name + TABLE any_id { $$ = $2 } | /*EMPTY*/ { $$ = ""; } sharding_rule_column_clause: - COLUMN ref_name + COLUMN any_id { $$ = $2 } | - COLUMNS ref_name + COLUMNS any_id { $$ = $2 }/* to be backward-compatable*/ sharding_rule_hash_function_clause: - HASH FUNCTION ref_name + HASH FUNCTION any_id { $$ = $3 } @@ -503,28 +450,28 @@ sharding_rule_hash_function_clause: key_range_define_stmt: - KEY RANGE internal_id FROM key_range_spec_bound TO key_range_spec_bound ROUTE TO internal_id + KEY RANGE any_id FROM any_val TO any_val ROUTE TO any_id { - $$ = &KeyRangeDefinition{LowerBound: $5, UpperBound: $7, ShardID: $10, KeyRangeID: $3} + $$ = &KeyRangeDefinition{LowerBound: []byte($5), UpperBound: []byte($7), ShardID: $10, KeyRangeID: $3} } | - KEY RANGE FROM key_range_spec_bound TO key_range_spec_bound ROUTE TO internal_id + KEY RANGE FROM any_val TO any_val ROUTE TO any_id { str, err := randomHex(6) if err != nil { panic(err) } - $$ = &KeyRangeDefinition{LowerBound: $4, UpperBound: $6, ShardID: $9, KeyRangeID: "kr"+str} + $$ = &KeyRangeDefinition{LowerBound: []byte($4), UpperBound: []byte($6), ShardID: $9, KeyRangeID: "kr"+str} } shard_define_stmt: - SHARD internal_id WITH HOST address + SHARD any_id WITH HOST any_val { $$ = &ShardDefinition{Id: $2, Hosts: []string{$5}} } | - SHARD WITH HOST address + SHARD WITH HOST any_val { str, err := randomHex(6) if err != nil { @@ -541,43 +488,43 @@ unlock_stmt: } sharding_rule_stmt: - SHARDING RULE internal_id + SHARDING RULE any_id { $$ =&ShardingRuleSelector{ID: $3} } key_range_stmt: - KEY RANGE internal_id + KEY RANGE any_id { $$ = &KeyRangeSelector{KeyRangeID: $3} } split_key_range_stmt: - SPLIT key_range_stmt FROM internal_id BY key_range_spec_bound + SPLIT key_range_stmt FROM any_id BY any_val { - $$ = &SplitKeyRange{KeyRangeID: $2.KeyRangeID, KeyRangeFromID: $4, Border: $6} + $$ = &SplitKeyRange{KeyRangeID: $2.KeyRangeID, KeyRangeFromID: $4, Border: []byte($6)} } kill_stmt: - KILL kill_statement_type target + KILL kill_statement_type any_val { $$ = &Kill{Cmd: $2, Target: $3} } move_key_range_stmt: - MOVE key_range_stmt TO internal_id + MOVE key_range_stmt TO any_id { $$ = &MoveKeyRange{KeyRangeID: $2.KeyRangeID, DestShardID: $4} } unite_key_range_stmt: - UNITE key_range_stmt WITH internal_id + UNITE key_range_stmt WITH any_id { $$ = &UniteKeyRange{KeyRangeIDL: $2.KeyRangeID, KeyRangeIDR: $4} } listen_stmt: - LISTEN address + LISTEN any_val { $$ = &Listen{addr: $2} } @@ -590,21 +537,14 @@ shutdown_stmt: // coordinator -router_addr: - STRING - { - $$ = string($1) - } - - register_router_stmt: - REGISTER ROUTER internal_id ADDRESS router_addr + REGISTER ROUTER any_id ADDRESS any_val { $$ = &RegisterRouter{ID: $3, Addr: $5} } unregister_router_stmt: - UNREGISTER ROUTER internal_id + UNREGISTER ROUTER any_id { $$ = &UnregisterRouter{ID: $3} } diff --git a/yacc/console/lex.go b/yacc/console/lex.go index d512a3c8d..6d390387d 100644 --- a/yacc/console/lex.go +++ b/yacc/console/lex.go @@ -1,142 +1,683 @@ + +//line lex.rl:1 +//nolint:all package spqrparser import ( - "errors" - "fmt" - "strings" + "strings" ) -// Tokenizer is the struct used to generate SQL -// tokens for the parser. -type Tokenizer struct { - s string - pos int - ParseTree Statement - LastError string + +//line lex.go:13 +const lexer_start int = 4 +const lexer_first_final int = 4 +const lexer_error int = 0 + +const lexer_en_main int = 4 + + +//line lex.rl:15 + + + +type Lexer struct { + data []byte + p, pe, cs int + ts, te, act int + + result []string } -func (t *Tokenizer) Lex(lval *yySymType) int { - if t.pos == len(t.s) { - return 0 +func NewLexer(data []byte) *Lexer { + lex := &Lexer{ + data: data, + pe: len(data), + } + +//line lex.go:39 + { + lex.cs = lexer_start + lex.ts = 0 + lex.te = 0 + lex.act = 0 } - var c rune - - // fmt.Printf("%s\n", t.s[t.pos:]) - - // skip through all the spaces, both at the ends and in between - -loop: - for { - if t.pos == len(t.s) { - return 0 - } - - c = rune(t.s[t.pos]) - - /* check if token is just some sybm */ - switch c { - case '(': - t.pos += 1 - return TOPENBR - case ')': - t.pos += 1 - return TCLOSEBR - // case ':': - // t.pos += 1 - // return TCOLON - // case ',': - // t.pos += 1 - // return TCOMMA - case ';': - t.pos += 1 - return TSEMICOLON - // case '.': - // t.pos += 1 - // return TDOT - case ' ': - fallthrough - case '\t': - fallthrough - case '\n': - t.pos += 1 - default: - break loop - } +//line lex.rl:32 + return lex +} + +func ResetLexer(lex *Lexer, data []byte) { + lex.pe = len(data) + lex.data = data + +//line lex.go:55 + { + lex.cs = lexer_start + lex.ts = 0 + lex.te = 0 + lex.act = 0 } - tok := "" - - var balance []rune - - // skip through all the spaces, both at the ends and in between -token_loop: - for { - if t.pos == len(t.s) { - break - } - c = rune(t.s[t.pos]) - /* check if token is just some sybm */ - switch c { - case '(': - fallthrough - case ')': - fallthrough - // case ':': - // fallthrough - // case ',': - // fallthrough - case ';': - fallthrough - // case '.': - // fallthrough - case ' ', '\t', '\n': - if len(balance) == 0 { - break token_loop - } // else append rune to current token - case '\'', '"': - if len(balance) > 0 && balance[len(balance)-1] == c { - balance = balance[:len(balance)-1] - } else { - balance = append(balance, c) - } - } - - tok = tok + string(c) - t.pos += 1 +//line lex.rl:39 +} + +func (l *Lexer) Error(msg string) { + println(msg) +} + + +func (lex *Lexer) Lex(lval *yySymType) int { + eof := lex.pe + var tok int + + +//line lex.go:76 + { + if ( lex.p) == ( lex.pe) { + goto _test_eof + } + switch lex.cs { + case 4: + goto st_case_4 + case 0: + goto st_case_0 + case 5: + goto st_case_5 + case 6: + goto st_case_6 + case 7: + goto st_case_7 + case 8: + goto st_case_8 + case 1: + goto st_case_1 + case 9: + goto st_case_9 + case 10: + goto st_case_10 + case 11: + goto st_case_11 + case 12: + goto st_case_12 + case 2: + goto st_case_2 + case 3: + goto st_case_3 + case 13: + goto st_case_13 + case 14: + goto st_case_14 } + goto st_out +tr1: +//line lex.rl:91 + lex.te = ( lex.p)+1 +{ lval.str = string(lex.data[lex.ts + 1:lex.te - 1]); tok = SCONST; {( lex.p)++; lex.cs = 4; goto _out }} + goto st4 +tr2: +//line NONE:1 + switch lex.act { + case 2: + {( lex.p) = ( lex.te) - 1 +/* nothing */} + case 4: + {( lex.p) = ( lex.te) - 1 + lval.str = string(lex.data[lex.ts + 1:lex.te - 1]); tok = IDENT; {( lex.p)++; lex.cs = 4; goto _out }} + case 5: + {( lex.p) = ( lex.te) - 1 + + + lval.str = string(lex.data[lex.ts:lex.te]); + if ttype, ok := reservedWords[strings.ToLower(lval.str)]; ok { + tok = ttype; + } else { + tok = IDENT; + } + {( lex.p)++; lex.cs = 4; goto _out }} + case 7: + {( lex.p) = ( lex.te) - 1 + lval.str = string(lex.data[lex.ts:lex.te]); tok = TEQ; {( lex.p)++; lex.cs = 4; goto _out }} + case 8: + {( lex.p) = ( lex.te) - 1 - if len(tok) >= 2 && tok[0] == tok[len(tok)-1] && (tok[0] == '\'' || tok[0] == '"') { - tok = tok[1 : len(tok)-1] + lval.str = string(lex.data[lex.ts:lex.te]); tok = int(OP); + {( lex.p)++; lex.cs = 4; goto _out } + } } + + goto st4 +tr15: +//line lex.rl:76 + lex.te = ( lex.p) +( lex.p)-- +{ /* do nothing */ } + goto st4 +tr17: +//line lex.rl:82 + lex.te = ( lex.p) +( lex.p)-- +{ + + lval.str = string(lex.data[lex.ts:lex.te]); + if ttype, ok := reservedWords[strings.ToLower(lval.str)]; ok { + tok = ttype; + } else { + tok = IDENT; + } + {( lex.p)++; lex.cs = 4; goto _out }} + goto st4 +tr19: +//line lex.rl:78 + lex.te = ( lex.p) +( lex.p)-- +{/* nothing */} + goto st4 +tr21: +//line lex.rl:79 + lex.te = ( lex.p) +( lex.p)-- +{ lval.str = string(lex.data[lex.ts:lex.te]); tok = SCONST; {( lex.p)++; lex.cs = 4; goto _out }} + goto st4 + st4: +//line NONE:1 + lex.ts = 0 - lval.str = tok + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof4 + } + st_case_4: +//line NONE:1 + lex.ts = ( lex.p) - if tp, ok := reservedWords[strings.ToLower(tok)]; ok { - return tp - } +//line lex.go:194 + switch lex.data[( lex.p)] { + case 32: + goto st5 + case 34: + goto tr9 + case 36: + goto st8 + case 39: + goto st1 + case 45: + goto st9 + case 47: + goto tr12 + case 58: + goto st8 + case 61: + goto tr14 + case 92: + goto tr8 + case 94: + goto tr8 + case 96: + goto tr8 + case 124: + goto tr8 + case 126: + goto tr8 + } + switch { + case lex.data[( lex.p)] < 42: + switch { + case lex.data[( lex.p)] < 33: + if 9 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 13 { + goto st5 + } + case lex.data[( lex.p)] > 38: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto st8 + } + default: + goto tr8 + } + case lex.data[( lex.p)] > 43: + switch { + case lex.data[( lex.p)] < 48: + if 44 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 46 { + goto st8 + } + case lex.data[( lex.p)] > 57: + switch { + case lex.data[( lex.p)] > 64: + if 65 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 125 { + goto st8 + } + case lex.data[( lex.p)] >= 60: + goto tr8 + } + default: + goto st14 + } + default: + goto tr8 + } + goto st0 +st_case_0: + st0: + lex.cs = 0 + goto _out + st5: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof5 + } + st_case_5: + if lex.data[( lex.p)] == 32 { + goto st5 + } + if 9 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 13 { + goto st5 + } + goto tr15 +tr8: +//line NONE:1 + lex.te = ( lex.p)+1 - return STRING -} +//line lex.rl:95 + lex.act = 8; + goto st6 +tr14: +//line NONE:1 + lex.te = ( lex.p)+1 -func (t *Tokenizer) Error(s string) { - t.LastError = s -} +//line lex.rl:93 + lex.act = 7; + goto st6 + st6: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof6 + } + st_case_6: +//line lex.go:294 + switch lex.data[( lex.p)] { + case 33: + goto tr8 + case 35: + goto tr8 + case 92: + goto tr8 + case 94: + goto tr8 + case 96: + goto tr8 + case 124: + goto tr8 + case 126: + goto tr8 + } + switch { + case lex.data[( lex.p)] < 42: + if 37 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 38 { + goto tr8 + } + case lex.data[( lex.p)] > 43: + if 60 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 64 { + goto tr8 + } + default: + goto tr8 + } + goto tr2 +tr9: +//line NONE:1 + lex.te = ( lex.p)+1 -func NewStringTokenizer(sql string) *Tokenizer { - return &Tokenizer{s: sql} -} +//line lex.rl:82 + lex.act = 5; + goto st7 +tr16: +//line NONE:1 + lex.te = ( lex.p)+1 -func setParseTree(yylex interface{}, stmt Statement) { - yylex.(*Tokenizer).ParseTree = stmt -} +//line lex.rl:81 + lex.act = 4; + goto st7 + st7: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof7 + } + st_case_7: +//line lex.go:343 + switch lex.data[( lex.p)] { + case 34: + goto tr16 + case 36: + goto tr9 + case 93: + goto tr9 + case 95: + goto tr9 + case 125: + goto tr9 + } + switch { + case lex.data[( lex.p)] < 44: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto tr9 + } + case lex.data[( lex.p)] > 58: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto tr9 + } + case lex.data[( lex.p)] >= 65: + goto tr9 + } + default: + goto tr9 + } + goto tr2 + st8: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof8 + } + st_case_8: + switch lex.data[( lex.p)] { + case 34: + goto st8 + case 36: + goto st8 + case 93: + goto st8 + case 95: + goto st8 + case 125: + goto st8 + } + switch { + case lex.data[( lex.p)] < 44: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto st8 + } + case lex.data[( lex.p)] > 58: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto st8 + } + case lex.data[( lex.p)] >= 65: + goto st8 + } + default: + goto st8 + } + goto tr17 + st1: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof1 + } + st_case_1: + if lex.data[( lex.p)] == 39 { + goto tr1 + } + goto st1 + st9: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof9 + } + st_case_9: + switch lex.data[( lex.p)] { + case 34: + goto st8 + case 36: + goto st8 + case 45: + goto st10 + case 93: + goto st8 + case 95: + goto st8 + case 125: + goto st8 + } + switch { + case lex.data[( lex.p)] < 44: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto st8 + } + case lex.data[( lex.p)] > 58: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto st8 + } + case lex.data[( lex.p)] >= 65: + goto st8 + } + default: + goto st8 + } + goto tr17 + st10: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof10 + } + st_case_10: + switch lex.data[( lex.p)] { + case 10: + goto tr19 + case 13: + goto tr19 + case 34: + goto st10 + case 36: + goto st10 + case 93: + goto st10 + case 95: + goto st10 + case 125: + goto st10 + } + switch { + case lex.data[( lex.p)] < 44: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto st10 + } + case lex.data[( lex.p)] > 58: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto st10 + } + case lex.data[( lex.p)] >= 65: + goto st10 + } + default: + goto st10 + } + goto st11 + st11: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof11 + } + st_case_11: + switch lex.data[( lex.p)] { + case 10: + goto tr19 + case 13: + goto tr19 + } + goto st11 +tr12: +//line NONE:1 + lex.te = ( lex.p)+1 -func Parse(sql string) (Statement, error) { - tokenizer := NewStringTokenizer(sql) - if yyParse(tokenizer) != 0 { - return nil, errors.New(tokenizer.LastError + fmt.Sprintf(" on pos %d", tokenizer.pos)) +//line lex.rl:82 + lex.act = 5; + goto st12 + st12: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof12 + } + st_case_12: +//line lex.go:518 + switch lex.data[( lex.p)] { + case 34: + goto st8 + case 36: + goto st8 + case 42: + goto st2 + case 93: + goto st8 + case 95: + goto st8 + case 125: + goto st8 + } + switch { + case lex.data[( lex.p)] < 44: + if 40 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 41 { + goto st8 + } + case lex.data[( lex.p)] > 58: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto st8 + } + case lex.data[( lex.p)] >= 65: + goto st8 + } + default: + goto st8 + } + goto tr17 + st2: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof2 + } + st_case_2: + if lex.data[( lex.p)] == 42 { + goto st3 + } + goto st2 + st3: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof3 + } + st_case_3: + switch lex.data[( lex.p)] { + case 42: + goto st3 + case 47: + goto tr5 + } + goto st2 +tr5: +//line NONE:1 + lex.te = ( lex.p)+1 + +//line lex.rl:78 + lex.act = 2; + goto st13 + st13: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof13 + } + st_case_13: +//line lex.go:584 + if lex.data[( lex.p)] == 42 { + goto st3 + } + goto st2 + st14: + if ( lex.p)++; ( lex.p) == ( lex.pe) { + goto _test_eof14 + } + st_case_14: + switch lex.data[( lex.p)] { + case 34: + goto st8 + case 36: + goto st8 + case 58: + goto st8 + case 93: + goto st8 + case 95: + goto st8 + case 125: + goto st8 + } + switch { + case lex.data[( lex.p)] < 48: + switch { + case lex.data[( lex.p)] > 41: + if 44 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 47 { + goto st8 + } + case lex.data[( lex.p)] >= 40: + goto st8 + } + case lex.data[( lex.p)] > 57: + switch { + case lex.data[( lex.p)] > 91: + if 97 <= lex.data[( lex.p)] && lex.data[( lex.p)] <= 123 { + goto st8 + } + case lex.data[( lex.p)] >= 65: + goto st8 + } + default: + goto st14 + } + goto tr21 + st_out: + _test_eof4: lex.cs = 4; goto _test_eof + _test_eof5: lex.cs = 5; goto _test_eof + _test_eof6: lex.cs = 6; goto _test_eof + _test_eof7: lex.cs = 7; goto _test_eof + _test_eof8: lex.cs = 8; goto _test_eof + _test_eof1: lex.cs = 1; goto _test_eof + _test_eof9: lex.cs = 9; goto _test_eof + _test_eof10: lex.cs = 10; goto _test_eof + _test_eof11: lex.cs = 11; goto _test_eof + _test_eof12: lex.cs = 12; goto _test_eof + _test_eof2: lex.cs = 2; goto _test_eof + _test_eof3: lex.cs = 3; goto _test_eof + _test_eof13: lex.cs = 13; goto _test_eof + _test_eof14: lex.cs = 14; goto _test_eof + + _test_eof: {} + if ( lex.p) == eof { + switch lex.cs { + case 5: + goto tr15 + case 6: + goto tr2 + case 7: + goto tr2 + case 8: + goto tr17 + case 9: + goto tr17 + case 10: + goto tr19 + case 11: + goto tr19 + case 12: + goto tr17 + case 2: + goto tr2 + case 3: + goto tr2 + case 13: + goto tr19 + case 14: + goto tr21 + } } - ast := tokenizer.ParseTree - return ast, nil -} + + _out: {} + } + +//line lex.rl:102 + + + return int(tok); +} \ No newline at end of file diff --git a/yacc/console/lex.rl b/yacc/console/lex.rl new file mode 100644 index 000000000..f03f8b587 --- /dev/null +++ b/yacc/console/lex.rl @@ -0,0 +1,105 @@ +//nolint:all +package spqrparser + +import ( + "strings" +) + + +%%{ + machine lexer; + write data; + access lex.; + variable p lex.p; + variable pe lex.pe; +}%% + + +type Lexer struct { + data []byte + p, pe, cs int + ts, te, act int + + result []string +} + +func NewLexer(data []byte) *Lexer { + lex := &Lexer{ + data: data, + pe: len(data), + } + %% write init; + return lex +} + +func ResetLexer(lex *Lexer, data []byte) { + lex.pe = len(data) + lex.data = data + %% write init; +} + +func (l *Lexer) Error(msg string) { + println(msg) +} + + +func (lex *Lexer) Lex(lval *yySymType) int { + eof := lex.pe + var tok int + + %%{ + + op_chars = ( '~' | '!' | '@' | '#' | '^' | '&' | '|' | '`' | '?' | '+' | '*' | '\\' | '%' | '<' | '>' | '=' ) ; + + sconst = '\'' (any-'\'')* '\''; + identifier = (print - space - op_chars-'\'' - ';')*; + + qidentifier = '"' identifier '"'; + + horiz_space = [ \t\f]; + newline = [\n\r]; + non_newline = [^\n\r]; + + sql_comment = '-''-' non_newline*; + c_style_comment = '/''*' (any - '*''/')* '*''/'; + comment = sql_comment | c_style_comment; + + + whitespace = space+; + + operator = op_chars+; + + integer = digit+; + + + main := |* + whitespace => { /* do nothing */ }; + # integer const is string const + comment => {/* nothing */}; + integer => { lval.str = string(lex.data[lex.ts:lex.te]); tok = SCONST; fbreak;}; + + qidentifier => { lval.str = string(lex.data[lex.ts + 1:lex.te - 1]); tok = IDENT; fbreak;}; + identifier => { + + lval.str = string(lex.data[lex.ts:lex.te]); + if ttype, ok := reservedWords[strings.ToLower(lval.str)]; ok { + tok = ttype; + } else { + tok = IDENT; + } + fbreak;}; + sconst => { lval.str = string(lex.data[lex.ts + 1:lex.te - 1]); tok = SCONST; fbreak;}; + + '=' => { lval.str = string(lex.data[lex.ts:lex.te]); tok = TEQ; fbreak;}; + + operator => { + lval.str = string(lex.data[lex.ts:lex.te]); tok = int(OP); + fbreak; + }; + *|; + + write exec; + }%% + + return int(tok); +} \ No newline at end of file diff --git a/yacc/console/lx_test.go b/yacc/console/lx_test.go new file mode 100644 index 000000000..8c37b2adb --- /dev/null +++ b/yacc/console/lx_test.go @@ -0,0 +1,69 @@ +package spqrparser_test + +import ( + "testing" + + spqrparser "github.com/pg-sharding/spqr/yacc/console" + "github.com/stretchr/testify/assert" +) + +func TestSimpleLex(t *testing.T) { + assert := assert.New(t) + + type tcase struct { + query string + exp []int + err error + } + + for _, tt := range []tcase{ + { + query: "SHOW version", + exp: []int{spqrparser.SHOW, spqrparser.IDENT}, + err: nil, + }, + { + query: "kill client 0xc00030f520;", + exp: []int{spqrparser.KILL, spqrparser.IDENT, spqrparser.IDENT}, + err: nil, + }, + { + query: "SHOW clients where user = 'usr1' or dbname = 'db1';", + exp: []int{ + spqrparser.SHOW, spqrparser.IDENT, + spqrparser.WHERE, + spqrparser.IDENT, + spqrparser.TEQ, + spqrparser.SCONST, + spqrparser.OR, + spqrparser.IDENT, + spqrparser.TEQ, + spqrparser.SCONST}, + err: nil, + }, + + { + query: "ADD KEY RANGE krid2 FROM 88888888-8888-8888-8888-888888888889 TO FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF ROUTE TO sh2;", + exp: []int{ + spqrparser.ADD, + spqrparser.KEY, + spqrparser.RANGE, + spqrparser.IDENT, + spqrparser.FROM, + spqrparser.IDENT, + spqrparser.TO, + spqrparser.IDENT, + spqrparser.ROUTE, + spqrparser.TO, + spqrparser.IDENT, + }, + err: nil, + }, + } { + tmp := spqrparser.NewStringTokenizer(tt.query) + + act := spqrparser.LexString(tmp) + + assert.Equal(tt.exp, act) + } +} diff --git a/yacc/console/reserved_keyword.go b/yacc/console/reserved_keyword.go index 6ca97d356..fc8d075d5 100644 --- a/yacc/console/reserved_keyword.go +++ b/yacc/console/reserved_keyword.go @@ -1,51 +1,41 @@ package spqrparser var reservedWords = map[string]int{ - "pools": POOLS, - "servers": SERVERS, - "clients": CLIENTS, - "client": CLIENT, - "databases": DATABASES, - "show": SHOW, - "stats": STATS, - "kill": KILL, - "column": COLUMN, - "columns": COLUMNS, - "shard": SHARD, - "rule": RULE, - "sharding": SHARDING, - "create": CREATE, - "add": ADD, - "key": KEY, - "range": RANGE, - "shards": SHARDS, - "key_ranges": KEY_RANGES, - "sharding_rules": SHARDING_RULES, - "lock": LOCK, - "unlock": UNLOCK, - "drop": DROP, - "all": ALL, - "shutdown": SHUTDOWN, - "split": SPLIT, - "version": VERSION, - "from": FROM, - "by": BY, - "to": TO, - "with": WITH, - "unite": UNITE, - "listen": LISTEN, - "register": REGISTER, - "unregister": UNREGISTER, - "router": ROUTER, - "move": MOVE, - "routers": ROUTERS, - "address": ADDRESS, - "host": HOST, - "route": ROUTE, - "dataspace": DATASPACE, - "table": TABLE, - "hash": HASH, - "function": FUNCTION, - "backend_connections": BACKEND_CONNECTIONS, - "where": WHERE, + "show": SHOW, + "kill": KILL, + "column": COLUMN, + "columns": COLUMNS, + "shard": SHARD, + "rule": RULE, + "sharding": SHARDING, + "create": CREATE, + "add": ADD, + "key": KEY, + "range": RANGE, + "lock": LOCK, + "unlock": UNLOCK, + "drop": DROP, + "all": ALL, + "shutdown": SHUTDOWN, + "split": SPLIT, + "from": FROM, + "by": BY, + "to": TO, + "with": WITH, + "unite": UNITE, + "listen": LISTEN, + "register": REGISTER, + "unregister": UNREGISTER, + "router": ROUTER, + "move": MOVE, + "address": ADDRESS, + "host": HOST, + "route": ROUTE, + "dataspace": DATASPACE, + "table": TABLE, + "hash": HASH, + "function": FUNCTION, + "where": WHERE, + "or": OR, + "and": AND, } diff --git a/yacc/console/util.go b/yacc/console/util.go new file mode 100644 index 000000000..44009f755 --- /dev/null +++ b/yacc/console/util.go @@ -0,0 +1,59 @@ +package spqrparser + +import ( + "errors" +) + +// Tokenizer is the struct used to generate SQL +// tokens for the parser. +type Tokenizer struct { + s string + pos int + + ParseTree Statement + LastError string + l *Lexer +} + +func (t *Tokenizer) Error(s string) { + t.LastError = s +} + +func NewStringTokenizer(sql string) *Tokenizer { + return &Tokenizer{ + s: sql, + l: NewLexer([]byte(sql)), + } +} + +func (t *Tokenizer) Lex(lval *yySymType) int { + return t.l.Lex(lval) +} + +func setParseTree(yylex interface{}, stmt Statement) { + yylex.(*Tokenizer).ParseTree = stmt +} + +func Parse(sql string) (Statement, error) { + tokenizer := NewStringTokenizer(sql) + if yyParse(tokenizer) != 0 { + return nil, errors.New(tokenizer.LastError) + } + ast := tokenizer.ParseTree + return ast, nil +} + +func LexString(l *Tokenizer) []int { + + act := make([]int, 0) + for { + v := l.Lex(&yySymType{}) + + if v == 0 { + break + } + act = append(act, v) + } + + return act +} diff --git a/yacc/console/yx_test.go b/yacc/console/yx_test.go new file mode 100644 index 000000000..19b75b4a9 --- /dev/null +++ b/yacc/console/yx_test.go @@ -0,0 +1,243 @@ +package spqrparser_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + spqrparser "github.com/pg-sharding/spqr/yacc/console" +) + +func TestSimpleShow(t *testing.T) { + assert := assert.New(t) + + type tcase struct { + query string + exp spqrparser.Statement + err error + } + + /* POOLS STATS LISTS SERVERS CLIENTS DATABASES BACKEND_CONNECTIONS */ + for _, tt := range []tcase{ + { + query: "SHOW version", + exp: &spqrparser.Show{ + Cmd: spqrparser.VersionStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + /* case insensetive */ + { + query: "ShOw versIon", + exp: &spqrparser.Show{ + Cmd: spqrparser.VersionStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + + { + query: "ShOw pools", + exp: &spqrparser.Show{ + Cmd: spqrparser.PoolsStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + { + query: "ShOw clients", + exp: &spqrparser.Show{ + Cmd: spqrparser.ClientsStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + { + query: "ShOw DATABASES", + exp: &spqrparser.Show{ + Cmd: spqrparser.DatabasesStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + { + query: "ShOw BACKEND_CONNECTIONS", + exp: &spqrparser.Show{ + Cmd: spqrparser.BackendConnectionsStr, + Where: spqrparser.WhereClauseEmpty{}, + }, + err: nil, + }, + { + query: "kill client 0xc00030f520;", + exp: &spqrparser.Kill{ + Cmd: spqrparser.ClientStr, + Target: "0xc00030f520", + }, + err: nil, + }, + } { + tmp, err := spqrparser.Parse(tt.query) + + assert.NoError(err, "query %s", tt.query) + + assert.Equal(tt.exp, tmp, "query %s", tt.query) + } +} + +func TestSimpleWhere(t *testing.T) { + + assert := assert.New(t) + + type tcase struct { + query string + exp spqrparser.Statement + err error + } + + for _, tt := range []tcase{ + { + query: "SHOW clients where user = 'usr1';", + exp: &spqrparser.Show{ + Cmd: spqrparser.ClientsStr, + Where: spqrparser.WhereClauseLeaf{ + Op: "=", + ColRef: spqrparser.ColumnRef{ColName: "user"}, + Value: "usr1", + }, + }, + err: nil, + }, + } { + + tmp, err := spqrparser.Parse(tt.query) + + assert.NoError(err, "query %s", tt.query) + + assert.Equal(tt.exp, tmp, "query %s", tt.query) + } +} + +func TestNestedWhere(t *testing.T) { + + assert := assert.New(t) + + type tcase struct { + query string + exp spqrparser.Statement + err error + } + + for _, tt := range []tcase{ + { + query: "SHOW clients where user = 'usr1' or dbname = 'db1';", + exp: &spqrparser.Show{ + Cmd: spqrparser.ClientsStr, + Where: spqrparser.WhereClauseOp{ + Op: "OR", + Left: spqrparser.WhereClauseLeaf{ + Op: "=", + ColRef: spqrparser.ColumnRef{ColName: "user"}, + Value: "usr1", + }, + Right: spqrparser.WhereClauseLeaf{ + Op: "=", + ColRef: spqrparser.ColumnRef{ColName: "dbname"}, + Value: "db1", + }, + }, + }, + err: nil, + }, + } { + + tmp, err := spqrparser.Parse(tt.query) + + assert.NoError(err, "query %s", tt.query) + + assert.Equal(tt.exp, tmp, "query %s", tt.query) + } +} + +func TestKeyRange(t *testing.T) { + + assert := assert.New(t) + + type tcase struct { + query string + exp spqrparser.Statement + err error + } + + for _, tt := range []tcase{ + { + query: "ADD KEY RANGE krid1 FROM 1 TO 10 ROUTE TO sh1;", + exp: &spqrparser.Create{ + Element: &spqrparser.KeyRangeDefinition{ + ShardID: "sh1", + KeyRangeID: "krid1", + LowerBound: []byte("1"), + UpperBound: []byte("10"), + }, + }, + err: nil, + }, + + { + query: "ADD KEY RANGE krid2 FROM 88888888-8888-8888-8888-888888888889 TO FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF ROUTE TO sh2;", + exp: &spqrparser.Create{ + Element: &spqrparser.KeyRangeDefinition{ + ShardID: "sh2", + KeyRangeID: "krid2", + LowerBound: []byte("88888888-8888-8888-8888-888888888889"), + UpperBound: []byte("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"), + }, + }, + err: nil, + }, + } { + + tmp, err := spqrparser.Parse(tt.query) + + assert.NoError(err, "query %s", tt.query) + + assert.Equal(tt.exp, tmp, "query %s", tt.query) + } +} + +func TestShardingRule(t *testing.T) { + + assert := assert.New(t) + + type tcase struct { + query string + exp spqrparser.Statement + err error + } + + for _, tt := range []tcase{ + { + query: "ADD SHARDING RULE rule1 COLUMNS id;", + exp: &spqrparser.Create{ + Element: &spqrparser.ShardingRuleDefinition{ + ID: "rule1", + TableName: "", + Entries: []spqrparser.ShardingRuleEntry{ + { + Column: "id", + }, + }, + }, + }, + err: nil, + }, + } { + + tmp, err := spqrparser.Parse(tt.query) + + assert.NoError(err, "query %s", tt.query) + + assert.Equal(tt.exp, tmp, "query %s", tt.query) + } +}