diff --git a/cli/cli.go b/cli/cli.go index fcf2e38b..ca769147 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -158,15 +158,20 @@ func ExecuteWith(ctx context.Context, rc *RunContext, args []string) error { // look like: [query, arg1, arg2] -- noting that SetArgs // doesn't want the first args element. effectiveArgs := append([]string{"slq"}, args...) + if effectiveArgs, err = preprocessFlagArgVars(effectiveArgs); err != nil { + return err + } rootCmd.SetArgs(effectiveArgs) } else { if cmd.Name() == rootCmd.Name() { // Not sure why we have two paths to this, but it appears // that we've found the root cmd again, so again // we redirect to "slq" cmd. - - a := append([]string{"slq"}, args...) - rootCmd.SetArgs(a) + effectiveArgs := append([]string{"slq"}, args...) + if effectiveArgs, err = preprocessFlagArgVars(effectiveArgs); err != nil { + return err + } + rootCmd.SetArgs(effectiveArgs) } else { // It's just a normal command like "sq ls" or such. diff --git a/cli/cmd_slq.go b/cli/cmd_slq.go index a1f18a61..60974752 100644 --- a/cli/cmd_slq.go +++ b/cli/cmd_slq.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + "golang.org/x/exp/slices" + "github.com/neilotoole/sq/libsq/core/lg/lgm" "github.com/neilotoole/sq/libsq/core/lg" @@ -25,26 +27,38 @@ func newSLQCmd() *cobra.Command { Short: "Execute SLQ query", // This command is hidden, because it is effectively the root cmd. Hidden: true, - Args: cobra.MaximumNArgs(1), RunE: execSLQ, ValidArgsFunction: completeSLQ, } addQueryCmdFlags(cmd) - // Explicitly flagVersion because people like to do "sq --version" + cmd.Flags().StringArray(flagArg, nil, flagArgUsage) + + // Explicitly add flagVersion because people like to do "sq --version" // as much as "sq version". cmd.Flags().Bool(flagVersion, false, flagVersionUsage) return cmd } -func execSLQ(cmd *cobra.Command, _ []string) error { - rc := RunContextFrom(cmd.Context()) +// execSLQ is sq's core command. +func execSLQ(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + msg := "no query" + if cmdFlagChanged(cmd, flagArg) { + msg += fmt.Sprintf(": maybe check flag --%s usage", flagArg) + } + + return errz.New(msg) + } + + ctx := cmd.Context() + rc := RunContextFrom(ctx) srcs := rc.Config.Sources // check if there's input on stdin - src, err := checkStdinSource(cmd.Context(), rc) + src, err := checkStdinSource(ctx, rc) if err != nil { return err } @@ -53,15 +67,13 @@ func execSLQ(cmd *cobra.Command, _ []string) error { // We have a valid source on stdin. // Add the source to the set. - err = srcs.Add(src) - if err != nil { + if err = srcs.Add(src); err != nil { return err } // Set the stdin pipe data source as the active source, // as it's commonly the only data source the user is acting upon. - _, err = srcs.SetActive(src.Handle) - if err != nil { + if _, err = srcs.SetActive(src.Handle); err != nil { return err } } else { @@ -74,10 +86,15 @@ func execSLQ(cmd *cobra.Command, _ []string) error { } } + mArgs, err := extractFlagArgsValues(cmd) + if err != nil { + return err + } + if !cmdFlagChanged(cmd, flagInsert) { // The user didn't specify the --insert=@src.tbl flag, // so we just want to print the records. - return execSLQPrint(cmd.Context(), rc) + return execSLQPrint(ctx, rc, mArgs) } // Instead of printing the records, they will be @@ -101,12 +118,14 @@ func execSLQ(cmd *cobra.Command, _ []string) error { return err } - return execSLQInsert(cmd.Context(), rc, destSrc, destTbl) + return execSLQInsert(ctx, rc, mArgs, destSrc, destTbl) } // execSQLInsert executes the SLQ and inserts resulting records // into destTbl in destSrc. -func execSLQInsert(ctx context.Context, rc *RunContext, destSrc *source.Source, destTbl string) error { +func execSLQInsert(ctx context.Context, rc *RunContext, mArgs map[string]string, + destSrc *source.Source, destTbl string, +) error { args, srcs, dbases := rc.Args, rc.Config.Sources, rc.databases slq, err := preprocessUserSLQ(ctx, rc, args) if err != nil { @@ -138,7 +157,7 @@ func execSLQInsert(ctx context.Context, rc *RunContext, destSrc *source.Source, Sources: srcs, DBOpener: rc.databases, JoinDBOpener: rc.databases, - Args: nil, + Args: mArgs, } execErr := libsq.ExecuteSLQ(ctx, qc, slq, inserter) @@ -156,7 +175,7 @@ func execSLQInsert(ctx context.Context, rc *RunContext, destSrc *source.Source, } // execSLQPrint executes the SLQ query, and prints output to writer. -func execSLQPrint(ctx context.Context, rc *RunContext) error { +func execSLQPrint(ctx context.Context, rc *RunContext, mArgs map[string]string) error { slq, err := preprocessUserSLQ(ctx, rc, rc.Args) if err != nil { return err @@ -166,7 +185,7 @@ func execSLQPrint(ctx context.Context, rc *RunContext) error { Sources: rc.Config.Sources, DBOpener: rc.databases, JoinDBOpener: rc.databases, - Args: nil, + Args: mArgs, } recw := output.NewRecordWriterAdapter(rc.writers.recordw) @@ -341,3 +360,113 @@ func addQueryCmdFlags(cmd *cobra.Command) { cmd.Flags().StringP(flagSrcOptions, "", "", flagQuerySrcOptionsUsage) } + +// extractFlagArgsValues returns a map {key:value} of predefined variables +// as supplied via --arg. For example: +// +// sq --arg name TOM '.actor | .first_name == $name' +// +// See preprocessFlagArgVars. +func extractFlagArgsValues(cmd *cobra.Command) (map[string]string, error) { + if !cmdFlagChanged(cmd, flagArg) { + return nil, nil //nolint:nilnil + } + + arr, err := cmd.Flags().GetStringArray(flagArg) + if err != nil { + return nil, errz.Err(err) + } + + if len(arr) == 0 { + return nil, nil //nolint:nilnil + } + + mArgs := map[string]string{} + for _, kv := range arr { + k, v, ok := strings.Cut(kv, ":") + if !ok || k == "" { + return nil, errz.Errorf("invalid --%s value", flagArg) + } + + if _, ok := mArgs[k]; ok { + // If the key already exists, don't overwrite. This mimics jq's + // behavior. + + log := lg.FromContext(cmd.Context()) + log.With("arg", k).Warn("Double use of --arg key; using first value.") + + continue + } + + mArgs[k] = v + } + + return mArgs, nil +} + +// preprocessFlagArgVars is a hack to support the predefined +// variables "--arg" mechanism. We implement the mechanism in alignment +// with how jq does it: "--arg name value". +// See: https://stedolan.github.io/jq/manual/v1.6/ +// +// For example: +// +// sq --arg first TOM --arg last MIRANDA '.actor | .first_name == $first && .last_name == $last' +// +// However, cobra (or rather, pflag) doesn't support this type of flag input. +// So, we have a hack. In the example above, the two elements "first" and "TOM" +// are concatenated into a single flag value "first:TOM". Thus, the returned +// slice will be shorter. +// +// This function needs to be called before cobra/pflag starts processing +// the program args. +// +// Any code making use of flagArg will need to deconstruct the flag value. +// Specifically, that means extractFlagArgsValues. +func preprocessFlagArgVars(args []string) ([]string, error) { + const flg = "--" + flagArg + + if len(args) == 0 { + return args, nil + } + + if !slices.Contains(args, flg) { + return args, nil + } + + rez := make([]string, 0, len(args)) + + var i int + for i = 0; i < len(args); { + if args[i] == flg { + val, err := extractFlagArgsSingleArg(args[i:]) + if err != nil { + return nil, err + } + rez = append(rez, flg) + rez = append(rez, val) + i += 3 + continue + } + + rez = append(rez, args[i]) + i++ + } + + return rez, nil +} + +// args will look like ["--arg", "key", "value", "--other-flag"]. +// The function will return "key:value". +// See preprocessFlagArgVars. +func extractFlagArgsSingleArg(args []string) (string, error) { + if len(args) < 3 { + return "", errz.Errorf("invalid %s flag: must be '--%s key value'", flagArg, flagArg) + } + + if err := stringz.ValidIdent(args[1]); err != nil { + return "", errz.Errorf("invalid --%s key: %s", flagArg, args[1]) + } + + return args[1] + ":" + args[2], nil +} diff --git a/cli/consts.go b/cli/consts.go index 2b92af95..5eeb37e5 100644 --- a/cli/consts.go +++ b/cli/consts.go @@ -112,6 +112,9 @@ const ( flagSkipVerify = "skip-verify" flagSkipVerifyUsage = "Don't ping source before adding it" + + flagArg = "arg" + flagArgUsage = "Set a string value to a variable" ) const ( diff --git a/cli/internal_test.go b/cli/internal_test.go index 7f1e458c..4ddedb2c 100644 --- a/cli/internal_test.go +++ b/cli/internal_test.go @@ -1 +1,87 @@ package cli + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_preprocessFlagArgVars(t *testing.T) { + testCases := []struct { + name string + in []string + want []string + wantErr bool + }{ + { + name: "empty", + in: []string{}, + want: []string{}, + }, + { + name: "no flags", + in: []string{".actor"}, + want: []string{".actor"}, + }, + { + name: "non-arg flag", + in: []string{"--json", ".actor"}, + want: []string{"--json", ".actor"}, + }, + { + name: "non-arg flag with value", + in: []string{"--json", "true", ".actor"}, + want: []string{"--json", "true", ".actor"}, + }, + { + name: "single arg flag", + in: []string{"--arg", "name", "TOM", ".actor"}, + want: []string{"--arg", "name:TOM", ".actor"}, + }, + { + name: "invalid arg name", + in: []string{"--arg", "na me", "TOM", ".actor"}, + wantErr: true, + }, + { + name: "invalid arg name (with colon)", + in: []string{"--arg", "na:me", "TOM", ".actor"}, + wantErr: true, + }, + { + name: "colon in value", + in: []string{"--arg", "name", "T:OM", ".actor"}, + want: []string{"--arg", "name:T:OM", ".actor"}, + }, + { + name: "single arg flag with whitespace", + in: []string{"--arg", "name", "TOM DOWD", ".actor"}, + want: []string{"--arg", "name:TOM DOWD", ".actor"}, + }, + { + name: "two arg flags", + in: []string{"--arg", "name", "TOM", "--arg", "eyes", "blue", ".actor"}, + want: []string{"--arg", "name:TOM", "--arg", "eyes:blue", ".actor"}, + }, + { + name: "two arg flags with interspersed flag", + in: []string{"--arg", "name", "TOM", "--json", "true", "--arg", "eyes", "blue", ".actor"}, + want: []string{"--arg", "name:TOM", "--json", "true", "--arg", "eyes:blue", ".actor"}, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + got, gotErr := preprocessFlagArgVars(tc.in) + if tc.wantErr { + t.Log(gotErr.Error()) + require.Error(t, gotErr) + return + } + + require.NoError(t, gotErr) + require.EqualValues(t, tc.want, got) + }) + } +} diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index b4217b4e..c4df2e49 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -7,6 +7,8 @@ import ( "fmt" "strings" + "github.com/neilotoole/sq/libsq/driver/dialect" + "github.com/neilotoole/sq/libsq/core/lg/lga" "github.com/neilotoole/sq/libsq/core/lg/lgm" @@ -18,7 +20,7 @@ import ( "github.com/go-sql-driver/mysql" "github.com/xo/dburl" - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/sqlmodel" @@ -70,13 +72,15 @@ func (d *driveri) DriverMetadata() driver.Metadata { } // Dialect implements driver.Driver. -func (d *driveri) Dialect() driver.Dialect { - return driver.Dialect{ +func (d *driveri) Dialect() dialect.Dialect { + return dialect.Dialect{ Type: Type, Placeholders: placeholders, - Quote: '`', + IdentQuote: '`', + Enquote: stringz.BacktickQuote, IntBool: true, MaxBatchValues: 250, + Ops: dialect.DefaultOps(), } } @@ -88,9 +92,10 @@ func placeholders(numCols, numRows int) string { return strings.Join(rows, driver.Comma) } -// SQLBuilder implements driver.SQLDriver. -func (d *driveri) SQLBuilder() (sqlbuilder.FragmentBuilder, sqlbuilder.QueryBuilder) { - return newFragmentBuilder(d.log), &sqlbuilder.BaseQueryBuilder{} +// Renderer implements driver.SQLDriver. +func (d *driveri) Renderer() *render.Renderer { + r := render.NewDefaultRenderer() + return r } // RecordMeta implements driver.SQLDriver. @@ -246,8 +251,8 @@ func (d *driveri) TableColumnTypes(ctx context.Context, db sqlz.DB, tblName stri const queryTpl = "SELECT %s FROM %s LIMIT 0" dialect := d.Dialect() - quote := string(dialect.Quote) - tblNameQuoted := stringz.Surround(tblName, quote) + quote := string(dialect.IdentQuote) + tblNameQuoted := dialect.Enquote(tblName) colsClause := "*" if len(colNames) > 0 { diff --git a/drivers/mysql/sqlbuilder.go b/drivers/mysql/render.go similarity index 93% rename from drivers/mysql/sqlbuilder.go rename to drivers/mysql/render.go index bd226a0c..469ca64b 100644 --- a/drivers/mysql/sqlbuilder.go +++ b/drivers/mysql/render.go @@ -5,26 +5,12 @@ import ( "fmt" "strings" - "golang.org/x/exp/slog" - - "github.com/neilotoole/sq/libsq/core/stringz" - - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/sqlmodel" ) -func newFragmentBuilder(log *slog.Logger) *sqlbuilder.BaseFragmentBuilder { - r := &sqlbuilder.BaseFragmentBuilder{} - r.Log = log - r.Quote = "`" - r.QuoteFn = stringz.BacktickQuote - r.Ops = sqlbuilder.BaseOps() - return r -} - func dbTypeNameFromKind(knd kind.Kind) string { switch knd { //nolint:exhaustive // ignore kind.Unknown and kind.Null case kind.Text: diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index f16ed7a0..d710d02b 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -8,6 +8,8 @@ import ( "strconv" "strings" + "github.com/neilotoole/sq/libsq/driver/dialect" + "github.com/neilotoole/sq/libsq/core/lg/lga" "github.com/neilotoole/sq/libsq/core/lg/lgm" @@ -19,7 +21,7 @@ import ( "github.com/jackc/pgx/v4" // Import jackc/pgx, which is our postgres driver. _ "github.com/jackc/pgx/v4/stdlib" - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/sqlmodel" @@ -67,12 +69,14 @@ func (d *driveri) DriverMetadata() driver.Metadata { } // Dialect implements driver.SQLDriver. -func (d *driveri) Dialect() driver.Dialect { - return driver.Dialect{ +func (d *driveri) Dialect() dialect.Dialect { + return dialect.Dialect{ Type: Type, Placeholders: placeholders, - Quote: '"', + IdentQuote: '"', + Enquote: stringz.DoubleQuote, MaxBatchValues: 1000, + Ops: dialect.DefaultOps(), } } @@ -99,9 +103,10 @@ func placeholders(numCols, numRows int) string { return strings.Join(rows, driver.Comma) } -// SQLBuilder implements driver.SQLDriver. -func (d *driveri) SQLBuilder() (sqlbuilder.FragmentBuilder, sqlbuilder.QueryBuilder) { - return newFragmentBuilder(d.log), &sqlbuilder.BaseQueryBuilder{} +// Renderer implements driver.SQLDriver. +func (d *driveri) Renderer() *render.Renderer { + r := render.NewDefaultRenderer() + return r } // Open implements driver.Driver. @@ -340,7 +345,7 @@ func (d *driveri) TableColumnTypes(ctx context.Context, db sqlz.DB, tblName stri // (SELECT username FROM person LIMIT 1) AS username, // (SELECT email FROM person LIMIT 1) AS email // LIMIT 1; - quote := string(d.Dialect().Quote) + quote := string(d.Dialect().IdentQuote) tblNameQuoted := stringz.Surround(tblName, quote) var query string diff --git a/drivers/postgres/sqlbuilder.go b/drivers/postgres/render.go similarity index 89% rename from drivers/postgres/sqlbuilder.go rename to drivers/postgres/render.go index 52699f0b..cded95a9 100644 --- a/drivers/postgres/sqlbuilder.go +++ b/drivers/postgres/render.go @@ -5,26 +5,12 @@ import ( "strconv" "strings" - "golang.org/x/exp/slog" - - "github.com/neilotoole/sq/libsq/core/stringz" - - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/sqlmodel" ) -func newFragmentBuilder(log *slog.Logger) *sqlbuilder.BaseFragmentBuilder { - fb := &sqlbuilder.BaseFragmentBuilder{} - fb.Log = log - fb.Quote = `"` - fb.QuoteFn = stringz.DoubleQuote - fb.Ops = sqlbuilder.BaseOps() - return fb -} - func dbTypeNameFromKind(knd kind.Kind) string { switch knd { //nolint:exhaustive default: diff --git a/drivers/sqlite3/sqlbuilder.go b/drivers/sqlite3/render.go similarity index 90% rename from drivers/sqlite3/sqlbuilder.go rename to drivers/sqlite3/render.go index 0caa4dc7..f734367d 100644 --- a/drivers/sqlite3/sqlbuilder.go +++ b/drivers/sqlite3/render.go @@ -4,26 +4,12 @@ import ( "bytes" "strings" - "golang.org/x/exp/slog" - - "github.com/neilotoole/sq/libsq/core/stringz" - - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/sqlmodel" ) -func newFragmentBuilder(log *slog.Logger) *sqlbuilder.BaseFragmentBuilder { - return &sqlbuilder.BaseFragmentBuilder{ - Log: log, - Quote: `"`, - QuoteFn: stringz.DoubleQuote, - Ops: sqlbuilder.BaseOps(), - } -} - // createTblKindDefaults is a mapping of Kind to the value // to use for a column's DEFAULT clause in a CREATE TABLE statement. var createTblKindDefaults = map[kind.Kind]string{ //nolint:exhaustive // ignore kind.Null diff --git a/drivers/sqlite3/sqlite3.go b/drivers/sqlite3/sqlite3.go index f7233d64..247948ca 100644 --- a/drivers/sqlite3/sqlite3.go +++ b/drivers/sqlite3/sqlite3.go @@ -15,6 +15,8 @@ import ( "sync" "time" + "github.com/neilotoole/sq/libsq/driver/dialect" + "github.com/neilotoole/sq/libsq/core/lg/lga" "github.com/neilotoole/sq/libsq/core/lg/lgm" @@ -24,7 +26,7 @@ import ( "golang.org/x/exp/slog" _ "github.com/mattn/go-sqlite3" // Import for side effect of loading the driver - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/sqlmodel" @@ -160,12 +162,14 @@ func (d *driveri) Ping(ctx context.Context, src *source.Source) error { } // Dialect implements driver.SQLDriver. -func (d *driveri) Dialect() driver.Dialect { - return driver.Dialect{ +func (d *driveri) Dialect() dialect.Dialect { + return dialect.Dialect{ Type: Type, Placeholders: placeholders, - Quote: '"', + IdentQuote: '"', + Enquote: stringz.DoubleQuote, MaxBatchValues: 500, + Ops: dialect.DefaultOps(), } } @@ -178,8 +182,9 @@ func placeholders(numCols, numRows int) string { } // SQLBuilder implements driver.SQLDriver. -func (d *driveri) SQLBuilder() (sqlbuilder.FragmentBuilder, sqlbuilder.QueryBuilder) { - return newFragmentBuilder(d.log), &sqlbuilder.BaseQueryBuilder{} +func (d *driveri) Renderer() *render.Renderer { + r := render.NewDefaultRenderer() + return r } // CopyTable implements driver.SQLDriver. @@ -682,7 +687,7 @@ func (d *driveri) TableColumnTypes(ctx context.Context, db sqlz.DB, tblName stri const queryTpl = "SELECT %s FROM %s LIMIT 1" dialect := d.Dialect() - quote := string(dialect.Quote) + quote := string(dialect.IdentQuote) tblNameQuoted := stringz.Surround(tblName, quote) colsClause := "*" diff --git a/drivers/sqlserver/sqlbuilder.go b/drivers/sqlserver/render.go similarity index 81% rename from drivers/sqlserver/sqlbuilder.go rename to drivers/sqlserver/render.go index 39915c96..d326816b 100644 --- a/drivers/sqlserver/sqlbuilder.go +++ b/drivers/sqlserver/render.go @@ -1,18 +1,11 @@ package sqlserver import ( - "bytes" "fmt" "strconv" "strings" - "github.com/neilotoole/sq/libsq/core/lg/lga" - - "golang.org/x/exp/slog" - - "github.com/neilotoole/sq/libsq/core/stringz" - - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/ast" @@ -20,22 +13,7 @@ import ( "github.com/neilotoole/sq/libsq/core/sqlmodel" ) -var _ sqlbuilder.FragmentBuilder = (*fragBuilder)(nil) - -type fragBuilder struct { - sqlbuilder.BaseFragmentBuilder -} - -func newFragmentBuilder(log *slog.Logger) *fragBuilder { - r := &fragBuilder{} - r.Log = log - r.Quote = `"` - r.QuoteFn = stringz.DoubleQuote - r.Ops = sqlbuilder.BaseOps() - return r -} - -func (fb *fragBuilder) Range(rr *ast.RowRangeNode) (string, error) { +func renderRange(_ *render.Context, rr *ast.RowRangeNode) (string, error) { if rr == nil { return "", nil } @@ -56,7 +34,7 @@ func (fb *fragBuilder) Range(rr *ast.RowRangeNode) (string, error) { offset = rr.Offset } - buf := &bytes.Buffer{} + var buf strings.Builder buf.WriteString(fmt.Sprintf("OFFSET %d ROWS", offset)) if rr.Limit > -1 { @@ -64,17 +42,10 @@ func (fb *fragBuilder) Range(rr *ast.RowRangeNode) (string, error) { } sql := buf.String() - fb.Log.Debug("Returning SQL fragment", lga.SQL, sql) return sql, nil } -var _ sqlbuilder.QueryBuilder = (*queryBuilder)(nil) - -type queryBuilder struct { - sqlbuilder.BaseQueryBuilder -} - -func (qb *queryBuilder) Render() (string, error) { +func preRender(_ *render.Context, f *render.Fragments) error { // SQL Server handles range (OFFSET, LIMIT) a little differently. If the query has a range, // then the ORDER BY clause is required. If ORDER BY is not specified, we use a trick (SELECT 0) // to satisfy SQL Server. For example: @@ -83,13 +54,13 @@ func (qb *queryBuilder) Render() (string, error) { // ORDER BY (SELECT 0) // OFFSET 1 ROWS // FETCH NEXT 2 ROWS ONLY; - if qb.Range != "" { - if qb.OrderBy == "" { - qb.OrderBy = "ORDER BY (SELECT 0)" + if f.Range != "" { + if f.OrderBy == "" { + f.OrderBy = "ORDER BY (SELECT 0)" } } - return qb.BaseQueryBuilder.Render() + return nil } func dbTypeNameFromKind(knd kind.Kind) string { diff --git a/drivers/sqlserver/sqlserver.go b/drivers/sqlserver/sqlserver.go index 5c507ef3..ede0372b 100644 --- a/drivers/sqlserver/sqlserver.go +++ b/drivers/sqlserver/sqlserver.go @@ -9,6 +9,8 @@ import ( "strconv" "strings" + "github.com/neilotoole/sq/libsq/driver/dialect" + "github.com/neilotoole/sq/libsq/core/lg/lga" "github.com/neilotoole/sq/libsq/core/lg/lgm" @@ -19,7 +21,7 @@ import ( mssql "github.com/microsoft/go-mssqldb" - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/errz" "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/sqlmodel" @@ -71,12 +73,14 @@ func (d *driveri) DriverMetadata() driver.Metadata { } // Dialect implements driver.SQLDriver. -func (d *driveri) Dialect() driver.Dialect { - return driver.Dialect{ +func (d *driveri) Dialect() dialect.Dialect { + return dialect.Dialect{ Type: Type, Placeholders: placeholders, - Quote: '"', + IdentQuote: '"', + Enquote: stringz.DoubleQuote, MaxBatchValues: 1000, + Ops: dialect.DefaultOps(), } } @@ -103,9 +107,15 @@ func placeholders(numCols, numRows int) string { return strings.Join(rows, driver.Comma) } -// SQLBuilder implements driver.SQLDriver. -func (d *driveri) SQLBuilder() (sqlbuilder.FragmentBuilder, sqlbuilder.QueryBuilder) { - return newFragmentBuilder(d.log), &queryBuilder{} +// Renderer implements driver.SQLDriver. +func (d *driveri) Renderer() *render.Renderer { + r := render.NewDefaultRenderer() + + // Custom functions for SQLServer specific stuff. + r.Range = renderRange + r.PreRender = preRender + + return r } // Open implements driver.Driver. @@ -196,7 +206,7 @@ func (d *driveri) TableColumnTypes(ctx context.Context, db sqlz.DB, tblName stri const queryTpl = "SELECT %s FROM %s ORDER BY (SELECT 0) OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY" dialect := d.Dialect() - quote := string(dialect.Quote) + quote := string(dialect.IdentQuote) tblNameQuoted := stringz.Surround(tblName, quote) colsClause := "*" @@ -403,7 +413,7 @@ func (d *driveri) getTableColsMeta(ctx context.Context, db sqlz.DB, tblName stri const queryTpl = "SELECT %s FROM %s ORDER BY (SELECT 0) OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY" dialect := d.Dialect() - quote := string(dialect.Quote) + quote := string(dialect.IdentQuote) tblNameQuoted := stringz.Surround(tblName, quote) colNamesQuoted := stringz.SurroundSlice(colNames, quote) colsJoined := strings.Join(colNamesQuoted, driver.Comma) diff --git a/grammar/SLQ.g4 b/grammar/SLQ.g4 index f156d3d7..fecc87fd 100644 --- a/grammar/SLQ.g4 +++ b/grammar/SLQ.g4 @@ -150,6 +150,8 @@ ALIAS_RESERVED ARG: '$' ID; +arg : ARG; + // handleTable is a handle.table pair. // - @my1.user handleTable: HANDLE NAME; @@ -188,6 +190,7 @@ rowRange: expr: selector | literal + | arg | unaryOperator expr | expr '||' expr | expr ( '*' | '/' | '%') expr @@ -203,6 +206,7 @@ literal: NN | NUMBER | STRING | NULL; unaryOperator: '-' | '+' | '~' | '!'; +NULL: 'null'; ID: [a-zA-Z_][a-zA-Z0-9_]*; WS: [ \t\r\n]+ -> skip; LPAR: '('; @@ -212,7 +216,7 @@ RBRA: ']'; COMMA: ','; PIPE: '|'; COLON: ':'; -NULL: 'null' | 'NULL'; + // NN: Natural Number {0,1,2,3, ...} NN: INTF; diff --git a/libsq/ast/arg.go b/libsq/ast/arg.go new file mode 100644 index 00000000..d8d564b7 --- /dev/null +++ b/libsq/ast/arg.go @@ -0,0 +1,37 @@ +package ast + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/ast/internal/slq" +) + +// ArgNode implements the SQL "DISTINCT" clause. +type ArgNode struct { + baseNode + key string +} + +// String returns a log/debug-friendly representation. +func (n *ArgNode) String() string { + return nodeString(n) +} + +// Key returns the arg key. If the arg is "$name", the key is "name". +func (n *ArgNode) Key() string { + return n.key +} + +// VisitArg implements slq.SLQVisitor. +func (v *parseTreeVisitor) VisitArg(ctx *slq.ArgContext) interface{} { + node := &ArgNode{} + node.ctx = ctx + node.text = ctx.GetText() + + if ctx.ARG() != nil { + // The node text will be "$key". We need to trim the $ prefix. + node.key = strings.TrimPrefix(ctx.ARG().GetText(), "$") + } + + return v.cur.AddChild(node) +} diff --git a/libsq/ast/ast.go b/libsq/ast/ast.go index f89c6871..a0eea1d4 100644 --- a/libsq/ast/ast.go +++ b/libsq/ast/ast.go @@ -31,7 +31,7 @@ func Parse(log *slog.Logger, input string) (*AST, error) { //nolint:staticcheck return nil, err } - if err := verify(log, ast); err != nil { + if err := verify(ast); err != nil { return nil, err } @@ -68,7 +68,7 @@ func buildAST(log *slog.Logger, query slq.IQueryContext) (*AST, error) { } for _, visitor := range visitors { - w := NewWalker(log, tree.ast).AddVisitor(visitor.typ, visitor.fn) + w := NewWalker(tree.ast).AddVisitor(visitor.typ, visitor.fn) if err := w.Walk(); err != nil { return nil, err } @@ -78,8 +78,8 @@ func buildAST(log *slog.Logger, query slq.IQueryContext) (*AST, error) { } // verify performs additional checks on the state of the built AST. -func verify(log *slog.Logger, ast *AST) error { - selCount := NewInspector(log, ast).CountNodes(typeSelectorNode) +func verify(ast *AST) error { + selCount := NewInspector(ast).CountNodes(typeSelectorNode) if selCount != 0 { return errorf("AST should have zero nodes of type %T but found %d", (*SelectorNode)(nil), selCount) diff --git a/libsq/ast/inspector.go b/libsq/ast/inspector.go index b84f9749..3250e9e7 100644 --- a/libsq/ast/inspector.go +++ b/libsq/ast/inspector.go @@ -3,35 +3,25 @@ package ast import ( "reflect" - "golang.org/x/exp/slog" - "github.com/samber/lo" - - "github.com/ryboe/q" ) // Inspector provides functionality for AST interrogation. type Inspector struct { - log *slog.Logger ast *AST } // NewInspector returns an Inspector instance for ast. -func NewInspector(log *slog.Logger, ast *AST) *Inspector { - return &Inspector{log: log, ast: ast} +func NewInspector(ast *AST) *Inspector { + return &Inspector{ast: ast} } // CountNodes counts the number of nodes having typ. func (in *Inspector) CountNodes(typ reflect.Type) int { count := 0 - w := NewWalker(in.log, in.ast) - w.AddVisitor(typ, func(log *slog.Logger, w *Walker, node Node) error { + w := NewWalker(in.ast) + w.AddVisitor(typ, func(w *Walker, node Node) error { count++ - if typ == typeSelectorNode { - // found it - // FIXME: delete this - q.Q("found it", node) - } return nil }) @@ -42,8 +32,8 @@ func (in *Inspector) CountNodes(typ reflect.Type) int { // FindNodes returns the nodes having typ. func (in *Inspector) FindNodes(typ reflect.Type) []Node { var nodes []Node - w := NewWalker(in.log, in.ast) - w.AddVisitor(typ, func(log *slog.Logger, w *Walker, node Node) error { + w := NewWalker(in.ast) + w.AddVisitor(typ, func(w *Walker, node Node) error { nodes = append(nodes, node) return nil }) @@ -59,14 +49,14 @@ func (in *Inspector) FindNodes(typ reflect.Type) []Node { func (in *Inspector) FindHandles() []string { var handles []string - if err := walkWith(in.log, in.ast, typeHandleNode, func(log *slog.Logger, walker *Walker, node Node) error { + if err := walkWith(in.ast, typeHandleNode, func(walker *Walker, node Node) error { handles = append(handles, node.Text()) return nil }); err != nil { panic(err) } - if err := walkWith(in.log, in.ast, typeTblSelectorNode, func(log *slog.Logger, walker *Walker, node Node) error { + if err := walkWith(in.ast, typeTblSelectorNode, func(walker *Walker, node Node) error { n, _ := node.(*TblSelectorNode) if n.handle != "" { handles = append(handles, n.handle) diff --git a/libsq/ast/inspector_test.go b/libsq/ast/inspector_test.go index 4fe57423..0f136072 100644 --- a/libsq/ast/inspector_test.go +++ b/libsq/ast/inspector_test.go @@ -3,21 +3,17 @@ package ast import ( "testing" - "github.com/neilotoole/slogt" - "github.com/stretchr/testify/require" ) func TestInspector_findSelectableSegments(t *testing.T) { - log := slogt.New(t) - // `@mydb1 | .user | .uid, .username` ast, err := buildInitialAST(t, fixtSelect1) require.Nil(t, err) - err = NewWalker(log, ast).AddVisitor(typeSelectorNode, narrowTblSel).Walk() + err = NewWalker(ast).AddVisitor(typeSelectorNode, narrowTblSel).Walk() require.Nil(t, err) - insp := NewInspector(log, ast) + insp := NewInspector(ast) segs := ast.Segments() require.Equal(t, 3, len(segs)) @@ -31,9 +27,9 @@ func TestInspector_findSelectableSegments(t *testing.T) { // `@mydb1 | .user, .address | join(.user.uid == .address.uid) | .uid, .username, .country` ast, err = buildInitialAST(t, fixtJoinQuery1) require.Nil(t, err) - err = NewWalker(log, ast).AddVisitor(typeSelectorNode, narrowTblSel).Walk() + err = NewWalker(ast).AddVisitor(typeSelectorNode, narrowTblSel).Walk() require.Nil(t, err) - insp = NewInspector(log, ast) + insp = NewInspector(ast) segs = ast.Segments() require.Equal(t, 4, len(segs)) diff --git a/libsq/ast/internal/slq/SLQ.interp b/libsq/ast/internal/slq/SLQ.interp index 78abc061..bd594b52 100644 --- a/libsq/ast/internal/slq/SLQ.interp +++ b/libsq/ast/internal/slq/SLQ.interp @@ -21,6 +21,7 @@ null null null null +'null' null null '(' @@ -32,7 +33,6 @@ null ':' null null -null '<=' '<' '>=' @@ -67,6 +67,7 @@ ORDER_DESC ORDER_BY ALIAS_RESERVED ARG +NULL ID WS LPAR @@ -76,7 +77,6 @@ RBRA COMMA PIPE COLON -NULL NN NUMBER LT_EQ @@ -110,6 +110,7 @@ orderBy selector selectorElement alias +arg handleTable handle rowRange @@ -119,4 +120,4 @@ unaryOperator atn: -[4, 1, 43, 258, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 1, 0, 5, 0, 52, 8, 0, 10, 0, 12, 0, 55, 9, 0, 1, 0, 1, 0, 4, 0, 59, 8, 0, 11, 0, 12, 0, 60, 1, 0, 5, 0, 64, 8, 0, 10, 0, 12, 0, 67, 9, 0, 1, 0, 5, 0, 70, 8, 0, 10, 0, 12, 0, 73, 9, 0, 1, 1, 1, 1, 1, 1, 5, 1, 78, 8, 1, 10, 1, 12, 1, 81, 9, 1, 1, 2, 1, 2, 1, 2, 5, 2, 86, 8, 2, 10, 2, 12, 2, 89, 9, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 102, 8, 3, 1, 4, 1, 4, 1, 5, 1, 5, 3, 5, 108, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 115, 8, 6, 10, 6, 12, 6, 118, 9, 6, 1, 6, 3, 6, 121, 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 137, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 3, 11, 144, 8, 11, 1, 11, 3, 11, 147, 8, 11, 1, 11, 3, 11, 150, 8, 11, 1, 12, 1, 12, 3, 12, 154, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 161, 8, 13, 10, 13, 12, 13, 164, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 3, 14, 170, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 177, 8, 15, 10, 15, 12, 15, 180, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 186, 8, 16, 1, 17, 1, 17, 3, 17, 190, 8, 17, 1, 18, 1, 18, 1, 18, 3, 18, 195, 8, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 211, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 222, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 243, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 249, 8, 22, 10, 22, 12, 22, 252, 9, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 0, 1, 44, 25, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 0, 8, 1, 0, 34, 39, 1, 0, 17, 18, 1, 0, 21, 22, 2, 0, 2, 2, 8, 9, 1, 0, 10, 12, 1, 0, 34, 37, 2, 0, 31, 33, 42, 42, 2, 0, 14, 15, 17, 18, 279, 0, 53, 1, 0, 0, 0, 2, 74, 1, 0, 0, 0, 4, 82, 1, 0, 0, 0, 6, 101, 1, 0, 0, 0, 8, 103, 1, 0, 0, 0, 10, 105, 1, 0, 0, 0, 12, 109, 1, 0, 0, 0, 14, 124, 1, 0, 0, 0, 16, 126, 1, 0, 0, 0, 18, 136, 1, 0, 0, 0, 20, 138, 1, 0, 0, 0, 22, 140, 1, 0, 0, 0, 24, 153, 1, 0, 0, 0, 26, 155, 1, 0, 0, 0, 28, 167, 1, 0, 0, 0, 30, 171, 1, 0, 0, 0, 32, 183, 1, 0, 0, 0, 34, 187, 1, 0, 0, 0, 36, 194, 1, 0, 0, 0, 38, 196, 1, 0, 0, 0, 40, 199, 1, 0, 0, 0, 42, 201, 1, 0, 0, 0, 44, 221, 1, 0, 0, 0, 46, 253, 1, 0, 0, 0, 48, 255, 1, 0, 0, 0, 50, 52, 5, 1, 0, 0, 51, 50, 1, 0, 0, 0, 52, 55, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 53, 54, 1, 0, 0, 0, 54, 56, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 56, 65, 3, 2, 1, 0, 57, 59, 5, 1, 0, 0, 58, 57, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 58, 1, 0, 0, 0, 60, 61, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 64, 3, 2, 1, 0, 63, 58, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 71, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 70, 5, 1, 0, 0, 69, 68, 1, 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 1, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 79, 3, 4, 2, 0, 75, 76, 5, 29, 0, 0, 76, 78, 3, 4, 2, 0, 77, 75, 1, 0, 0, 0, 78, 81, 1, 0, 0, 0, 79, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 3, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 82, 87, 3, 6, 3, 0, 83, 84, 5, 28, 0, 0, 84, 86, 3, 6, 3, 0, 85, 83, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 5, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 102, 3, 38, 19, 0, 91, 102, 3, 40, 20, 0, 92, 102, 3, 34, 17, 0, 93, 102, 3, 16, 8, 0, 94, 102, 3, 26, 13, 0, 95, 102, 3, 30, 15, 0, 96, 102, 3, 42, 21, 0, 97, 102, 3, 20, 10, 0, 98, 102, 3, 22, 11, 0, 99, 102, 3, 10, 5, 0, 100, 102, 3, 44, 22, 0, 101, 90, 1, 0, 0, 0, 101, 91, 1, 0, 0, 0, 101, 92, 1, 0, 0, 0, 101, 93, 1, 0, 0, 0, 101, 94, 1, 0, 0, 0, 101, 95, 1, 0, 0, 0, 101, 96, 1, 0, 0, 0, 101, 97, 1, 0, 0, 0, 101, 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 100, 1, 0, 0, 0, 102, 7, 1, 0, 0, 0, 103, 104, 7, 0, 0, 0, 104, 9, 1, 0, 0, 0, 105, 107, 3, 12, 6, 0, 106, 108, 3, 36, 18, 0, 107, 106, 1, 0, 0, 0, 107, 108, 1, 0, 0, 0, 108, 11, 1, 0, 0, 0, 109, 110, 3, 14, 7, 0, 110, 120, 5, 24, 0, 0, 111, 116, 3, 44, 22, 0, 112, 113, 5, 28, 0, 0, 113, 115, 3, 44, 22, 0, 114, 112, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 121, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, 121, 5, 2, 0, 0, 120, 111, 1, 0, 0, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 25, 0, 0, 123, 13, 1, 0, 0, 0, 124, 125, 5, 22, 0, 0, 125, 15, 1, 0, 0, 0, 126, 127, 5, 3, 0, 0, 127, 128, 5, 24, 0, 0, 128, 129, 3, 18, 9, 0, 129, 130, 5, 25, 0, 0, 130, 17, 1, 0, 0, 0, 131, 132, 3, 32, 16, 0, 132, 133, 3, 8, 4, 0, 133, 134, 3, 32, 16, 0, 134, 137, 1, 0, 0, 0, 135, 137, 3, 32, 16, 0, 136, 131, 1, 0, 0, 0, 136, 135, 1, 0, 0, 0, 137, 19, 1, 0, 0, 0, 138, 139, 5, 4, 0, 0, 139, 21, 1, 0, 0, 0, 140, 146, 5, 5, 0, 0, 141, 143, 5, 24, 0, 0, 142, 144, 3, 32, 16, 0, 143, 142, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 145, 1, 0, 0, 0, 145, 147, 5, 25, 0, 0, 146, 141, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 3, 36, 18, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 23, 1, 0, 0, 0, 151, 154, 3, 32, 16, 0, 152, 154, 3, 12, 6, 0, 153, 151, 1, 0, 0, 0, 153, 152, 1, 0, 0, 0, 154, 25, 1, 0, 0, 0, 155, 156, 5, 16, 0, 0, 156, 157, 5, 24, 0, 0, 157, 162, 3, 24, 12, 0, 158, 159, 5, 28, 0, 0, 159, 161, 3, 24, 12, 0, 160, 158, 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 5, 25, 0, 0, 166, 27, 1, 0, 0, 0, 167, 169, 3, 32, 16, 0, 168, 170, 7, 1, 0, 0, 169, 168, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 29, 1, 0, 0, 0, 171, 172, 5, 19, 0, 0, 172, 173, 5, 24, 0, 0, 173, 178, 3, 28, 14, 0, 174, 175, 5, 28, 0, 0, 175, 177, 3, 28, 14, 0, 176, 174, 1, 0, 0, 0, 177, 180, 1, 0, 0, 0, 178, 176, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 181, 1, 0, 0, 0, 180, 178, 1, 0, 0, 0, 181, 182, 5, 25, 0, 0, 182, 31, 1, 0, 0, 0, 183, 185, 5, 40, 0, 0, 184, 186, 5, 40, 0, 0, 185, 184, 1, 0, 0, 0, 185, 186, 1, 0, 0, 0, 186, 33, 1, 0, 0, 0, 187, 189, 3, 32, 16, 0, 188, 190, 3, 36, 18, 0, 189, 188, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 35, 1, 0, 0, 0, 191, 195, 5, 20, 0, 0, 192, 193, 5, 30, 0, 0, 193, 195, 7, 2, 0, 0, 194, 191, 1, 0, 0, 0, 194, 192, 1, 0, 0, 0, 195, 37, 1, 0, 0, 0, 196, 197, 5, 41, 0, 0, 197, 198, 5, 40, 0, 0, 198, 39, 1, 0, 0, 0, 199, 200, 5, 41, 0, 0, 200, 41, 1, 0, 0, 0, 201, 210, 5, 6, 0, 0, 202, 203, 5, 32, 0, 0, 203, 204, 5, 30, 0, 0, 204, 211, 5, 32, 0, 0, 205, 206, 5, 32, 0, 0, 206, 211, 5, 30, 0, 0, 207, 208, 5, 30, 0, 0, 208, 211, 5, 32, 0, 0, 209, 211, 5, 32, 0, 0, 210, 202, 1, 0, 0, 0, 210, 205, 1, 0, 0, 0, 210, 207, 1, 0, 0, 0, 210, 209, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 212, 1, 0, 0, 0, 212, 213, 5, 27, 0, 0, 213, 43, 1, 0, 0, 0, 214, 215, 6, 22, -1, 0, 215, 222, 3, 32, 16, 0, 216, 222, 3, 46, 23, 0, 217, 218, 3, 48, 24, 0, 218, 219, 3, 44, 22, 9, 219, 222, 1, 0, 0, 0, 220, 222, 3, 12, 6, 0, 221, 214, 1, 0, 0, 0, 221, 216, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 250, 1, 0, 0, 0, 223, 224, 10, 8, 0, 0, 224, 225, 5, 7, 0, 0, 225, 249, 3, 44, 22, 9, 226, 227, 10, 7, 0, 0, 227, 228, 7, 3, 0, 0, 228, 249, 3, 44, 22, 8, 229, 230, 10, 6, 0, 0, 230, 231, 7, 1, 0, 0, 231, 249, 3, 44, 22, 7, 232, 233, 10, 5, 0, 0, 233, 234, 7, 4, 0, 0, 234, 249, 3, 44, 22, 6, 235, 236, 10, 4, 0, 0, 236, 237, 7, 5, 0, 0, 237, 249, 3, 44, 22, 5, 238, 242, 10, 3, 0, 0, 239, 243, 5, 39, 0, 0, 240, 243, 5, 38, 0, 0, 241, 243, 1, 0, 0, 0, 242, 239, 1, 0, 0, 0, 242, 240, 1, 0, 0, 0, 242, 241, 1, 0, 0, 0, 243, 244, 1, 0, 0, 0, 244, 249, 3, 44, 22, 4, 245, 246, 10, 2, 0, 0, 246, 247, 5, 13, 0, 0, 247, 249, 3, 44, 22, 3, 248, 223, 1, 0, 0, 0, 248, 226, 1, 0, 0, 0, 248, 229, 1, 0, 0, 0, 248, 232, 1, 0, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 45, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 254, 7, 6, 0, 0, 254, 47, 1, 0, 0, 0, 255, 256, 7, 7, 0, 0, 256, 49, 1, 0, 0, 0, 26, 53, 60, 65, 71, 79, 87, 101, 107, 116, 120, 136, 143, 146, 149, 153, 162, 169, 178, 185, 189, 194, 210, 221, 242, 248, 250] \ No newline at end of file +[4, 1, 43, 263, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 1, 0, 5, 0, 54, 8, 0, 10, 0, 12, 0, 57, 9, 0, 1, 0, 1, 0, 4, 0, 61, 8, 0, 11, 0, 12, 0, 62, 1, 0, 5, 0, 66, 8, 0, 10, 0, 12, 0, 69, 9, 0, 1, 0, 5, 0, 72, 8, 0, 10, 0, 12, 0, 75, 9, 0, 1, 1, 1, 1, 1, 1, 5, 1, 80, 8, 1, 10, 1, 12, 1, 83, 9, 1, 1, 2, 1, 2, 1, 2, 5, 2, 88, 8, 2, 10, 2, 12, 2, 91, 9, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 104, 8, 3, 1, 4, 1, 4, 1, 5, 1, 5, 3, 5, 110, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 117, 8, 6, 10, 6, 12, 6, 120, 9, 6, 1, 6, 3, 6, 123, 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 139, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 3, 11, 146, 8, 11, 1, 11, 3, 11, 149, 8, 11, 1, 11, 3, 11, 152, 8, 11, 1, 12, 1, 12, 3, 12, 156, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 163, 8, 13, 10, 13, 12, 13, 166, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 3, 14, 172, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 179, 8, 15, 10, 15, 12, 15, 182, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 188, 8, 16, 1, 17, 1, 17, 3, 17, 192, 8, 17, 1, 18, 1, 18, 1, 18, 3, 18, 197, 8, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 215, 8, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 227, 8, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 248, 8, 23, 1, 23, 1, 23, 1, 23, 1, 23, 5, 23, 254, 8, 23, 10, 23, 12, 23, 257, 9, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 0, 1, 46, 26, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 0, 8, 1, 0, 34, 39, 1, 0, 17, 18, 2, 0, 21, 21, 23, 23, 2, 0, 2, 2, 8, 9, 1, 0, 10, 12, 1, 0, 34, 37, 3, 0, 22, 22, 32, 33, 42, 42, 2, 0, 14, 15, 17, 18, 284, 0, 55, 1, 0, 0, 0, 2, 76, 1, 0, 0, 0, 4, 84, 1, 0, 0, 0, 6, 103, 1, 0, 0, 0, 8, 105, 1, 0, 0, 0, 10, 107, 1, 0, 0, 0, 12, 111, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, 18, 138, 1, 0, 0, 0, 20, 140, 1, 0, 0, 0, 22, 142, 1, 0, 0, 0, 24, 155, 1, 0, 0, 0, 26, 157, 1, 0, 0, 0, 28, 169, 1, 0, 0, 0, 30, 173, 1, 0, 0, 0, 32, 185, 1, 0, 0, 0, 34, 189, 1, 0, 0, 0, 36, 196, 1, 0, 0, 0, 38, 198, 1, 0, 0, 0, 40, 200, 1, 0, 0, 0, 42, 203, 1, 0, 0, 0, 44, 205, 1, 0, 0, 0, 46, 226, 1, 0, 0, 0, 48, 258, 1, 0, 0, 0, 50, 260, 1, 0, 0, 0, 52, 54, 5, 1, 0, 0, 53, 52, 1, 0, 0, 0, 54, 57, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 58, 1, 0, 0, 0, 57, 55, 1, 0, 0, 0, 58, 67, 3, 2, 1, 0, 59, 61, 5, 1, 0, 0, 60, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 60, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 66, 3, 2, 1, 0, 65, 60, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 73, 1, 0, 0, 0, 69, 67, 1, 0, 0, 0, 70, 72, 5, 1, 0, 0, 71, 70, 1, 0, 0, 0, 72, 75, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, 74, 1, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 76, 81, 3, 4, 2, 0, 77, 78, 5, 30, 0, 0, 78, 80, 3, 4, 2, 0, 79, 77, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 3, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 89, 3, 6, 3, 0, 85, 86, 5, 29, 0, 0, 86, 88, 3, 6, 3, 0, 87, 85, 1, 0, 0, 0, 88, 91, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 5, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 92, 104, 3, 40, 20, 0, 93, 104, 3, 42, 21, 0, 94, 104, 3, 34, 17, 0, 95, 104, 3, 16, 8, 0, 96, 104, 3, 26, 13, 0, 97, 104, 3, 30, 15, 0, 98, 104, 3, 44, 22, 0, 99, 104, 3, 20, 10, 0, 100, 104, 3, 22, 11, 0, 101, 104, 3, 10, 5, 0, 102, 104, 3, 46, 23, 0, 103, 92, 1, 0, 0, 0, 103, 93, 1, 0, 0, 0, 103, 94, 1, 0, 0, 0, 103, 95, 1, 0, 0, 0, 103, 96, 1, 0, 0, 0, 103, 97, 1, 0, 0, 0, 103, 98, 1, 0, 0, 0, 103, 99, 1, 0, 0, 0, 103, 100, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 102, 1, 0, 0, 0, 104, 7, 1, 0, 0, 0, 105, 106, 7, 0, 0, 0, 106, 9, 1, 0, 0, 0, 107, 109, 3, 12, 6, 0, 108, 110, 3, 36, 18, 0, 109, 108, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 11, 1, 0, 0, 0, 111, 112, 3, 14, 7, 0, 112, 122, 5, 25, 0, 0, 113, 118, 3, 46, 23, 0, 114, 115, 5, 29, 0, 0, 115, 117, 3, 46, 23, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 123, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 121, 123, 5, 2, 0, 0, 122, 113, 1, 0, 0, 0, 122, 121, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 125, 5, 26, 0, 0, 125, 13, 1, 0, 0, 0, 126, 127, 5, 23, 0, 0, 127, 15, 1, 0, 0, 0, 128, 129, 5, 3, 0, 0, 129, 130, 5, 25, 0, 0, 130, 131, 3, 18, 9, 0, 131, 132, 5, 26, 0, 0, 132, 17, 1, 0, 0, 0, 133, 134, 3, 32, 16, 0, 134, 135, 3, 8, 4, 0, 135, 136, 3, 32, 16, 0, 136, 139, 1, 0, 0, 0, 137, 139, 3, 32, 16, 0, 138, 133, 1, 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 19, 1, 0, 0, 0, 140, 141, 5, 4, 0, 0, 141, 21, 1, 0, 0, 0, 142, 148, 5, 5, 0, 0, 143, 145, 5, 25, 0, 0, 144, 146, 3, 32, 16, 0, 145, 144, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 5, 26, 0, 0, 148, 143, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 151, 1, 0, 0, 0, 150, 152, 3, 36, 18, 0, 151, 150, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 23, 1, 0, 0, 0, 153, 156, 3, 32, 16, 0, 154, 156, 3, 12, 6, 0, 155, 153, 1, 0, 0, 0, 155, 154, 1, 0, 0, 0, 156, 25, 1, 0, 0, 0, 157, 158, 5, 16, 0, 0, 158, 159, 5, 25, 0, 0, 159, 164, 3, 24, 12, 0, 160, 161, 5, 29, 0, 0, 161, 163, 3, 24, 12, 0, 162, 160, 1, 0, 0, 0, 163, 166, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 167, 1, 0, 0, 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 26, 0, 0, 168, 27, 1, 0, 0, 0, 169, 171, 3, 32, 16, 0, 170, 172, 7, 1, 0, 0, 171, 170, 1, 0, 0, 0, 171, 172, 1, 0, 0, 0, 172, 29, 1, 0, 0, 0, 173, 174, 5, 19, 0, 0, 174, 175, 5, 25, 0, 0, 175, 180, 3, 28, 14, 0, 176, 177, 5, 29, 0, 0, 177, 179, 3, 28, 14, 0, 178, 176, 1, 0, 0, 0, 179, 182, 1, 0, 0, 0, 180, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 183, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 183, 184, 5, 26, 0, 0, 184, 31, 1, 0, 0, 0, 185, 187, 5, 40, 0, 0, 186, 188, 5, 40, 0, 0, 187, 186, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 33, 1, 0, 0, 0, 189, 191, 3, 32, 16, 0, 190, 192, 3, 36, 18, 0, 191, 190, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 35, 1, 0, 0, 0, 193, 197, 5, 20, 0, 0, 194, 195, 5, 31, 0, 0, 195, 197, 7, 2, 0, 0, 196, 193, 1, 0, 0, 0, 196, 194, 1, 0, 0, 0, 197, 37, 1, 0, 0, 0, 198, 199, 5, 21, 0, 0, 199, 39, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 202, 5, 40, 0, 0, 202, 41, 1, 0, 0, 0, 203, 204, 5, 41, 0, 0, 204, 43, 1, 0, 0, 0, 205, 214, 5, 6, 0, 0, 206, 207, 5, 32, 0, 0, 207, 208, 5, 31, 0, 0, 208, 215, 5, 32, 0, 0, 209, 210, 5, 32, 0, 0, 210, 215, 5, 31, 0, 0, 211, 212, 5, 31, 0, 0, 212, 215, 5, 32, 0, 0, 213, 215, 5, 32, 0, 0, 214, 206, 1, 0, 0, 0, 214, 209, 1, 0, 0, 0, 214, 211, 1, 0, 0, 0, 214, 213, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 217, 5, 28, 0, 0, 217, 45, 1, 0, 0, 0, 218, 219, 6, 23, -1, 0, 219, 227, 3, 32, 16, 0, 220, 227, 3, 48, 24, 0, 221, 227, 3, 38, 19, 0, 222, 223, 3, 50, 25, 0, 223, 224, 3, 46, 23, 9, 224, 227, 1, 0, 0, 0, 225, 227, 3, 12, 6, 0, 226, 218, 1, 0, 0, 0, 226, 220, 1, 0, 0, 0, 226, 221, 1, 0, 0, 0, 226, 222, 1, 0, 0, 0, 226, 225, 1, 0, 0, 0, 227, 255, 1, 0, 0, 0, 228, 229, 10, 8, 0, 0, 229, 230, 5, 7, 0, 0, 230, 254, 3, 46, 23, 9, 231, 232, 10, 7, 0, 0, 232, 233, 7, 3, 0, 0, 233, 254, 3, 46, 23, 8, 234, 235, 10, 6, 0, 0, 235, 236, 7, 1, 0, 0, 236, 254, 3, 46, 23, 7, 237, 238, 10, 5, 0, 0, 238, 239, 7, 4, 0, 0, 239, 254, 3, 46, 23, 6, 240, 241, 10, 4, 0, 0, 241, 242, 7, 5, 0, 0, 242, 254, 3, 46, 23, 5, 243, 247, 10, 3, 0, 0, 244, 248, 5, 39, 0, 0, 245, 248, 5, 38, 0, 0, 246, 248, 1, 0, 0, 0, 247, 244, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 246, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 254, 3, 46, 23, 4, 250, 251, 10, 2, 0, 0, 251, 252, 5, 13, 0, 0, 252, 254, 3, 46, 23, 3, 253, 228, 1, 0, 0, 0, 253, 231, 1, 0, 0, 0, 253, 234, 1, 0, 0, 0, 253, 237, 1, 0, 0, 0, 253, 240, 1, 0, 0, 0, 253, 243, 1, 0, 0, 0, 253, 250, 1, 0, 0, 0, 254, 257, 1, 0, 0, 0, 255, 253, 1, 0, 0, 0, 255, 256, 1, 0, 0, 0, 256, 47, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 258, 259, 7, 6, 0, 0, 259, 49, 1, 0, 0, 0, 260, 261, 7, 7, 0, 0, 261, 51, 1, 0, 0, 0, 26, 55, 62, 67, 73, 81, 89, 103, 109, 118, 122, 138, 145, 148, 151, 155, 164, 171, 180, 187, 191, 196, 214, 226, 247, 253, 255] \ No newline at end of file diff --git a/libsq/ast/internal/slq/SLQ.tokens b/libsq/ast/internal/slq/SLQ.tokens index cc3a584e..1c47f05b 100644 --- a/libsq/ast/internal/slq/SLQ.tokens +++ b/libsq/ast/internal/slq/SLQ.tokens @@ -19,16 +19,16 @@ ORDER_DESC=18 ORDER_BY=19 ALIAS_RESERVED=20 ARG=21 -ID=22 -WS=23 -LPAR=24 -RPAR=25 -LBRA=26 -RBRA=27 -COMMA=28 -PIPE=29 -COLON=30 -NULL=31 +NULL=22 +ID=23 +WS=24 +LPAR=25 +RPAR=26 +LBRA=27 +RBRA=28 +COMMA=29 +PIPE=30 +COLON=31 NN=32 NUMBER=33 LT_EQ=34 @@ -59,13 +59,14 @@ LINECOMMENT=43 'group_by'=16 '+'=17 '-'=18 -'('=24 -')'=25 -'['=26 -']'=27 -','=28 -'|'=29 -':'=30 +'null'=22 +'('=25 +')'=26 +'['=27 +']'=28 +','=29 +'|'=30 +':'=31 '<='=34 '<'=35 '>='=36 diff --git a/libsq/ast/internal/slq/SLQLexer.interp b/libsq/ast/internal/slq/SLQLexer.interp index 412ea78d..1fd6e9f8 100644 --- a/libsq/ast/internal/slq/SLQLexer.interp +++ b/libsq/ast/internal/slq/SLQLexer.interp @@ -21,6 +21,7 @@ null null null null +'null' null null '(' @@ -32,7 +33,6 @@ null ':' null null -null '<=' '<' '>=' @@ -67,6 +67,7 @@ ORDER_DESC ORDER_BY ALIAS_RESERVED ARG +NULL ID WS LPAR @@ -76,7 +77,6 @@ RBRA COMMA PIPE COLON -NULL NN NUMBER LT_EQ @@ -112,6 +112,7 @@ ORDER_DESC ORDER_BY ALIAS_RESERVED ARG +NULL ID WS LPAR @@ -121,7 +122,6 @@ RBRA COMMA PIPE COLON -NULL NN NUMBER INTF @@ -175,4 +175,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 43, 484, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 227, 8, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 3, 19, 285, 8, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 5, 21, 292, 8, 21, 10, 21, 12, 21, 295, 9, 21, 1, 22, 4, 22, 298, 8, 22, 11, 22, 12, 22, 299, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 326, 8, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 332, 8, 32, 1, 32, 1, 32, 1, 32, 4, 32, 337, 8, 32, 11, 32, 12, 32, 338, 1, 32, 3, 32, 342, 8, 32, 1, 32, 3, 32, 345, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 351, 8, 32, 1, 32, 3, 32, 354, 8, 32, 1, 33, 1, 33, 1, 33, 5, 33, 359, 8, 33, 10, 33, 12, 33, 362, 9, 33, 3, 33, 364, 8, 33, 1, 34, 1, 34, 3, 34, 368, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 392, 8, 41, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 5, 43, 400, 8, 43, 10, 43, 12, 43, 403, 9, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 3, 44, 410, 8, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 5, 74, 476, 8, 74, 10, 74, 12, 74, 479, 9, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 477, 0, 75, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 0, 69, 0, 71, 34, 73, 35, 75, 36, 77, 37, 79, 38, 81, 39, 83, 40, 85, 41, 87, 42, 89, 0, 91, 0, 93, 0, 95, 0, 97, 0, 99, 0, 101, 0, 103, 0, 105, 0, 107, 0, 109, 0, 111, 0, 113, 0, 115, 0, 117, 0, 119, 0, 121, 0, 123, 0, 125, 0, 127, 0, 129, 0, 131, 0, 133, 0, 135, 0, 137, 0, 139, 0, 141, 0, 143, 0, 145, 0, 147, 0, 149, 43, 1, 0, 35, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 1, 0, 49, 57, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 479, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 1, 151, 1, 0, 0, 0, 3, 153, 1, 0, 0, 0, 5, 155, 1, 0, 0, 0, 7, 160, 1, 0, 0, 0, 9, 167, 1, 0, 0, 0, 11, 173, 1, 0, 0, 0, 13, 176, 1, 0, 0, 0, 15, 179, 1, 0, 0, 0, 17, 181, 1, 0, 0, 0, 19, 183, 1, 0, 0, 0, 21, 186, 1, 0, 0, 0, 23, 189, 1, 0, 0, 0, 25, 191, 1, 0, 0, 0, 27, 194, 1, 0, 0, 0, 29, 196, 1, 0, 0, 0, 31, 198, 1, 0, 0, 0, 33, 207, 1, 0, 0, 0, 35, 209, 1, 0, 0, 0, 37, 226, 1, 0, 0, 0, 39, 284, 1, 0, 0, 0, 41, 286, 1, 0, 0, 0, 43, 289, 1, 0, 0, 0, 45, 297, 1, 0, 0, 0, 47, 303, 1, 0, 0, 0, 49, 305, 1, 0, 0, 0, 51, 307, 1, 0, 0, 0, 53, 309, 1, 0, 0, 0, 55, 311, 1, 0, 0, 0, 57, 313, 1, 0, 0, 0, 59, 315, 1, 0, 0, 0, 61, 325, 1, 0, 0, 0, 63, 327, 1, 0, 0, 0, 65, 353, 1, 0, 0, 0, 67, 363, 1, 0, 0, 0, 69, 365, 1, 0, 0, 0, 71, 371, 1, 0, 0, 0, 73, 374, 1, 0, 0, 0, 75, 376, 1, 0, 0, 0, 77, 379, 1, 0, 0, 0, 79, 381, 1, 0, 0, 0, 81, 384, 1, 0, 0, 0, 83, 387, 1, 0, 0, 0, 85, 393, 1, 0, 0, 0, 87, 396, 1, 0, 0, 0, 89, 406, 1, 0, 0, 0, 91, 411, 1, 0, 0, 0, 93, 417, 1, 0, 0, 0, 95, 419, 1, 0, 0, 0, 97, 421, 1, 0, 0, 0, 99, 423, 1, 0, 0, 0, 101, 425, 1, 0, 0, 0, 103, 427, 1, 0, 0, 0, 105, 429, 1, 0, 0, 0, 107, 431, 1, 0, 0, 0, 109, 433, 1, 0, 0, 0, 111, 435, 1, 0, 0, 0, 113, 437, 1, 0, 0, 0, 115, 439, 1, 0, 0, 0, 117, 441, 1, 0, 0, 0, 119, 443, 1, 0, 0, 0, 121, 445, 1, 0, 0, 0, 123, 447, 1, 0, 0, 0, 125, 449, 1, 0, 0, 0, 127, 451, 1, 0, 0, 0, 129, 453, 1, 0, 0, 0, 131, 455, 1, 0, 0, 0, 133, 457, 1, 0, 0, 0, 135, 459, 1, 0, 0, 0, 137, 461, 1, 0, 0, 0, 139, 463, 1, 0, 0, 0, 141, 465, 1, 0, 0, 0, 143, 467, 1, 0, 0, 0, 145, 469, 1, 0, 0, 0, 147, 471, 1, 0, 0, 0, 149, 473, 1, 0, 0, 0, 151, 152, 5, 59, 0, 0, 152, 2, 1, 0, 0, 0, 153, 154, 5, 42, 0, 0, 154, 4, 1, 0, 0, 0, 155, 156, 5, 106, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 105, 0, 0, 158, 159, 5, 110, 0, 0, 159, 6, 1, 0, 0, 0, 160, 161, 5, 117, 0, 0, 161, 162, 5, 110, 0, 0, 162, 163, 5, 105, 0, 0, 163, 164, 5, 113, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 101, 0, 0, 166, 8, 1, 0, 0, 0, 167, 168, 5, 99, 0, 0, 168, 169, 5, 111, 0, 0, 169, 170, 5, 117, 0, 0, 170, 171, 5, 110, 0, 0, 171, 172, 5, 116, 0, 0, 172, 10, 1, 0, 0, 0, 173, 174, 5, 46, 0, 0, 174, 175, 5, 91, 0, 0, 175, 12, 1, 0, 0, 0, 176, 177, 5, 124, 0, 0, 177, 178, 5, 124, 0, 0, 178, 14, 1, 0, 0, 0, 179, 180, 5, 47, 0, 0, 180, 16, 1, 0, 0, 0, 181, 182, 5, 37, 0, 0, 182, 18, 1, 0, 0, 0, 183, 184, 5, 60, 0, 0, 184, 185, 5, 60, 0, 0, 185, 20, 1, 0, 0, 0, 186, 187, 5, 62, 0, 0, 187, 188, 5, 62, 0, 0, 188, 22, 1, 0, 0, 0, 189, 190, 5, 38, 0, 0, 190, 24, 1, 0, 0, 0, 191, 192, 5, 38, 0, 0, 192, 193, 5, 38, 0, 0, 193, 26, 1, 0, 0, 0, 194, 195, 5, 126, 0, 0, 195, 28, 1, 0, 0, 0, 196, 197, 5, 33, 0, 0, 197, 30, 1, 0, 0, 0, 198, 199, 5, 103, 0, 0, 199, 200, 5, 114, 0, 0, 200, 201, 5, 111, 0, 0, 201, 202, 5, 117, 0, 0, 202, 203, 5, 112, 0, 0, 203, 204, 5, 95, 0, 0, 204, 205, 5, 98, 0, 0, 205, 206, 5, 121, 0, 0, 206, 32, 1, 0, 0, 0, 207, 208, 5, 43, 0, 0, 208, 34, 1, 0, 0, 0, 209, 210, 5, 45, 0, 0, 210, 36, 1, 0, 0, 0, 211, 212, 5, 111, 0, 0, 212, 213, 5, 114, 0, 0, 213, 214, 5, 100, 0, 0, 214, 215, 5, 101, 0, 0, 215, 216, 5, 114, 0, 0, 216, 217, 5, 95, 0, 0, 217, 218, 5, 98, 0, 0, 218, 227, 5, 121, 0, 0, 219, 220, 5, 115, 0, 0, 220, 221, 5, 111, 0, 0, 221, 222, 5, 114, 0, 0, 222, 223, 5, 116, 0, 0, 223, 224, 5, 95, 0, 0, 224, 225, 5, 98, 0, 0, 225, 227, 5, 121, 0, 0, 226, 211, 1, 0, 0, 0, 226, 219, 1, 0, 0, 0, 227, 38, 1, 0, 0, 0, 228, 229, 5, 58, 0, 0, 229, 230, 5, 99, 0, 0, 230, 231, 5, 111, 0, 0, 231, 232, 5, 117, 0, 0, 232, 233, 5, 110, 0, 0, 233, 285, 5, 116, 0, 0, 234, 235, 5, 58, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 117, 0, 0, 238, 239, 5, 110, 0, 0, 239, 240, 5, 116, 0, 0, 240, 241, 5, 95, 0, 0, 241, 242, 5, 117, 0, 0, 242, 243, 5, 110, 0, 0, 243, 244, 5, 105, 0, 0, 244, 245, 5, 113, 0, 0, 245, 246, 5, 117, 0, 0, 246, 285, 5, 101, 0, 0, 247, 248, 5, 58, 0, 0, 248, 249, 5, 97, 0, 0, 249, 250, 5, 118, 0, 0, 250, 285, 5, 103, 0, 0, 251, 252, 5, 58, 0, 0, 252, 253, 5, 103, 0, 0, 253, 254, 5, 114, 0, 0, 254, 255, 5, 111, 0, 0, 255, 256, 5, 117, 0, 0, 256, 257, 5, 112, 0, 0, 257, 258, 5, 95, 0, 0, 258, 259, 5, 98, 0, 0, 259, 285, 5, 121, 0, 0, 260, 261, 5, 58, 0, 0, 261, 262, 5, 109, 0, 0, 262, 263, 5, 97, 0, 0, 263, 285, 5, 120, 0, 0, 264, 265, 5, 58, 0, 0, 265, 266, 5, 109, 0, 0, 266, 267, 5, 105, 0, 0, 267, 285, 5, 110, 0, 0, 268, 269, 5, 58, 0, 0, 269, 270, 5, 111, 0, 0, 270, 271, 5, 114, 0, 0, 271, 272, 5, 100, 0, 0, 272, 273, 5, 101, 0, 0, 273, 274, 5, 114, 0, 0, 274, 275, 5, 95, 0, 0, 275, 276, 5, 98, 0, 0, 276, 285, 5, 121, 0, 0, 277, 278, 5, 58, 0, 0, 278, 279, 5, 117, 0, 0, 279, 280, 5, 110, 0, 0, 280, 281, 5, 105, 0, 0, 281, 282, 5, 113, 0, 0, 282, 283, 5, 117, 0, 0, 283, 285, 5, 101, 0, 0, 284, 228, 1, 0, 0, 0, 284, 234, 1, 0, 0, 0, 284, 247, 1, 0, 0, 0, 284, 251, 1, 0, 0, 0, 284, 260, 1, 0, 0, 0, 284, 264, 1, 0, 0, 0, 284, 268, 1, 0, 0, 0, 284, 277, 1, 0, 0, 0, 285, 40, 1, 0, 0, 0, 286, 287, 5, 36, 0, 0, 287, 288, 3, 43, 21, 0, 288, 42, 1, 0, 0, 0, 289, 293, 7, 0, 0, 0, 290, 292, 7, 1, 0, 0, 291, 290, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 44, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 296, 298, 7, 2, 0, 0, 297, 296, 1, 0, 0, 0, 298, 299, 1, 0, 0, 0, 299, 297, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 301, 1, 0, 0, 0, 301, 302, 6, 22, 0, 0, 302, 46, 1, 0, 0, 0, 303, 304, 5, 40, 0, 0, 304, 48, 1, 0, 0, 0, 305, 306, 5, 41, 0, 0, 306, 50, 1, 0, 0, 0, 307, 308, 5, 91, 0, 0, 308, 52, 1, 0, 0, 0, 309, 310, 5, 93, 0, 0, 310, 54, 1, 0, 0, 0, 311, 312, 5, 44, 0, 0, 312, 56, 1, 0, 0, 0, 313, 314, 5, 124, 0, 0, 314, 58, 1, 0, 0, 0, 315, 316, 5, 58, 0, 0, 316, 60, 1, 0, 0, 0, 317, 318, 5, 110, 0, 0, 318, 319, 5, 117, 0, 0, 319, 320, 5, 108, 0, 0, 320, 326, 5, 108, 0, 0, 321, 322, 5, 78, 0, 0, 322, 323, 5, 85, 0, 0, 323, 324, 5, 76, 0, 0, 324, 326, 5, 76, 0, 0, 325, 317, 1, 0, 0, 0, 325, 321, 1, 0, 0, 0, 326, 62, 1, 0, 0, 0, 327, 328, 3, 67, 33, 0, 328, 64, 1, 0, 0, 0, 329, 354, 3, 63, 31, 0, 330, 332, 5, 45, 0, 0, 331, 330, 1, 0, 0, 0, 331, 332, 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 334, 3, 67, 33, 0, 334, 336, 5, 46, 0, 0, 335, 337, 7, 3, 0, 0, 336, 335, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 341, 1, 0, 0, 0, 340, 342, 3, 69, 34, 0, 341, 340, 1, 0, 0, 0, 341, 342, 1, 0, 0, 0, 342, 354, 1, 0, 0, 0, 343, 345, 5, 45, 0, 0, 344, 343, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 346, 1, 0, 0, 0, 346, 347, 3, 67, 33, 0, 347, 348, 3, 69, 34, 0, 348, 354, 1, 0, 0, 0, 349, 351, 5, 45, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 352, 1, 0, 0, 0, 352, 354, 3, 67, 33, 0, 353, 329, 1, 0, 0, 0, 353, 331, 1, 0, 0, 0, 353, 344, 1, 0, 0, 0, 353, 350, 1, 0, 0, 0, 354, 66, 1, 0, 0, 0, 355, 364, 5, 48, 0, 0, 356, 360, 7, 4, 0, 0, 357, 359, 7, 3, 0, 0, 358, 357, 1, 0, 0, 0, 359, 362, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 363, 355, 1, 0, 0, 0, 363, 356, 1, 0, 0, 0, 364, 68, 1, 0, 0, 0, 365, 367, 7, 5, 0, 0, 366, 368, 7, 6, 0, 0, 367, 366, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 3, 67, 33, 0, 370, 70, 1, 0, 0, 0, 371, 372, 5, 60, 0, 0, 372, 373, 5, 61, 0, 0, 373, 72, 1, 0, 0, 0, 374, 375, 5, 60, 0, 0, 375, 74, 1, 0, 0, 0, 376, 377, 5, 62, 0, 0, 377, 378, 5, 61, 0, 0, 378, 76, 1, 0, 0, 0, 379, 380, 5, 62, 0, 0, 380, 78, 1, 0, 0, 0, 381, 382, 5, 33, 0, 0, 382, 383, 5, 61, 0, 0, 383, 80, 1, 0, 0, 0, 384, 385, 5, 61, 0, 0, 385, 386, 5, 61, 0, 0, 386, 82, 1, 0, 0, 0, 387, 391, 5, 46, 0, 0, 388, 392, 3, 41, 20, 0, 389, 392, 3, 43, 21, 0, 390, 392, 3, 87, 43, 0, 391, 388, 1, 0, 0, 0, 391, 389, 1, 0, 0, 0, 391, 390, 1, 0, 0, 0, 392, 84, 1, 0, 0, 0, 393, 394, 5, 64, 0, 0, 394, 395, 3, 43, 21, 0, 395, 86, 1, 0, 0, 0, 396, 401, 5, 34, 0, 0, 397, 400, 3, 89, 44, 0, 398, 400, 8, 7, 0, 0, 399, 397, 1, 0, 0, 0, 399, 398, 1, 0, 0, 0, 400, 403, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 404, 1, 0, 0, 0, 403, 401, 1, 0, 0, 0, 404, 405, 5, 34, 0, 0, 405, 88, 1, 0, 0, 0, 406, 409, 5, 92, 0, 0, 407, 410, 7, 8, 0, 0, 408, 410, 3, 91, 45, 0, 409, 407, 1, 0, 0, 0, 409, 408, 1, 0, 0, 0, 410, 90, 1, 0, 0, 0, 411, 412, 5, 117, 0, 0, 412, 413, 3, 93, 46, 0, 413, 414, 3, 93, 46, 0, 414, 415, 3, 93, 46, 0, 415, 416, 3, 93, 46, 0, 416, 92, 1, 0, 0, 0, 417, 418, 7, 9, 0, 0, 418, 94, 1, 0, 0, 0, 419, 420, 7, 3, 0, 0, 420, 96, 1, 0, 0, 0, 421, 422, 7, 10, 0, 0, 422, 98, 1, 0, 0, 0, 423, 424, 7, 11, 0, 0, 424, 100, 1, 0, 0, 0, 425, 426, 7, 12, 0, 0, 426, 102, 1, 0, 0, 0, 427, 428, 7, 13, 0, 0, 428, 104, 1, 0, 0, 0, 429, 430, 7, 5, 0, 0, 430, 106, 1, 0, 0, 0, 431, 432, 7, 14, 0, 0, 432, 108, 1, 0, 0, 0, 433, 434, 7, 15, 0, 0, 434, 110, 1, 0, 0, 0, 435, 436, 7, 16, 0, 0, 436, 112, 1, 0, 0, 0, 437, 438, 7, 17, 0, 0, 438, 114, 1, 0, 0, 0, 439, 440, 7, 18, 0, 0, 440, 116, 1, 0, 0, 0, 441, 442, 7, 19, 0, 0, 442, 118, 1, 0, 0, 0, 443, 444, 7, 20, 0, 0, 444, 120, 1, 0, 0, 0, 445, 446, 7, 21, 0, 0, 446, 122, 1, 0, 0, 0, 447, 448, 7, 22, 0, 0, 448, 124, 1, 0, 0, 0, 449, 450, 7, 23, 0, 0, 450, 126, 1, 0, 0, 0, 451, 452, 7, 24, 0, 0, 452, 128, 1, 0, 0, 0, 453, 454, 7, 25, 0, 0, 454, 130, 1, 0, 0, 0, 455, 456, 7, 26, 0, 0, 456, 132, 1, 0, 0, 0, 457, 458, 7, 27, 0, 0, 458, 134, 1, 0, 0, 0, 459, 460, 7, 28, 0, 0, 460, 136, 1, 0, 0, 0, 461, 462, 7, 29, 0, 0, 462, 138, 1, 0, 0, 0, 463, 464, 7, 30, 0, 0, 464, 140, 1, 0, 0, 0, 465, 466, 7, 31, 0, 0, 466, 142, 1, 0, 0, 0, 467, 468, 7, 32, 0, 0, 468, 144, 1, 0, 0, 0, 469, 470, 7, 33, 0, 0, 470, 146, 1, 0, 0, 0, 471, 472, 7, 34, 0, 0, 472, 148, 1, 0, 0, 0, 473, 477, 5, 35, 0, 0, 474, 476, 9, 0, 0, 0, 475, 474, 1, 0, 0, 0, 476, 479, 1, 0, 0, 0, 477, 478, 1, 0, 0, 0, 477, 475, 1, 0, 0, 0, 478, 480, 1, 0, 0, 0, 479, 477, 1, 0, 0, 0, 480, 481, 5, 10, 0, 0, 481, 482, 1, 0, 0, 0, 482, 483, 6, 74, 0, 0, 483, 150, 1, 0, 0, 0, 20, 0, 226, 284, 293, 299, 325, 331, 338, 341, 344, 350, 353, 360, 363, 367, 391, 399, 401, 409, 477, 1, 6, 0, 0] \ No newline at end of file +[4, 0, 43, 479, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 227, 8, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 3, 19, 285, 8, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 5, 22, 297, 8, 22, 10, 22, 12, 22, 300, 9, 22, 1, 23, 4, 23, 303, 8, 23, 11, 23, 12, 23, 304, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 327, 8, 32, 1, 32, 1, 32, 1, 32, 4, 32, 332, 8, 32, 11, 32, 12, 32, 333, 1, 32, 3, 32, 337, 8, 32, 1, 32, 3, 32, 340, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 346, 8, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, 1, 33, 1, 33, 5, 33, 354, 8, 33, 10, 33, 12, 33, 357, 9, 33, 3, 33, 359, 8, 33, 1, 34, 1, 34, 3, 34, 363, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 387, 8, 41, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 5, 43, 395, 8, 43, 10, 43, 12, 43, 398, 9, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 3, 44, 405, 8, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 5, 74, 471, 8, 74, 10, 74, 12, 74, 474, 9, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 472, 0, 75, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 0, 69, 0, 71, 34, 73, 35, 75, 36, 77, 37, 79, 38, 81, 39, 83, 40, 85, 41, 87, 42, 89, 0, 91, 0, 93, 0, 95, 0, 97, 0, 99, 0, 101, 0, 103, 0, 105, 0, 107, 0, 109, 0, 111, 0, 113, 0, 115, 0, 117, 0, 119, 0, 121, 0, 123, 0, 125, 0, 127, 0, 129, 0, 131, 0, 133, 0, 135, 0, 137, 0, 139, 0, 141, 0, 143, 0, 145, 0, 147, 0, 149, 43, 1, 0, 35, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 1, 0, 49, 57, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 473, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 1, 151, 1, 0, 0, 0, 3, 153, 1, 0, 0, 0, 5, 155, 1, 0, 0, 0, 7, 160, 1, 0, 0, 0, 9, 167, 1, 0, 0, 0, 11, 173, 1, 0, 0, 0, 13, 176, 1, 0, 0, 0, 15, 179, 1, 0, 0, 0, 17, 181, 1, 0, 0, 0, 19, 183, 1, 0, 0, 0, 21, 186, 1, 0, 0, 0, 23, 189, 1, 0, 0, 0, 25, 191, 1, 0, 0, 0, 27, 194, 1, 0, 0, 0, 29, 196, 1, 0, 0, 0, 31, 198, 1, 0, 0, 0, 33, 207, 1, 0, 0, 0, 35, 209, 1, 0, 0, 0, 37, 226, 1, 0, 0, 0, 39, 284, 1, 0, 0, 0, 41, 286, 1, 0, 0, 0, 43, 289, 1, 0, 0, 0, 45, 294, 1, 0, 0, 0, 47, 302, 1, 0, 0, 0, 49, 308, 1, 0, 0, 0, 51, 310, 1, 0, 0, 0, 53, 312, 1, 0, 0, 0, 55, 314, 1, 0, 0, 0, 57, 316, 1, 0, 0, 0, 59, 318, 1, 0, 0, 0, 61, 320, 1, 0, 0, 0, 63, 322, 1, 0, 0, 0, 65, 348, 1, 0, 0, 0, 67, 358, 1, 0, 0, 0, 69, 360, 1, 0, 0, 0, 71, 366, 1, 0, 0, 0, 73, 369, 1, 0, 0, 0, 75, 371, 1, 0, 0, 0, 77, 374, 1, 0, 0, 0, 79, 376, 1, 0, 0, 0, 81, 379, 1, 0, 0, 0, 83, 382, 1, 0, 0, 0, 85, 388, 1, 0, 0, 0, 87, 391, 1, 0, 0, 0, 89, 401, 1, 0, 0, 0, 91, 406, 1, 0, 0, 0, 93, 412, 1, 0, 0, 0, 95, 414, 1, 0, 0, 0, 97, 416, 1, 0, 0, 0, 99, 418, 1, 0, 0, 0, 101, 420, 1, 0, 0, 0, 103, 422, 1, 0, 0, 0, 105, 424, 1, 0, 0, 0, 107, 426, 1, 0, 0, 0, 109, 428, 1, 0, 0, 0, 111, 430, 1, 0, 0, 0, 113, 432, 1, 0, 0, 0, 115, 434, 1, 0, 0, 0, 117, 436, 1, 0, 0, 0, 119, 438, 1, 0, 0, 0, 121, 440, 1, 0, 0, 0, 123, 442, 1, 0, 0, 0, 125, 444, 1, 0, 0, 0, 127, 446, 1, 0, 0, 0, 129, 448, 1, 0, 0, 0, 131, 450, 1, 0, 0, 0, 133, 452, 1, 0, 0, 0, 135, 454, 1, 0, 0, 0, 137, 456, 1, 0, 0, 0, 139, 458, 1, 0, 0, 0, 141, 460, 1, 0, 0, 0, 143, 462, 1, 0, 0, 0, 145, 464, 1, 0, 0, 0, 147, 466, 1, 0, 0, 0, 149, 468, 1, 0, 0, 0, 151, 152, 5, 59, 0, 0, 152, 2, 1, 0, 0, 0, 153, 154, 5, 42, 0, 0, 154, 4, 1, 0, 0, 0, 155, 156, 5, 106, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 105, 0, 0, 158, 159, 5, 110, 0, 0, 159, 6, 1, 0, 0, 0, 160, 161, 5, 117, 0, 0, 161, 162, 5, 110, 0, 0, 162, 163, 5, 105, 0, 0, 163, 164, 5, 113, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 101, 0, 0, 166, 8, 1, 0, 0, 0, 167, 168, 5, 99, 0, 0, 168, 169, 5, 111, 0, 0, 169, 170, 5, 117, 0, 0, 170, 171, 5, 110, 0, 0, 171, 172, 5, 116, 0, 0, 172, 10, 1, 0, 0, 0, 173, 174, 5, 46, 0, 0, 174, 175, 5, 91, 0, 0, 175, 12, 1, 0, 0, 0, 176, 177, 5, 124, 0, 0, 177, 178, 5, 124, 0, 0, 178, 14, 1, 0, 0, 0, 179, 180, 5, 47, 0, 0, 180, 16, 1, 0, 0, 0, 181, 182, 5, 37, 0, 0, 182, 18, 1, 0, 0, 0, 183, 184, 5, 60, 0, 0, 184, 185, 5, 60, 0, 0, 185, 20, 1, 0, 0, 0, 186, 187, 5, 62, 0, 0, 187, 188, 5, 62, 0, 0, 188, 22, 1, 0, 0, 0, 189, 190, 5, 38, 0, 0, 190, 24, 1, 0, 0, 0, 191, 192, 5, 38, 0, 0, 192, 193, 5, 38, 0, 0, 193, 26, 1, 0, 0, 0, 194, 195, 5, 126, 0, 0, 195, 28, 1, 0, 0, 0, 196, 197, 5, 33, 0, 0, 197, 30, 1, 0, 0, 0, 198, 199, 5, 103, 0, 0, 199, 200, 5, 114, 0, 0, 200, 201, 5, 111, 0, 0, 201, 202, 5, 117, 0, 0, 202, 203, 5, 112, 0, 0, 203, 204, 5, 95, 0, 0, 204, 205, 5, 98, 0, 0, 205, 206, 5, 121, 0, 0, 206, 32, 1, 0, 0, 0, 207, 208, 5, 43, 0, 0, 208, 34, 1, 0, 0, 0, 209, 210, 5, 45, 0, 0, 210, 36, 1, 0, 0, 0, 211, 212, 5, 111, 0, 0, 212, 213, 5, 114, 0, 0, 213, 214, 5, 100, 0, 0, 214, 215, 5, 101, 0, 0, 215, 216, 5, 114, 0, 0, 216, 217, 5, 95, 0, 0, 217, 218, 5, 98, 0, 0, 218, 227, 5, 121, 0, 0, 219, 220, 5, 115, 0, 0, 220, 221, 5, 111, 0, 0, 221, 222, 5, 114, 0, 0, 222, 223, 5, 116, 0, 0, 223, 224, 5, 95, 0, 0, 224, 225, 5, 98, 0, 0, 225, 227, 5, 121, 0, 0, 226, 211, 1, 0, 0, 0, 226, 219, 1, 0, 0, 0, 227, 38, 1, 0, 0, 0, 228, 229, 5, 58, 0, 0, 229, 230, 5, 99, 0, 0, 230, 231, 5, 111, 0, 0, 231, 232, 5, 117, 0, 0, 232, 233, 5, 110, 0, 0, 233, 285, 5, 116, 0, 0, 234, 235, 5, 58, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 117, 0, 0, 238, 239, 5, 110, 0, 0, 239, 240, 5, 116, 0, 0, 240, 241, 5, 95, 0, 0, 241, 242, 5, 117, 0, 0, 242, 243, 5, 110, 0, 0, 243, 244, 5, 105, 0, 0, 244, 245, 5, 113, 0, 0, 245, 246, 5, 117, 0, 0, 246, 285, 5, 101, 0, 0, 247, 248, 5, 58, 0, 0, 248, 249, 5, 97, 0, 0, 249, 250, 5, 118, 0, 0, 250, 285, 5, 103, 0, 0, 251, 252, 5, 58, 0, 0, 252, 253, 5, 103, 0, 0, 253, 254, 5, 114, 0, 0, 254, 255, 5, 111, 0, 0, 255, 256, 5, 117, 0, 0, 256, 257, 5, 112, 0, 0, 257, 258, 5, 95, 0, 0, 258, 259, 5, 98, 0, 0, 259, 285, 5, 121, 0, 0, 260, 261, 5, 58, 0, 0, 261, 262, 5, 109, 0, 0, 262, 263, 5, 97, 0, 0, 263, 285, 5, 120, 0, 0, 264, 265, 5, 58, 0, 0, 265, 266, 5, 109, 0, 0, 266, 267, 5, 105, 0, 0, 267, 285, 5, 110, 0, 0, 268, 269, 5, 58, 0, 0, 269, 270, 5, 111, 0, 0, 270, 271, 5, 114, 0, 0, 271, 272, 5, 100, 0, 0, 272, 273, 5, 101, 0, 0, 273, 274, 5, 114, 0, 0, 274, 275, 5, 95, 0, 0, 275, 276, 5, 98, 0, 0, 276, 285, 5, 121, 0, 0, 277, 278, 5, 58, 0, 0, 278, 279, 5, 117, 0, 0, 279, 280, 5, 110, 0, 0, 280, 281, 5, 105, 0, 0, 281, 282, 5, 113, 0, 0, 282, 283, 5, 117, 0, 0, 283, 285, 5, 101, 0, 0, 284, 228, 1, 0, 0, 0, 284, 234, 1, 0, 0, 0, 284, 247, 1, 0, 0, 0, 284, 251, 1, 0, 0, 0, 284, 260, 1, 0, 0, 0, 284, 264, 1, 0, 0, 0, 284, 268, 1, 0, 0, 0, 284, 277, 1, 0, 0, 0, 285, 40, 1, 0, 0, 0, 286, 287, 5, 36, 0, 0, 287, 288, 3, 45, 22, 0, 288, 42, 1, 0, 0, 0, 289, 290, 5, 110, 0, 0, 290, 291, 5, 117, 0, 0, 291, 292, 5, 108, 0, 0, 292, 293, 5, 108, 0, 0, 293, 44, 1, 0, 0, 0, 294, 298, 7, 0, 0, 0, 295, 297, 7, 1, 0, 0, 296, 295, 1, 0, 0, 0, 297, 300, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 298, 299, 1, 0, 0, 0, 299, 46, 1, 0, 0, 0, 300, 298, 1, 0, 0, 0, 301, 303, 7, 2, 0, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, 6, 23, 0, 0, 307, 48, 1, 0, 0, 0, 308, 309, 5, 40, 0, 0, 309, 50, 1, 0, 0, 0, 310, 311, 5, 41, 0, 0, 311, 52, 1, 0, 0, 0, 312, 313, 5, 91, 0, 0, 313, 54, 1, 0, 0, 0, 314, 315, 5, 93, 0, 0, 315, 56, 1, 0, 0, 0, 316, 317, 5, 44, 0, 0, 317, 58, 1, 0, 0, 0, 318, 319, 5, 124, 0, 0, 319, 60, 1, 0, 0, 0, 320, 321, 5, 58, 0, 0, 321, 62, 1, 0, 0, 0, 322, 323, 3, 67, 33, 0, 323, 64, 1, 0, 0, 0, 324, 349, 3, 63, 31, 0, 325, 327, 5, 45, 0, 0, 326, 325, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 329, 3, 67, 33, 0, 329, 331, 5, 46, 0, 0, 330, 332, 7, 3, 0, 0, 331, 330, 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 331, 1, 0, 0, 0, 333, 334, 1, 0, 0, 0, 334, 336, 1, 0, 0, 0, 335, 337, 3, 69, 34, 0, 336, 335, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 349, 1, 0, 0, 0, 338, 340, 5, 45, 0, 0, 339, 338, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 341, 1, 0, 0, 0, 341, 342, 3, 67, 33, 0, 342, 343, 3, 69, 34, 0, 343, 349, 1, 0, 0, 0, 344, 346, 5, 45, 0, 0, 345, 344, 1, 0, 0, 0, 345, 346, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 349, 3, 67, 33, 0, 348, 324, 1, 0, 0, 0, 348, 326, 1, 0, 0, 0, 348, 339, 1, 0, 0, 0, 348, 345, 1, 0, 0, 0, 349, 66, 1, 0, 0, 0, 350, 359, 5, 48, 0, 0, 351, 355, 7, 4, 0, 0, 352, 354, 7, 3, 0, 0, 353, 352, 1, 0, 0, 0, 354, 357, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 355, 356, 1, 0, 0, 0, 356, 359, 1, 0, 0, 0, 357, 355, 1, 0, 0, 0, 358, 350, 1, 0, 0, 0, 358, 351, 1, 0, 0, 0, 359, 68, 1, 0, 0, 0, 360, 362, 7, 5, 0, 0, 361, 363, 7, 6, 0, 0, 362, 361, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 365, 3, 67, 33, 0, 365, 70, 1, 0, 0, 0, 366, 367, 5, 60, 0, 0, 367, 368, 5, 61, 0, 0, 368, 72, 1, 0, 0, 0, 369, 370, 5, 60, 0, 0, 370, 74, 1, 0, 0, 0, 371, 372, 5, 62, 0, 0, 372, 373, 5, 61, 0, 0, 373, 76, 1, 0, 0, 0, 374, 375, 5, 62, 0, 0, 375, 78, 1, 0, 0, 0, 376, 377, 5, 33, 0, 0, 377, 378, 5, 61, 0, 0, 378, 80, 1, 0, 0, 0, 379, 380, 5, 61, 0, 0, 380, 381, 5, 61, 0, 0, 381, 82, 1, 0, 0, 0, 382, 386, 5, 46, 0, 0, 383, 387, 3, 41, 20, 0, 384, 387, 3, 45, 22, 0, 385, 387, 3, 87, 43, 0, 386, 383, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0, 386, 385, 1, 0, 0, 0, 387, 84, 1, 0, 0, 0, 388, 389, 5, 64, 0, 0, 389, 390, 3, 45, 22, 0, 390, 86, 1, 0, 0, 0, 391, 396, 5, 34, 0, 0, 392, 395, 3, 89, 44, 0, 393, 395, 8, 7, 0, 0, 394, 392, 1, 0, 0, 0, 394, 393, 1, 0, 0, 0, 395, 398, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 396, 397, 1, 0, 0, 0, 397, 399, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 399, 400, 5, 34, 0, 0, 400, 88, 1, 0, 0, 0, 401, 404, 5, 92, 0, 0, 402, 405, 7, 8, 0, 0, 403, 405, 3, 91, 45, 0, 404, 402, 1, 0, 0, 0, 404, 403, 1, 0, 0, 0, 405, 90, 1, 0, 0, 0, 406, 407, 5, 117, 0, 0, 407, 408, 3, 93, 46, 0, 408, 409, 3, 93, 46, 0, 409, 410, 3, 93, 46, 0, 410, 411, 3, 93, 46, 0, 411, 92, 1, 0, 0, 0, 412, 413, 7, 9, 0, 0, 413, 94, 1, 0, 0, 0, 414, 415, 7, 3, 0, 0, 415, 96, 1, 0, 0, 0, 416, 417, 7, 10, 0, 0, 417, 98, 1, 0, 0, 0, 418, 419, 7, 11, 0, 0, 419, 100, 1, 0, 0, 0, 420, 421, 7, 12, 0, 0, 421, 102, 1, 0, 0, 0, 422, 423, 7, 13, 0, 0, 423, 104, 1, 0, 0, 0, 424, 425, 7, 5, 0, 0, 425, 106, 1, 0, 0, 0, 426, 427, 7, 14, 0, 0, 427, 108, 1, 0, 0, 0, 428, 429, 7, 15, 0, 0, 429, 110, 1, 0, 0, 0, 430, 431, 7, 16, 0, 0, 431, 112, 1, 0, 0, 0, 432, 433, 7, 17, 0, 0, 433, 114, 1, 0, 0, 0, 434, 435, 7, 18, 0, 0, 435, 116, 1, 0, 0, 0, 436, 437, 7, 19, 0, 0, 437, 118, 1, 0, 0, 0, 438, 439, 7, 20, 0, 0, 439, 120, 1, 0, 0, 0, 440, 441, 7, 21, 0, 0, 441, 122, 1, 0, 0, 0, 442, 443, 7, 22, 0, 0, 443, 124, 1, 0, 0, 0, 444, 445, 7, 23, 0, 0, 445, 126, 1, 0, 0, 0, 446, 447, 7, 24, 0, 0, 447, 128, 1, 0, 0, 0, 448, 449, 7, 25, 0, 0, 449, 130, 1, 0, 0, 0, 450, 451, 7, 26, 0, 0, 451, 132, 1, 0, 0, 0, 452, 453, 7, 27, 0, 0, 453, 134, 1, 0, 0, 0, 454, 455, 7, 28, 0, 0, 455, 136, 1, 0, 0, 0, 456, 457, 7, 29, 0, 0, 457, 138, 1, 0, 0, 0, 458, 459, 7, 30, 0, 0, 459, 140, 1, 0, 0, 0, 460, 461, 7, 31, 0, 0, 461, 142, 1, 0, 0, 0, 462, 463, 7, 32, 0, 0, 463, 144, 1, 0, 0, 0, 464, 465, 7, 33, 0, 0, 465, 146, 1, 0, 0, 0, 466, 467, 7, 34, 0, 0, 467, 148, 1, 0, 0, 0, 468, 472, 5, 35, 0, 0, 469, 471, 9, 0, 0, 0, 470, 469, 1, 0, 0, 0, 471, 474, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 473, 475, 1, 0, 0, 0, 474, 472, 1, 0, 0, 0, 475, 476, 5, 10, 0, 0, 476, 477, 1, 0, 0, 0, 477, 478, 6, 74, 0, 0, 478, 150, 1, 0, 0, 0, 19, 0, 226, 284, 298, 304, 326, 333, 336, 339, 345, 348, 355, 358, 362, 386, 394, 396, 404, 472, 1, 6, 0, 0] \ No newline at end of file diff --git a/libsq/ast/internal/slq/SLQLexer.tokens b/libsq/ast/internal/slq/SLQLexer.tokens index cc3a584e..1c47f05b 100644 --- a/libsq/ast/internal/slq/SLQLexer.tokens +++ b/libsq/ast/internal/slq/SLQLexer.tokens @@ -19,16 +19,16 @@ ORDER_DESC=18 ORDER_BY=19 ALIAS_RESERVED=20 ARG=21 -ID=22 -WS=23 -LPAR=24 -RPAR=25 -LBRA=26 -RBRA=27 -COMMA=28 -PIPE=29 -COLON=30 -NULL=31 +NULL=22 +ID=23 +WS=24 +LPAR=25 +RPAR=26 +LBRA=27 +RBRA=28 +COMMA=29 +PIPE=30 +COLON=31 NN=32 NUMBER=33 LT_EQ=34 @@ -59,13 +59,14 @@ LINECOMMENT=43 'group_by'=16 '+'=17 '-'=18 -'('=24 -')'=25 -'['=26 -']'=27 -','=28 -'|'=29 -':'=30 +'null'=22 +'('=25 +')'=26 +'['=27 +']'=28 +','=29 +'|'=30 +':'=31 '<='=34 '<'=35 '>='=36 diff --git a/libsq/ast/internal/slq/slq_base_listener.go b/libsq/ast/internal/slq/slq_base_listener.go index 5f1a5392..3c4f97c9 100644 --- a/libsq/ast/internal/slq/slq_base_listener.go +++ b/libsq/ast/internal/slq/slq_base_listener.go @@ -134,6 +134,12 @@ func (s *BaseSLQListener) EnterAlias(ctx *AliasContext) {} // ExitAlias is called when production alias is exited. func (s *BaseSLQListener) ExitAlias(ctx *AliasContext) {} +// EnterArg is called when production arg is entered. +func (s *BaseSLQListener) EnterArg(ctx *ArgContext) {} + +// ExitArg is called when production arg is exited. +func (s *BaseSLQListener) ExitArg(ctx *ArgContext) {} + // EnterHandleTable is called when production handleTable is entered. func (s *BaseSLQListener) EnterHandleTable(ctx *HandleTableContext) {} diff --git a/libsq/ast/internal/slq/slq_base_visitor.go b/libsq/ast/internal/slq/slq_base_visitor.go index 9ee75fa4..63830758 100644 --- a/libsq/ast/internal/slq/slq_base_visitor.go +++ b/libsq/ast/internal/slq/slq_base_visitor.go @@ -83,6 +83,10 @@ func (v *BaseSLQVisitor) VisitAlias(ctx *AliasContext) interface{} { return v.VisitChildren(ctx) } +func (v *BaseSLQVisitor) VisitArg(ctx *ArgContext) interface{} { + return v.VisitChildren(ctx) +} + func (v *BaseSLQVisitor) VisitHandleTable(ctx *HandleTableContext) interface{} { return v.VisitChildren(ctx) } diff --git a/libsq/ast/internal/slq/slq_lexer.go b/libsq/ast/internal/slq/slq_lexer.go index f8b182ee..55f8ef6a 100644 --- a/libsq/ast/internal/slq/slq_lexer.go +++ b/libsq/ast/internal/slq/slq_lexer.go @@ -46,21 +46,21 @@ func slqlexerLexerInit() { staticData.literalNames = []string{ "", "';'", "'*'", "'join'", "'unique'", "'count'", "'.['", "'||'", "'/'", "'%'", "'<<'", "'>>'", "'&'", "'&&'", "'~'", "'!'", "'group_by'", "'+'", - "'-'", "", "", "", "", "", "'('", "')'", "'['", "']'", "','", "'|'", - "':'", "", "", "", "'<='", "'<'", "'>='", "'>'", "'!='", "'=='", + "'-'", "", "", "", "'null'", "", "", "'('", "')'", "'['", "']'", "','", + "'|'", "':'", "", "", "'<='", "'<'", "'>='", "'>'", "'!='", "'=='", } staticData.symbolicNames = []string{ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GROUP_BY", - "ORDER_ASC", "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "ID", - "WS", "LPAR", "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NULL", + "ORDER_ASC", "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "NULL", + "ID", "WS", "LPAR", "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NN", "NUMBER", "LT_EQ", "LT", "GT_EQ", "GT", "NEQ", "EQ", "NAME", "HANDLE", "STRING", "LINECOMMENT", } staticData.ruleNames = []string{ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "GROUP_BY", "ORDER_ASC", - "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "ID", "WS", "LPAR", - "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NULL", "NN", "NUMBER", + "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "NULL", "ID", "WS", + "LPAR", "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NN", "NUMBER", "INTF", "EXP", "LT_EQ", "LT", "GT_EQ", "GT", "NEQ", "EQ", "NAME", "HANDLE", "STRING", "ESC", "UNICODE", "HEX", "DIGIT", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", @@ -68,7 +68,7 @@ func slqlexerLexerInit() { } staticData.predictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 0, 43, 484, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 0, 43, 479, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, @@ -95,196 +95,194 @@ func slqlexerLexerInit() { 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 3, 19, 285, 8, 19, 1, - 20, 1, 20, 1, 20, 1, 21, 1, 21, 5, 21, 292, 8, 21, 10, 21, 12, 21, 295, - 9, 21, 1, 22, 4, 22, 298, 8, 22, 11, 22, 12, 22, 299, 1, 22, 1, 22, 1, - 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, - 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, - 30, 3, 30, 326, 8, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 332, 8, 32, 1, - 32, 1, 32, 1, 32, 4, 32, 337, 8, 32, 11, 32, 12, 32, 338, 1, 32, 3, 32, - 342, 8, 32, 1, 32, 3, 32, 345, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, - 351, 8, 32, 1, 32, 3, 32, 354, 8, 32, 1, 33, 1, 33, 1, 33, 5, 33, 359, - 8, 33, 10, 33, 12, 33, 362, 9, 33, 3, 33, 364, 8, 33, 1, 34, 1, 34, 3, - 34, 368, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, - 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, - 41, 1, 41, 1, 41, 1, 41, 3, 41, 392, 8, 41, 1, 42, 1, 42, 1, 42, 1, 43, - 1, 43, 1, 43, 5, 43, 400, 8, 43, 10, 43, 12, 43, 403, 9, 43, 1, 43, 1, - 43, 1, 44, 1, 44, 1, 44, 3, 44, 410, 8, 44, 1, 45, 1, 45, 1, 45, 1, 45, - 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, - 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, - 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 59, 1, 59, 1, 60, 1, - 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, - 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, - 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 5, 74, 476, 8, 74, - 10, 74, 12, 74, 479, 9, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 477, 0, 75, - 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, - 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, - 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, - 59, 30, 61, 31, 63, 32, 65, 33, 67, 0, 69, 0, 71, 34, 73, 35, 75, 36, 77, - 37, 79, 38, 81, 39, 83, 40, 85, 41, 87, 42, 89, 0, 91, 0, 93, 0, 95, 0, - 97, 0, 99, 0, 101, 0, 103, 0, 105, 0, 107, 0, 109, 0, 111, 0, 113, 0, 115, - 0, 117, 0, 119, 0, 121, 0, 123, 0, 125, 0, 127, 0, 129, 0, 131, 0, 133, - 0, 135, 0, 137, 0, 139, 0, 141, 0, 143, 0, 145, 0, 147, 0, 149, 43, 1, - 0, 35, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, - 122, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 1, 0, 49, 57, 2, 0, 69, - 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 8, 0, 34, 34, - 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, - 57, 65, 70, 97, 102, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, - 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 71, - 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, - 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, - 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, - 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, - 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, - 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, - 89, 121, 121, 2, 0, 90, 90, 122, 122, 479, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, - 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, - 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, - 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, - 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, - 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, - 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, - 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, - 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, - 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, - 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, - 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 1, 151, 1, 0, 0, - 0, 3, 153, 1, 0, 0, 0, 5, 155, 1, 0, 0, 0, 7, 160, 1, 0, 0, 0, 9, 167, - 1, 0, 0, 0, 11, 173, 1, 0, 0, 0, 13, 176, 1, 0, 0, 0, 15, 179, 1, 0, 0, - 0, 17, 181, 1, 0, 0, 0, 19, 183, 1, 0, 0, 0, 21, 186, 1, 0, 0, 0, 23, 189, - 1, 0, 0, 0, 25, 191, 1, 0, 0, 0, 27, 194, 1, 0, 0, 0, 29, 196, 1, 0, 0, - 0, 31, 198, 1, 0, 0, 0, 33, 207, 1, 0, 0, 0, 35, 209, 1, 0, 0, 0, 37, 226, - 1, 0, 0, 0, 39, 284, 1, 0, 0, 0, 41, 286, 1, 0, 0, 0, 43, 289, 1, 0, 0, - 0, 45, 297, 1, 0, 0, 0, 47, 303, 1, 0, 0, 0, 49, 305, 1, 0, 0, 0, 51, 307, - 1, 0, 0, 0, 53, 309, 1, 0, 0, 0, 55, 311, 1, 0, 0, 0, 57, 313, 1, 0, 0, - 0, 59, 315, 1, 0, 0, 0, 61, 325, 1, 0, 0, 0, 63, 327, 1, 0, 0, 0, 65, 353, - 1, 0, 0, 0, 67, 363, 1, 0, 0, 0, 69, 365, 1, 0, 0, 0, 71, 371, 1, 0, 0, - 0, 73, 374, 1, 0, 0, 0, 75, 376, 1, 0, 0, 0, 77, 379, 1, 0, 0, 0, 79, 381, - 1, 0, 0, 0, 81, 384, 1, 0, 0, 0, 83, 387, 1, 0, 0, 0, 85, 393, 1, 0, 0, - 0, 87, 396, 1, 0, 0, 0, 89, 406, 1, 0, 0, 0, 91, 411, 1, 0, 0, 0, 93, 417, - 1, 0, 0, 0, 95, 419, 1, 0, 0, 0, 97, 421, 1, 0, 0, 0, 99, 423, 1, 0, 0, - 0, 101, 425, 1, 0, 0, 0, 103, 427, 1, 0, 0, 0, 105, 429, 1, 0, 0, 0, 107, - 431, 1, 0, 0, 0, 109, 433, 1, 0, 0, 0, 111, 435, 1, 0, 0, 0, 113, 437, - 1, 0, 0, 0, 115, 439, 1, 0, 0, 0, 117, 441, 1, 0, 0, 0, 119, 443, 1, 0, - 0, 0, 121, 445, 1, 0, 0, 0, 123, 447, 1, 0, 0, 0, 125, 449, 1, 0, 0, 0, - 127, 451, 1, 0, 0, 0, 129, 453, 1, 0, 0, 0, 131, 455, 1, 0, 0, 0, 133, - 457, 1, 0, 0, 0, 135, 459, 1, 0, 0, 0, 137, 461, 1, 0, 0, 0, 139, 463, - 1, 0, 0, 0, 141, 465, 1, 0, 0, 0, 143, 467, 1, 0, 0, 0, 145, 469, 1, 0, - 0, 0, 147, 471, 1, 0, 0, 0, 149, 473, 1, 0, 0, 0, 151, 152, 5, 59, 0, 0, - 152, 2, 1, 0, 0, 0, 153, 154, 5, 42, 0, 0, 154, 4, 1, 0, 0, 0, 155, 156, - 5, 106, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 105, 0, 0, 158, 159, - 5, 110, 0, 0, 159, 6, 1, 0, 0, 0, 160, 161, 5, 117, 0, 0, 161, 162, 5, - 110, 0, 0, 162, 163, 5, 105, 0, 0, 163, 164, 5, 113, 0, 0, 164, 165, 5, - 117, 0, 0, 165, 166, 5, 101, 0, 0, 166, 8, 1, 0, 0, 0, 167, 168, 5, 99, - 0, 0, 168, 169, 5, 111, 0, 0, 169, 170, 5, 117, 0, 0, 170, 171, 5, 110, - 0, 0, 171, 172, 5, 116, 0, 0, 172, 10, 1, 0, 0, 0, 173, 174, 5, 46, 0, - 0, 174, 175, 5, 91, 0, 0, 175, 12, 1, 0, 0, 0, 176, 177, 5, 124, 0, 0, - 177, 178, 5, 124, 0, 0, 178, 14, 1, 0, 0, 0, 179, 180, 5, 47, 0, 0, 180, - 16, 1, 0, 0, 0, 181, 182, 5, 37, 0, 0, 182, 18, 1, 0, 0, 0, 183, 184, 5, - 60, 0, 0, 184, 185, 5, 60, 0, 0, 185, 20, 1, 0, 0, 0, 186, 187, 5, 62, - 0, 0, 187, 188, 5, 62, 0, 0, 188, 22, 1, 0, 0, 0, 189, 190, 5, 38, 0, 0, - 190, 24, 1, 0, 0, 0, 191, 192, 5, 38, 0, 0, 192, 193, 5, 38, 0, 0, 193, - 26, 1, 0, 0, 0, 194, 195, 5, 126, 0, 0, 195, 28, 1, 0, 0, 0, 196, 197, - 5, 33, 0, 0, 197, 30, 1, 0, 0, 0, 198, 199, 5, 103, 0, 0, 199, 200, 5, - 114, 0, 0, 200, 201, 5, 111, 0, 0, 201, 202, 5, 117, 0, 0, 202, 203, 5, - 112, 0, 0, 203, 204, 5, 95, 0, 0, 204, 205, 5, 98, 0, 0, 205, 206, 5, 121, - 0, 0, 206, 32, 1, 0, 0, 0, 207, 208, 5, 43, 0, 0, 208, 34, 1, 0, 0, 0, - 209, 210, 5, 45, 0, 0, 210, 36, 1, 0, 0, 0, 211, 212, 5, 111, 0, 0, 212, - 213, 5, 114, 0, 0, 213, 214, 5, 100, 0, 0, 214, 215, 5, 101, 0, 0, 215, - 216, 5, 114, 0, 0, 216, 217, 5, 95, 0, 0, 217, 218, 5, 98, 0, 0, 218, 227, - 5, 121, 0, 0, 219, 220, 5, 115, 0, 0, 220, 221, 5, 111, 0, 0, 221, 222, - 5, 114, 0, 0, 222, 223, 5, 116, 0, 0, 223, 224, 5, 95, 0, 0, 224, 225, - 5, 98, 0, 0, 225, 227, 5, 121, 0, 0, 226, 211, 1, 0, 0, 0, 226, 219, 1, - 0, 0, 0, 227, 38, 1, 0, 0, 0, 228, 229, 5, 58, 0, 0, 229, 230, 5, 99, 0, - 0, 230, 231, 5, 111, 0, 0, 231, 232, 5, 117, 0, 0, 232, 233, 5, 110, 0, - 0, 233, 285, 5, 116, 0, 0, 234, 235, 5, 58, 0, 0, 235, 236, 5, 99, 0, 0, - 236, 237, 5, 111, 0, 0, 237, 238, 5, 117, 0, 0, 238, 239, 5, 110, 0, 0, - 239, 240, 5, 116, 0, 0, 240, 241, 5, 95, 0, 0, 241, 242, 5, 117, 0, 0, - 242, 243, 5, 110, 0, 0, 243, 244, 5, 105, 0, 0, 244, 245, 5, 113, 0, 0, - 245, 246, 5, 117, 0, 0, 246, 285, 5, 101, 0, 0, 247, 248, 5, 58, 0, 0, - 248, 249, 5, 97, 0, 0, 249, 250, 5, 118, 0, 0, 250, 285, 5, 103, 0, 0, - 251, 252, 5, 58, 0, 0, 252, 253, 5, 103, 0, 0, 253, 254, 5, 114, 0, 0, - 254, 255, 5, 111, 0, 0, 255, 256, 5, 117, 0, 0, 256, 257, 5, 112, 0, 0, - 257, 258, 5, 95, 0, 0, 258, 259, 5, 98, 0, 0, 259, 285, 5, 121, 0, 0, 260, - 261, 5, 58, 0, 0, 261, 262, 5, 109, 0, 0, 262, 263, 5, 97, 0, 0, 263, 285, - 5, 120, 0, 0, 264, 265, 5, 58, 0, 0, 265, 266, 5, 109, 0, 0, 266, 267, - 5, 105, 0, 0, 267, 285, 5, 110, 0, 0, 268, 269, 5, 58, 0, 0, 269, 270, - 5, 111, 0, 0, 270, 271, 5, 114, 0, 0, 271, 272, 5, 100, 0, 0, 272, 273, - 5, 101, 0, 0, 273, 274, 5, 114, 0, 0, 274, 275, 5, 95, 0, 0, 275, 276, - 5, 98, 0, 0, 276, 285, 5, 121, 0, 0, 277, 278, 5, 58, 0, 0, 278, 279, 5, - 117, 0, 0, 279, 280, 5, 110, 0, 0, 280, 281, 5, 105, 0, 0, 281, 282, 5, - 113, 0, 0, 282, 283, 5, 117, 0, 0, 283, 285, 5, 101, 0, 0, 284, 228, 1, - 0, 0, 0, 284, 234, 1, 0, 0, 0, 284, 247, 1, 0, 0, 0, 284, 251, 1, 0, 0, - 0, 284, 260, 1, 0, 0, 0, 284, 264, 1, 0, 0, 0, 284, 268, 1, 0, 0, 0, 284, - 277, 1, 0, 0, 0, 285, 40, 1, 0, 0, 0, 286, 287, 5, 36, 0, 0, 287, 288, - 3, 43, 21, 0, 288, 42, 1, 0, 0, 0, 289, 293, 7, 0, 0, 0, 290, 292, 7, 1, - 0, 0, 291, 290, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, - 293, 294, 1, 0, 0, 0, 294, 44, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 296, 298, - 7, 2, 0, 0, 297, 296, 1, 0, 0, 0, 298, 299, 1, 0, 0, 0, 299, 297, 1, 0, - 0, 0, 299, 300, 1, 0, 0, 0, 300, 301, 1, 0, 0, 0, 301, 302, 6, 22, 0, 0, - 302, 46, 1, 0, 0, 0, 303, 304, 5, 40, 0, 0, 304, 48, 1, 0, 0, 0, 305, 306, - 5, 41, 0, 0, 306, 50, 1, 0, 0, 0, 307, 308, 5, 91, 0, 0, 308, 52, 1, 0, - 0, 0, 309, 310, 5, 93, 0, 0, 310, 54, 1, 0, 0, 0, 311, 312, 5, 44, 0, 0, - 312, 56, 1, 0, 0, 0, 313, 314, 5, 124, 0, 0, 314, 58, 1, 0, 0, 0, 315, - 316, 5, 58, 0, 0, 316, 60, 1, 0, 0, 0, 317, 318, 5, 110, 0, 0, 318, 319, - 5, 117, 0, 0, 319, 320, 5, 108, 0, 0, 320, 326, 5, 108, 0, 0, 321, 322, - 5, 78, 0, 0, 322, 323, 5, 85, 0, 0, 323, 324, 5, 76, 0, 0, 324, 326, 5, - 76, 0, 0, 325, 317, 1, 0, 0, 0, 325, 321, 1, 0, 0, 0, 326, 62, 1, 0, 0, - 0, 327, 328, 3, 67, 33, 0, 328, 64, 1, 0, 0, 0, 329, 354, 3, 63, 31, 0, - 330, 332, 5, 45, 0, 0, 331, 330, 1, 0, 0, 0, 331, 332, 1, 0, 0, 0, 332, - 333, 1, 0, 0, 0, 333, 334, 3, 67, 33, 0, 334, 336, 5, 46, 0, 0, 335, 337, - 7, 3, 0, 0, 336, 335, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 336, 1, 0, - 0, 0, 338, 339, 1, 0, 0, 0, 339, 341, 1, 0, 0, 0, 340, 342, 3, 69, 34, - 0, 341, 340, 1, 0, 0, 0, 341, 342, 1, 0, 0, 0, 342, 354, 1, 0, 0, 0, 343, - 345, 5, 45, 0, 0, 344, 343, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 346, - 1, 0, 0, 0, 346, 347, 3, 67, 33, 0, 347, 348, 3, 69, 34, 0, 348, 354, 1, - 0, 0, 0, 349, 351, 5, 45, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, - 0, 351, 352, 1, 0, 0, 0, 352, 354, 3, 67, 33, 0, 353, 329, 1, 0, 0, 0, - 353, 331, 1, 0, 0, 0, 353, 344, 1, 0, 0, 0, 353, 350, 1, 0, 0, 0, 354, - 66, 1, 0, 0, 0, 355, 364, 5, 48, 0, 0, 356, 360, 7, 4, 0, 0, 357, 359, - 7, 3, 0, 0, 358, 357, 1, 0, 0, 0, 359, 362, 1, 0, 0, 0, 360, 358, 1, 0, - 0, 0, 360, 361, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, - 363, 355, 1, 0, 0, 0, 363, 356, 1, 0, 0, 0, 364, 68, 1, 0, 0, 0, 365, 367, - 7, 5, 0, 0, 366, 368, 7, 6, 0, 0, 367, 366, 1, 0, 0, 0, 367, 368, 1, 0, - 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 3, 67, 33, 0, 370, 70, 1, 0, 0, 0, - 371, 372, 5, 60, 0, 0, 372, 373, 5, 61, 0, 0, 373, 72, 1, 0, 0, 0, 374, - 375, 5, 60, 0, 0, 375, 74, 1, 0, 0, 0, 376, 377, 5, 62, 0, 0, 377, 378, - 5, 61, 0, 0, 378, 76, 1, 0, 0, 0, 379, 380, 5, 62, 0, 0, 380, 78, 1, 0, - 0, 0, 381, 382, 5, 33, 0, 0, 382, 383, 5, 61, 0, 0, 383, 80, 1, 0, 0, 0, - 384, 385, 5, 61, 0, 0, 385, 386, 5, 61, 0, 0, 386, 82, 1, 0, 0, 0, 387, - 391, 5, 46, 0, 0, 388, 392, 3, 41, 20, 0, 389, 392, 3, 43, 21, 0, 390, - 392, 3, 87, 43, 0, 391, 388, 1, 0, 0, 0, 391, 389, 1, 0, 0, 0, 391, 390, - 1, 0, 0, 0, 392, 84, 1, 0, 0, 0, 393, 394, 5, 64, 0, 0, 394, 395, 3, 43, - 21, 0, 395, 86, 1, 0, 0, 0, 396, 401, 5, 34, 0, 0, 397, 400, 3, 89, 44, - 0, 398, 400, 8, 7, 0, 0, 399, 397, 1, 0, 0, 0, 399, 398, 1, 0, 0, 0, 400, - 403, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 404, - 1, 0, 0, 0, 403, 401, 1, 0, 0, 0, 404, 405, 5, 34, 0, 0, 405, 88, 1, 0, - 0, 0, 406, 409, 5, 92, 0, 0, 407, 410, 7, 8, 0, 0, 408, 410, 3, 91, 45, - 0, 409, 407, 1, 0, 0, 0, 409, 408, 1, 0, 0, 0, 410, 90, 1, 0, 0, 0, 411, - 412, 5, 117, 0, 0, 412, 413, 3, 93, 46, 0, 413, 414, 3, 93, 46, 0, 414, - 415, 3, 93, 46, 0, 415, 416, 3, 93, 46, 0, 416, 92, 1, 0, 0, 0, 417, 418, - 7, 9, 0, 0, 418, 94, 1, 0, 0, 0, 419, 420, 7, 3, 0, 0, 420, 96, 1, 0, 0, - 0, 421, 422, 7, 10, 0, 0, 422, 98, 1, 0, 0, 0, 423, 424, 7, 11, 0, 0, 424, - 100, 1, 0, 0, 0, 425, 426, 7, 12, 0, 0, 426, 102, 1, 0, 0, 0, 427, 428, - 7, 13, 0, 0, 428, 104, 1, 0, 0, 0, 429, 430, 7, 5, 0, 0, 430, 106, 1, 0, - 0, 0, 431, 432, 7, 14, 0, 0, 432, 108, 1, 0, 0, 0, 433, 434, 7, 15, 0, - 0, 434, 110, 1, 0, 0, 0, 435, 436, 7, 16, 0, 0, 436, 112, 1, 0, 0, 0, 437, - 438, 7, 17, 0, 0, 438, 114, 1, 0, 0, 0, 439, 440, 7, 18, 0, 0, 440, 116, - 1, 0, 0, 0, 441, 442, 7, 19, 0, 0, 442, 118, 1, 0, 0, 0, 443, 444, 7, 20, - 0, 0, 444, 120, 1, 0, 0, 0, 445, 446, 7, 21, 0, 0, 446, 122, 1, 0, 0, 0, - 447, 448, 7, 22, 0, 0, 448, 124, 1, 0, 0, 0, 449, 450, 7, 23, 0, 0, 450, - 126, 1, 0, 0, 0, 451, 452, 7, 24, 0, 0, 452, 128, 1, 0, 0, 0, 453, 454, - 7, 25, 0, 0, 454, 130, 1, 0, 0, 0, 455, 456, 7, 26, 0, 0, 456, 132, 1, - 0, 0, 0, 457, 458, 7, 27, 0, 0, 458, 134, 1, 0, 0, 0, 459, 460, 7, 28, - 0, 0, 460, 136, 1, 0, 0, 0, 461, 462, 7, 29, 0, 0, 462, 138, 1, 0, 0, 0, - 463, 464, 7, 30, 0, 0, 464, 140, 1, 0, 0, 0, 465, 466, 7, 31, 0, 0, 466, - 142, 1, 0, 0, 0, 467, 468, 7, 32, 0, 0, 468, 144, 1, 0, 0, 0, 469, 470, - 7, 33, 0, 0, 470, 146, 1, 0, 0, 0, 471, 472, 7, 34, 0, 0, 472, 148, 1, - 0, 0, 0, 473, 477, 5, 35, 0, 0, 474, 476, 9, 0, 0, 0, 475, 474, 1, 0, 0, - 0, 476, 479, 1, 0, 0, 0, 477, 478, 1, 0, 0, 0, 477, 475, 1, 0, 0, 0, 478, - 480, 1, 0, 0, 0, 479, 477, 1, 0, 0, 0, 480, 481, 5, 10, 0, 0, 481, 482, - 1, 0, 0, 0, 482, 483, 6, 74, 0, 0, 483, 150, 1, 0, 0, 0, 20, 0, 226, 284, - 293, 299, 325, 331, 338, 341, 344, 350, 353, 360, 363, 367, 391, 399, 401, - 409, 477, 1, 6, 0, 0, + 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 5, 22, + 297, 8, 22, 10, 22, 12, 22, 300, 9, 22, 1, 23, 4, 23, 303, 8, 23, 11, 23, + 12, 23, 304, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, + 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, + 1, 32, 3, 32, 327, 8, 32, 1, 32, 1, 32, 1, 32, 4, 32, 332, 8, 32, 11, 32, + 12, 32, 333, 1, 32, 3, 32, 337, 8, 32, 1, 32, 3, 32, 340, 8, 32, 1, 32, + 1, 32, 1, 32, 1, 32, 3, 32, 346, 8, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, + 1, 33, 1, 33, 5, 33, 354, 8, 33, 10, 33, 12, 33, 357, 9, 33, 3, 33, 359, + 8, 33, 1, 34, 1, 34, 3, 34, 363, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, + 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, + 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 387, 8, 41, 1, + 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 5, 43, 395, 8, 43, 10, 43, 12, 43, + 398, 9, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 3, 44, 405, 8, 44, 1, 45, + 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, + 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, + 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, + 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, + 1, 64, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, + 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, + 5, 74, 471, 8, 74, 10, 74, 12, 74, 474, 9, 74, 1, 74, 1, 74, 1, 74, 1, + 74, 1, 472, 0, 75, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, + 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, + 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, + 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 0, 69, 0, 71, 34, + 73, 35, 75, 36, 77, 37, 79, 38, 81, 39, 83, 40, 85, 41, 87, 42, 89, 0, + 91, 0, 93, 0, 95, 0, 97, 0, 99, 0, 101, 0, 103, 0, 105, 0, 107, 0, 109, + 0, 111, 0, 113, 0, 115, 0, 117, 0, 119, 0, 121, 0, 123, 0, 125, 0, 127, + 0, 129, 0, 131, 0, 133, 0, 135, 0, 137, 0, 139, 0, 141, 0, 143, 0, 145, + 0, 147, 0, 149, 43, 1, 0, 35, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, + 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, + 1, 0, 49, 57, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, + 92, 92, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, + 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 65, 65, 97, 97, 2, + 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, + 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, + 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, + 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, + 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, + 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, + 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, + 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 473, + 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, + 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, + 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, + 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, + 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, + 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, + 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, + 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, + 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, + 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, + 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 149, + 1, 0, 0, 0, 1, 151, 1, 0, 0, 0, 3, 153, 1, 0, 0, 0, 5, 155, 1, 0, 0, 0, + 7, 160, 1, 0, 0, 0, 9, 167, 1, 0, 0, 0, 11, 173, 1, 0, 0, 0, 13, 176, 1, + 0, 0, 0, 15, 179, 1, 0, 0, 0, 17, 181, 1, 0, 0, 0, 19, 183, 1, 0, 0, 0, + 21, 186, 1, 0, 0, 0, 23, 189, 1, 0, 0, 0, 25, 191, 1, 0, 0, 0, 27, 194, + 1, 0, 0, 0, 29, 196, 1, 0, 0, 0, 31, 198, 1, 0, 0, 0, 33, 207, 1, 0, 0, + 0, 35, 209, 1, 0, 0, 0, 37, 226, 1, 0, 0, 0, 39, 284, 1, 0, 0, 0, 41, 286, + 1, 0, 0, 0, 43, 289, 1, 0, 0, 0, 45, 294, 1, 0, 0, 0, 47, 302, 1, 0, 0, + 0, 49, 308, 1, 0, 0, 0, 51, 310, 1, 0, 0, 0, 53, 312, 1, 0, 0, 0, 55, 314, + 1, 0, 0, 0, 57, 316, 1, 0, 0, 0, 59, 318, 1, 0, 0, 0, 61, 320, 1, 0, 0, + 0, 63, 322, 1, 0, 0, 0, 65, 348, 1, 0, 0, 0, 67, 358, 1, 0, 0, 0, 69, 360, + 1, 0, 0, 0, 71, 366, 1, 0, 0, 0, 73, 369, 1, 0, 0, 0, 75, 371, 1, 0, 0, + 0, 77, 374, 1, 0, 0, 0, 79, 376, 1, 0, 0, 0, 81, 379, 1, 0, 0, 0, 83, 382, + 1, 0, 0, 0, 85, 388, 1, 0, 0, 0, 87, 391, 1, 0, 0, 0, 89, 401, 1, 0, 0, + 0, 91, 406, 1, 0, 0, 0, 93, 412, 1, 0, 0, 0, 95, 414, 1, 0, 0, 0, 97, 416, + 1, 0, 0, 0, 99, 418, 1, 0, 0, 0, 101, 420, 1, 0, 0, 0, 103, 422, 1, 0, + 0, 0, 105, 424, 1, 0, 0, 0, 107, 426, 1, 0, 0, 0, 109, 428, 1, 0, 0, 0, + 111, 430, 1, 0, 0, 0, 113, 432, 1, 0, 0, 0, 115, 434, 1, 0, 0, 0, 117, + 436, 1, 0, 0, 0, 119, 438, 1, 0, 0, 0, 121, 440, 1, 0, 0, 0, 123, 442, + 1, 0, 0, 0, 125, 444, 1, 0, 0, 0, 127, 446, 1, 0, 0, 0, 129, 448, 1, 0, + 0, 0, 131, 450, 1, 0, 0, 0, 133, 452, 1, 0, 0, 0, 135, 454, 1, 0, 0, 0, + 137, 456, 1, 0, 0, 0, 139, 458, 1, 0, 0, 0, 141, 460, 1, 0, 0, 0, 143, + 462, 1, 0, 0, 0, 145, 464, 1, 0, 0, 0, 147, 466, 1, 0, 0, 0, 149, 468, + 1, 0, 0, 0, 151, 152, 5, 59, 0, 0, 152, 2, 1, 0, 0, 0, 153, 154, 5, 42, + 0, 0, 154, 4, 1, 0, 0, 0, 155, 156, 5, 106, 0, 0, 156, 157, 5, 111, 0, + 0, 157, 158, 5, 105, 0, 0, 158, 159, 5, 110, 0, 0, 159, 6, 1, 0, 0, 0, + 160, 161, 5, 117, 0, 0, 161, 162, 5, 110, 0, 0, 162, 163, 5, 105, 0, 0, + 163, 164, 5, 113, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 101, 0, 0, + 166, 8, 1, 0, 0, 0, 167, 168, 5, 99, 0, 0, 168, 169, 5, 111, 0, 0, 169, + 170, 5, 117, 0, 0, 170, 171, 5, 110, 0, 0, 171, 172, 5, 116, 0, 0, 172, + 10, 1, 0, 0, 0, 173, 174, 5, 46, 0, 0, 174, 175, 5, 91, 0, 0, 175, 12, + 1, 0, 0, 0, 176, 177, 5, 124, 0, 0, 177, 178, 5, 124, 0, 0, 178, 14, 1, + 0, 0, 0, 179, 180, 5, 47, 0, 0, 180, 16, 1, 0, 0, 0, 181, 182, 5, 37, 0, + 0, 182, 18, 1, 0, 0, 0, 183, 184, 5, 60, 0, 0, 184, 185, 5, 60, 0, 0, 185, + 20, 1, 0, 0, 0, 186, 187, 5, 62, 0, 0, 187, 188, 5, 62, 0, 0, 188, 22, + 1, 0, 0, 0, 189, 190, 5, 38, 0, 0, 190, 24, 1, 0, 0, 0, 191, 192, 5, 38, + 0, 0, 192, 193, 5, 38, 0, 0, 193, 26, 1, 0, 0, 0, 194, 195, 5, 126, 0, + 0, 195, 28, 1, 0, 0, 0, 196, 197, 5, 33, 0, 0, 197, 30, 1, 0, 0, 0, 198, + 199, 5, 103, 0, 0, 199, 200, 5, 114, 0, 0, 200, 201, 5, 111, 0, 0, 201, + 202, 5, 117, 0, 0, 202, 203, 5, 112, 0, 0, 203, 204, 5, 95, 0, 0, 204, + 205, 5, 98, 0, 0, 205, 206, 5, 121, 0, 0, 206, 32, 1, 0, 0, 0, 207, 208, + 5, 43, 0, 0, 208, 34, 1, 0, 0, 0, 209, 210, 5, 45, 0, 0, 210, 36, 1, 0, + 0, 0, 211, 212, 5, 111, 0, 0, 212, 213, 5, 114, 0, 0, 213, 214, 5, 100, + 0, 0, 214, 215, 5, 101, 0, 0, 215, 216, 5, 114, 0, 0, 216, 217, 5, 95, + 0, 0, 217, 218, 5, 98, 0, 0, 218, 227, 5, 121, 0, 0, 219, 220, 5, 115, + 0, 0, 220, 221, 5, 111, 0, 0, 221, 222, 5, 114, 0, 0, 222, 223, 5, 116, + 0, 0, 223, 224, 5, 95, 0, 0, 224, 225, 5, 98, 0, 0, 225, 227, 5, 121, 0, + 0, 226, 211, 1, 0, 0, 0, 226, 219, 1, 0, 0, 0, 227, 38, 1, 0, 0, 0, 228, + 229, 5, 58, 0, 0, 229, 230, 5, 99, 0, 0, 230, 231, 5, 111, 0, 0, 231, 232, + 5, 117, 0, 0, 232, 233, 5, 110, 0, 0, 233, 285, 5, 116, 0, 0, 234, 235, + 5, 58, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, + 117, 0, 0, 238, 239, 5, 110, 0, 0, 239, 240, 5, 116, 0, 0, 240, 241, 5, + 95, 0, 0, 241, 242, 5, 117, 0, 0, 242, 243, 5, 110, 0, 0, 243, 244, 5, + 105, 0, 0, 244, 245, 5, 113, 0, 0, 245, 246, 5, 117, 0, 0, 246, 285, 5, + 101, 0, 0, 247, 248, 5, 58, 0, 0, 248, 249, 5, 97, 0, 0, 249, 250, 5, 118, + 0, 0, 250, 285, 5, 103, 0, 0, 251, 252, 5, 58, 0, 0, 252, 253, 5, 103, + 0, 0, 253, 254, 5, 114, 0, 0, 254, 255, 5, 111, 0, 0, 255, 256, 5, 117, + 0, 0, 256, 257, 5, 112, 0, 0, 257, 258, 5, 95, 0, 0, 258, 259, 5, 98, 0, + 0, 259, 285, 5, 121, 0, 0, 260, 261, 5, 58, 0, 0, 261, 262, 5, 109, 0, + 0, 262, 263, 5, 97, 0, 0, 263, 285, 5, 120, 0, 0, 264, 265, 5, 58, 0, 0, + 265, 266, 5, 109, 0, 0, 266, 267, 5, 105, 0, 0, 267, 285, 5, 110, 0, 0, + 268, 269, 5, 58, 0, 0, 269, 270, 5, 111, 0, 0, 270, 271, 5, 114, 0, 0, + 271, 272, 5, 100, 0, 0, 272, 273, 5, 101, 0, 0, 273, 274, 5, 114, 0, 0, + 274, 275, 5, 95, 0, 0, 275, 276, 5, 98, 0, 0, 276, 285, 5, 121, 0, 0, 277, + 278, 5, 58, 0, 0, 278, 279, 5, 117, 0, 0, 279, 280, 5, 110, 0, 0, 280, + 281, 5, 105, 0, 0, 281, 282, 5, 113, 0, 0, 282, 283, 5, 117, 0, 0, 283, + 285, 5, 101, 0, 0, 284, 228, 1, 0, 0, 0, 284, 234, 1, 0, 0, 0, 284, 247, + 1, 0, 0, 0, 284, 251, 1, 0, 0, 0, 284, 260, 1, 0, 0, 0, 284, 264, 1, 0, + 0, 0, 284, 268, 1, 0, 0, 0, 284, 277, 1, 0, 0, 0, 285, 40, 1, 0, 0, 0, + 286, 287, 5, 36, 0, 0, 287, 288, 3, 45, 22, 0, 288, 42, 1, 0, 0, 0, 289, + 290, 5, 110, 0, 0, 290, 291, 5, 117, 0, 0, 291, 292, 5, 108, 0, 0, 292, + 293, 5, 108, 0, 0, 293, 44, 1, 0, 0, 0, 294, 298, 7, 0, 0, 0, 295, 297, + 7, 1, 0, 0, 296, 295, 1, 0, 0, 0, 297, 300, 1, 0, 0, 0, 298, 296, 1, 0, + 0, 0, 298, 299, 1, 0, 0, 0, 299, 46, 1, 0, 0, 0, 300, 298, 1, 0, 0, 0, + 301, 303, 7, 2, 0, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, + 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, + 6, 23, 0, 0, 307, 48, 1, 0, 0, 0, 308, 309, 5, 40, 0, 0, 309, 50, 1, 0, + 0, 0, 310, 311, 5, 41, 0, 0, 311, 52, 1, 0, 0, 0, 312, 313, 5, 91, 0, 0, + 313, 54, 1, 0, 0, 0, 314, 315, 5, 93, 0, 0, 315, 56, 1, 0, 0, 0, 316, 317, + 5, 44, 0, 0, 317, 58, 1, 0, 0, 0, 318, 319, 5, 124, 0, 0, 319, 60, 1, 0, + 0, 0, 320, 321, 5, 58, 0, 0, 321, 62, 1, 0, 0, 0, 322, 323, 3, 67, 33, + 0, 323, 64, 1, 0, 0, 0, 324, 349, 3, 63, 31, 0, 325, 327, 5, 45, 0, 0, + 326, 325, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, + 329, 3, 67, 33, 0, 329, 331, 5, 46, 0, 0, 330, 332, 7, 3, 0, 0, 331, 330, + 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 331, 1, 0, 0, 0, 333, 334, 1, 0, + 0, 0, 334, 336, 1, 0, 0, 0, 335, 337, 3, 69, 34, 0, 336, 335, 1, 0, 0, + 0, 336, 337, 1, 0, 0, 0, 337, 349, 1, 0, 0, 0, 338, 340, 5, 45, 0, 0, 339, + 338, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 341, 1, 0, 0, 0, 341, 342, + 3, 67, 33, 0, 342, 343, 3, 69, 34, 0, 343, 349, 1, 0, 0, 0, 344, 346, 5, + 45, 0, 0, 345, 344, 1, 0, 0, 0, 345, 346, 1, 0, 0, 0, 346, 347, 1, 0, 0, + 0, 347, 349, 3, 67, 33, 0, 348, 324, 1, 0, 0, 0, 348, 326, 1, 0, 0, 0, + 348, 339, 1, 0, 0, 0, 348, 345, 1, 0, 0, 0, 349, 66, 1, 0, 0, 0, 350, 359, + 5, 48, 0, 0, 351, 355, 7, 4, 0, 0, 352, 354, 7, 3, 0, 0, 353, 352, 1, 0, + 0, 0, 354, 357, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 355, 356, 1, 0, 0, 0, + 356, 359, 1, 0, 0, 0, 357, 355, 1, 0, 0, 0, 358, 350, 1, 0, 0, 0, 358, + 351, 1, 0, 0, 0, 359, 68, 1, 0, 0, 0, 360, 362, 7, 5, 0, 0, 361, 363, 7, + 6, 0, 0, 362, 361, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 364, 1, 0, 0, + 0, 364, 365, 3, 67, 33, 0, 365, 70, 1, 0, 0, 0, 366, 367, 5, 60, 0, 0, + 367, 368, 5, 61, 0, 0, 368, 72, 1, 0, 0, 0, 369, 370, 5, 60, 0, 0, 370, + 74, 1, 0, 0, 0, 371, 372, 5, 62, 0, 0, 372, 373, 5, 61, 0, 0, 373, 76, + 1, 0, 0, 0, 374, 375, 5, 62, 0, 0, 375, 78, 1, 0, 0, 0, 376, 377, 5, 33, + 0, 0, 377, 378, 5, 61, 0, 0, 378, 80, 1, 0, 0, 0, 379, 380, 5, 61, 0, 0, + 380, 381, 5, 61, 0, 0, 381, 82, 1, 0, 0, 0, 382, 386, 5, 46, 0, 0, 383, + 387, 3, 41, 20, 0, 384, 387, 3, 45, 22, 0, 385, 387, 3, 87, 43, 0, 386, + 383, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0, 386, 385, 1, 0, 0, 0, 387, 84, 1, + 0, 0, 0, 388, 389, 5, 64, 0, 0, 389, 390, 3, 45, 22, 0, 390, 86, 1, 0, + 0, 0, 391, 396, 5, 34, 0, 0, 392, 395, 3, 89, 44, 0, 393, 395, 8, 7, 0, + 0, 394, 392, 1, 0, 0, 0, 394, 393, 1, 0, 0, 0, 395, 398, 1, 0, 0, 0, 396, + 394, 1, 0, 0, 0, 396, 397, 1, 0, 0, 0, 397, 399, 1, 0, 0, 0, 398, 396, + 1, 0, 0, 0, 399, 400, 5, 34, 0, 0, 400, 88, 1, 0, 0, 0, 401, 404, 5, 92, + 0, 0, 402, 405, 7, 8, 0, 0, 403, 405, 3, 91, 45, 0, 404, 402, 1, 0, 0, + 0, 404, 403, 1, 0, 0, 0, 405, 90, 1, 0, 0, 0, 406, 407, 5, 117, 0, 0, 407, + 408, 3, 93, 46, 0, 408, 409, 3, 93, 46, 0, 409, 410, 3, 93, 46, 0, 410, + 411, 3, 93, 46, 0, 411, 92, 1, 0, 0, 0, 412, 413, 7, 9, 0, 0, 413, 94, + 1, 0, 0, 0, 414, 415, 7, 3, 0, 0, 415, 96, 1, 0, 0, 0, 416, 417, 7, 10, + 0, 0, 417, 98, 1, 0, 0, 0, 418, 419, 7, 11, 0, 0, 419, 100, 1, 0, 0, 0, + 420, 421, 7, 12, 0, 0, 421, 102, 1, 0, 0, 0, 422, 423, 7, 13, 0, 0, 423, + 104, 1, 0, 0, 0, 424, 425, 7, 5, 0, 0, 425, 106, 1, 0, 0, 0, 426, 427, + 7, 14, 0, 0, 427, 108, 1, 0, 0, 0, 428, 429, 7, 15, 0, 0, 429, 110, 1, + 0, 0, 0, 430, 431, 7, 16, 0, 0, 431, 112, 1, 0, 0, 0, 432, 433, 7, 17, + 0, 0, 433, 114, 1, 0, 0, 0, 434, 435, 7, 18, 0, 0, 435, 116, 1, 0, 0, 0, + 436, 437, 7, 19, 0, 0, 437, 118, 1, 0, 0, 0, 438, 439, 7, 20, 0, 0, 439, + 120, 1, 0, 0, 0, 440, 441, 7, 21, 0, 0, 441, 122, 1, 0, 0, 0, 442, 443, + 7, 22, 0, 0, 443, 124, 1, 0, 0, 0, 444, 445, 7, 23, 0, 0, 445, 126, 1, + 0, 0, 0, 446, 447, 7, 24, 0, 0, 447, 128, 1, 0, 0, 0, 448, 449, 7, 25, + 0, 0, 449, 130, 1, 0, 0, 0, 450, 451, 7, 26, 0, 0, 451, 132, 1, 0, 0, 0, + 452, 453, 7, 27, 0, 0, 453, 134, 1, 0, 0, 0, 454, 455, 7, 28, 0, 0, 455, + 136, 1, 0, 0, 0, 456, 457, 7, 29, 0, 0, 457, 138, 1, 0, 0, 0, 458, 459, + 7, 30, 0, 0, 459, 140, 1, 0, 0, 0, 460, 461, 7, 31, 0, 0, 461, 142, 1, + 0, 0, 0, 462, 463, 7, 32, 0, 0, 463, 144, 1, 0, 0, 0, 464, 465, 7, 33, + 0, 0, 465, 146, 1, 0, 0, 0, 466, 467, 7, 34, 0, 0, 467, 148, 1, 0, 0, 0, + 468, 472, 5, 35, 0, 0, 469, 471, 9, 0, 0, 0, 470, 469, 1, 0, 0, 0, 471, + 474, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 473, 475, + 1, 0, 0, 0, 474, 472, 1, 0, 0, 0, 475, 476, 5, 10, 0, 0, 476, 477, 1, 0, + 0, 0, 477, 478, 6, 74, 0, 0, 478, 150, 1, 0, 0, 0, 19, 0, 226, 284, 298, + 304, 326, 333, 336, 339, 345, 348, 355, 358, 362, 386, 394, 396, 404, 472, + 1, 6, 0, 0, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) @@ -346,16 +344,16 @@ const ( SLQLexerORDER_BY = 19 SLQLexerALIAS_RESERVED = 20 SLQLexerARG = 21 - SLQLexerID = 22 - SLQLexerWS = 23 - SLQLexerLPAR = 24 - SLQLexerRPAR = 25 - SLQLexerLBRA = 26 - SLQLexerRBRA = 27 - SLQLexerCOMMA = 28 - SLQLexerPIPE = 29 - SLQLexerCOLON = 30 - SLQLexerNULL = 31 + SLQLexerNULL = 22 + SLQLexerID = 23 + SLQLexerWS = 24 + SLQLexerLPAR = 25 + SLQLexerRPAR = 26 + SLQLexerLBRA = 27 + SLQLexerRBRA = 28 + SLQLexerCOMMA = 29 + SLQLexerPIPE = 30 + SLQLexerCOLON = 31 SLQLexerNN = 32 SLQLexerNUMBER = 33 SLQLexerLT_EQ = 34 diff --git a/libsq/ast/internal/slq/slq_listener.go b/libsq/ast/internal/slq/slq_listener.go index e5fd7a2e..acc178ec 100644 --- a/libsq/ast/internal/slq/slq_listener.go +++ b/libsq/ast/internal/slq/slq_listener.go @@ -64,6 +64,9 @@ type SLQListener interface { // EnterAlias is called when entering the alias production. EnterAlias(c *AliasContext) + // EnterArg is called when entering the arg production. + EnterArg(c *ArgContext) + // EnterHandleTable is called when entering the handleTable production. EnterHandleTable(c *HandleTableContext) @@ -139,6 +142,9 @@ type SLQListener interface { // ExitAlias is called when exiting the alias production. ExitAlias(c *AliasContext) + // ExitArg is called when exiting the arg production. + ExitArg(c *ArgContext) + // ExitHandleTable is called when exiting the handleTable production. ExitHandleTable(c *HandleTableContext) diff --git a/libsq/ast/internal/slq/slq_parser.go b/libsq/ast/internal/slq/slq_parser.go index 5034dd86..b34d10df 100644 --- a/libsq/ast/internal/slq/slq_parser.go +++ b/libsq/ast/internal/slq/slq_parser.go @@ -34,13 +34,13 @@ func slqParserInit() { staticData.literalNames = []string{ "", "';'", "'*'", "'join'", "'unique'", "'count'", "'.['", "'||'", "'/'", "'%'", "'<<'", "'>>'", "'&'", "'&&'", "'~'", "'!'", "'group_by'", "'+'", - "'-'", "", "", "", "", "", "'('", "')'", "'['", "']'", "','", "'|'", - "':'", "", "", "", "'<='", "'<'", "'>='", "'>'", "'!='", "'=='", + "'-'", "", "", "", "'null'", "", "", "'('", "')'", "'['", "']'", "','", + "'|'", "':'", "", "", "'<='", "'<'", "'>='", "'>'", "'!='", "'=='", } staticData.symbolicNames = []string{ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GROUP_BY", - "ORDER_ASC", "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "ID", - "WS", "LPAR", "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NULL", + "ORDER_ASC", "ORDER_DESC", "ORDER_BY", "ALIAS_RESERVED", "ARG", "NULL", + "ID", "WS", "LPAR", "RPAR", "LBRA", "RBRA", "COMMA", "PIPE", "COLON", "NN", "NUMBER", "LT_EQ", "LT", "GT_EQ", "GT", "NEQ", "EQ", "NAME", "HANDLE", "STRING", "LINECOMMENT", } @@ -48,126 +48,129 @@ func slqParserInit() { "stmtList", "query", "segment", "element", "cmpr", "funcElement", "func", "funcName", "join", "joinConstraint", "uniqueFunc", "countFunc", "groupByTerm", "groupBy", "orderByTerm", "orderBy", "selector", "selectorElement", - "alias", "handleTable", "handle", "rowRange", "expr", "literal", "unaryOperator", + "alias", "arg", "handleTable", "handle", "rowRange", "expr", "literal", + "unaryOperator", } staticData.predictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 1, 43, 258, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 1, 43, 263, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, - 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 1, 0, 5, 0, 52, 8, - 0, 10, 0, 12, 0, 55, 9, 0, 1, 0, 1, 0, 4, 0, 59, 8, 0, 11, 0, 12, 0, 60, - 1, 0, 5, 0, 64, 8, 0, 10, 0, 12, 0, 67, 9, 0, 1, 0, 5, 0, 70, 8, 0, 10, - 0, 12, 0, 73, 9, 0, 1, 1, 1, 1, 1, 1, 5, 1, 78, 8, 1, 10, 1, 12, 1, 81, - 9, 1, 1, 2, 1, 2, 1, 2, 5, 2, 86, 8, 2, 10, 2, 12, 2, 89, 9, 2, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 102, 8, - 3, 1, 4, 1, 4, 1, 5, 1, 5, 3, 5, 108, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, - 6, 5, 6, 115, 8, 6, 10, 6, 12, 6, 118, 9, 6, 1, 6, 3, 6, 121, 8, 6, 1, - 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, - 9, 1, 9, 3, 9, 137, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 3, 11, 144, - 8, 11, 1, 11, 3, 11, 147, 8, 11, 1, 11, 3, 11, 150, 8, 11, 1, 12, 1, 12, - 3, 12, 154, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 161, 8, 13, - 10, 13, 12, 13, 164, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 3, 14, 170, 8, - 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 177, 8, 15, 10, 15, 12, 15, - 180, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 186, 8, 16, 1, 17, 1, 17, - 3, 17, 190, 8, 17, 1, 18, 1, 18, 1, 18, 3, 18, 195, 8, 18, 1, 19, 1, 19, - 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, - 21, 1, 21, 3, 21, 211, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, - 1, 22, 1, 22, 1, 22, 3, 22, 222, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, - 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, - 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 243, 8, 22, 1, 22, 1, 22, 1, 22, 1, - 22, 5, 22, 249, 8, 22, 10, 22, 12, 22, 252, 9, 22, 1, 23, 1, 23, 1, 24, - 1, 24, 1, 24, 0, 1, 44, 25, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, - 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 0, 8, 1, 0, 34, 39, - 1, 0, 17, 18, 1, 0, 21, 22, 2, 0, 2, 2, 8, 9, 1, 0, 10, 12, 1, 0, 34, 37, - 2, 0, 31, 33, 42, 42, 2, 0, 14, 15, 17, 18, 279, 0, 53, 1, 0, 0, 0, 2, - 74, 1, 0, 0, 0, 4, 82, 1, 0, 0, 0, 6, 101, 1, 0, 0, 0, 8, 103, 1, 0, 0, - 0, 10, 105, 1, 0, 0, 0, 12, 109, 1, 0, 0, 0, 14, 124, 1, 0, 0, 0, 16, 126, - 1, 0, 0, 0, 18, 136, 1, 0, 0, 0, 20, 138, 1, 0, 0, 0, 22, 140, 1, 0, 0, - 0, 24, 153, 1, 0, 0, 0, 26, 155, 1, 0, 0, 0, 28, 167, 1, 0, 0, 0, 30, 171, - 1, 0, 0, 0, 32, 183, 1, 0, 0, 0, 34, 187, 1, 0, 0, 0, 36, 194, 1, 0, 0, - 0, 38, 196, 1, 0, 0, 0, 40, 199, 1, 0, 0, 0, 42, 201, 1, 0, 0, 0, 44, 221, - 1, 0, 0, 0, 46, 253, 1, 0, 0, 0, 48, 255, 1, 0, 0, 0, 50, 52, 5, 1, 0, - 0, 51, 50, 1, 0, 0, 0, 52, 55, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 53, 54, - 1, 0, 0, 0, 54, 56, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 56, 65, 3, 2, 1, 0, - 57, 59, 5, 1, 0, 0, 58, 57, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 58, 1, - 0, 0, 0, 60, 61, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 64, 3, 2, 1, 0, 63, - 58, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, - 0, 66, 71, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 70, 5, 1, 0, 0, 69, 68, - 1, 0, 0, 0, 70, 73, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, - 72, 1, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 74, 79, 3, 4, 2, 0, 75, 76, 5, 29, - 0, 0, 76, 78, 3, 4, 2, 0, 77, 75, 1, 0, 0, 0, 78, 81, 1, 0, 0, 0, 79, 77, - 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 3, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, - 82, 87, 3, 6, 3, 0, 83, 84, 5, 28, 0, 0, 84, 86, 3, 6, 3, 0, 85, 83, 1, - 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, - 5, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 102, 3, 38, 19, 0, 91, 102, 3, 40, - 20, 0, 92, 102, 3, 34, 17, 0, 93, 102, 3, 16, 8, 0, 94, 102, 3, 26, 13, - 0, 95, 102, 3, 30, 15, 0, 96, 102, 3, 42, 21, 0, 97, 102, 3, 20, 10, 0, - 98, 102, 3, 22, 11, 0, 99, 102, 3, 10, 5, 0, 100, 102, 3, 44, 22, 0, 101, - 90, 1, 0, 0, 0, 101, 91, 1, 0, 0, 0, 101, 92, 1, 0, 0, 0, 101, 93, 1, 0, - 0, 0, 101, 94, 1, 0, 0, 0, 101, 95, 1, 0, 0, 0, 101, 96, 1, 0, 0, 0, 101, - 97, 1, 0, 0, 0, 101, 98, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 100, 1, - 0, 0, 0, 102, 7, 1, 0, 0, 0, 103, 104, 7, 0, 0, 0, 104, 9, 1, 0, 0, 0, - 105, 107, 3, 12, 6, 0, 106, 108, 3, 36, 18, 0, 107, 106, 1, 0, 0, 0, 107, - 108, 1, 0, 0, 0, 108, 11, 1, 0, 0, 0, 109, 110, 3, 14, 7, 0, 110, 120, - 5, 24, 0, 0, 111, 116, 3, 44, 22, 0, 112, 113, 5, 28, 0, 0, 113, 115, 3, - 44, 22, 0, 114, 112, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, - 0, 0, 116, 117, 1, 0, 0, 0, 117, 121, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, - 119, 121, 5, 2, 0, 0, 120, 111, 1, 0, 0, 0, 120, 119, 1, 0, 0, 0, 120, - 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 25, 0, 0, 123, 13, - 1, 0, 0, 0, 124, 125, 5, 22, 0, 0, 125, 15, 1, 0, 0, 0, 126, 127, 5, 3, - 0, 0, 127, 128, 5, 24, 0, 0, 128, 129, 3, 18, 9, 0, 129, 130, 5, 25, 0, - 0, 130, 17, 1, 0, 0, 0, 131, 132, 3, 32, 16, 0, 132, 133, 3, 8, 4, 0, 133, - 134, 3, 32, 16, 0, 134, 137, 1, 0, 0, 0, 135, 137, 3, 32, 16, 0, 136, 131, - 1, 0, 0, 0, 136, 135, 1, 0, 0, 0, 137, 19, 1, 0, 0, 0, 138, 139, 5, 4, - 0, 0, 139, 21, 1, 0, 0, 0, 140, 146, 5, 5, 0, 0, 141, 143, 5, 24, 0, 0, - 142, 144, 3, 32, 16, 0, 143, 142, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, - 145, 1, 0, 0, 0, 145, 147, 5, 25, 0, 0, 146, 141, 1, 0, 0, 0, 146, 147, - 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 3, 36, 18, 0, 149, 148, 1, - 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 23, 1, 0, 0, 0, 151, 154, 3, 32, 16, - 0, 152, 154, 3, 12, 6, 0, 153, 151, 1, 0, 0, 0, 153, 152, 1, 0, 0, 0, 154, - 25, 1, 0, 0, 0, 155, 156, 5, 16, 0, 0, 156, 157, 5, 24, 0, 0, 157, 162, - 3, 24, 12, 0, 158, 159, 5, 28, 0, 0, 159, 161, 3, 24, 12, 0, 160, 158, - 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, - 0, 0, 163, 165, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 5, 25, 0, 0, - 166, 27, 1, 0, 0, 0, 167, 169, 3, 32, 16, 0, 168, 170, 7, 1, 0, 0, 169, - 168, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 29, 1, 0, 0, 0, 171, 172, 5, - 19, 0, 0, 172, 173, 5, 24, 0, 0, 173, 178, 3, 28, 14, 0, 174, 175, 5, 28, - 0, 0, 175, 177, 3, 28, 14, 0, 176, 174, 1, 0, 0, 0, 177, 180, 1, 0, 0, - 0, 178, 176, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 181, 1, 0, 0, 0, 180, - 178, 1, 0, 0, 0, 181, 182, 5, 25, 0, 0, 182, 31, 1, 0, 0, 0, 183, 185, - 5, 40, 0, 0, 184, 186, 5, 40, 0, 0, 185, 184, 1, 0, 0, 0, 185, 186, 1, - 0, 0, 0, 186, 33, 1, 0, 0, 0, 187, 189, 3, 32, 16, 0, 188, 190, 3, 36, - 18, 0, 189, 188, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 35, 1, 0, 0, 0, - 191, 195, 5, 20, 0, 0, 192, 193, 5, 30, 0, 0, 193, 195, 7, 2, 0, 0, 194, - 191, 1, 0, 0, 0, 194, 192, 1, 0, 0, 0, 195, 37, 1, 0, 0, 0, 196, 197, 5, - 41, 0, 0, 197, 198, 5, 40, 0, 0, 198, 39, 1, 0, 0, 0, 199, 200, 5, 41, - 0, 0, 200, 41, 1, 0, 0, 0, 201, 210, 5, 6, 0, 0, 202, 203, 5, 32, 0, 0, - 203, 204, 5, 30, 0, 0, 204, 211, 5, 32, 0, 0, 205, 206, 5, 32, 0, 0, 206, - 211, 5, 30, 0, 0, 207, 208, 5, 30, 0, 0, 208, 211, 5, 32, 0, 0, 209, 211, - 5, 32, 0, 0, 210, 202, 1, 0, 0, 0, 210, 205, 1, 0, 0, 0, 210, 207, 1, 0, - 0, 0, 210, 209, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 212, 1, 0, 0, 0, - 212, 213, 5, 27, 0, 0, 213, 43, 1, 0, 0, 0, 214, 215, 6, 22, -1, 0, 215, - 222, 3, 32, 16, 0, 216, 222, 3, 46, 23, 0, 217, 218, 3, 48, 24, 0, 218, - 219, 3, 44, 22, 9, 219, 222, 1, 0, 0, 0, 220, 222, 3, 12, 6, 0, 221, 214, - 1, 0, 0, 0, 221, 216, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 220, 1, 0, - 0, 0, 222, 250, 1, 0, 0, 0, 223, 224, 10, 8, 0, 0, 224, 225, 5, 7, 0, 0, - 225, 249, 3, 44, 22, 9, 226, 227, 10, 7, 0, 0, 227, 228, 7, 3, 0, 0, 228, - 249, 3, 44, 22, 8, 229, 230, 10, 6, 0, 0, 230, 231, 7, 1, 0, 0, 231, 249, - 3, 44, 22, 7, 232, 233, 10, 5, 0, 0, 233, 234, 7, 4, 0, 0, 234, 249, 3, - 44, 22, 6, 235, 236, 10, 4, 0, 0, 236, 237, 7, 5, 0, 0, 237, 249, 3, 44, - 22, 5, 238, 242, 10, 3, 0, 0, 239, 243, 5, 39, 0, 0, 240, 243, 5, 38, 0, - 0, 241, 243, 1, 0, 0, 0, 242, 239, 1, 0, 0, 0, 242, 240, 1, 0, 0, 0, 242, - 241, 1, 0, 0, 0, 243, 244, 1, 0, 0, 0, 244, 249, 3, 44, 22, 4, 245, 246, - 10, 2, 0, 0, 246, 247, 5, 13, 0, 0, 247, 249, 3, 44, 22, 3, 248, 223, 1, - 0, 0, 0, 248, 226, 1, 0, 0, 0, 248, 229, 1, 0, 0, 0, 248, 232, 1, 0, 0, - 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 249, - 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 45, 1, - 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 254, 7, 6, 0, 0, 254, 47, 1, 0, 0, - 0, 255, 256, 7, 7, 0, 0, 256, 49, 1, 0, 0, 0, 26, 53, 60, 65, 71, 79, 87, - 101, 107, 116, 120, 136, 143, 146, 149, 153, 162, 169, 178, 185, 189, 194, - 210, 221, 242, 248, 250, + 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 1, 0, + 5, 0, 54, 8, 0, 10, 0, 12, 0, 57, 9, 0, 1, 0, 1, 0, 4, 0, 61, 8, 0, 11, + 0, 12, 0, 62, 1, 0, 5, 0, 66, 8, 0, 10, 0, 12, 0, 69, 9, 0, 1, 0, 5, 0, + 72, 8, 0, 10, 0, 12, 0, 75, 9, 0, 1, 1, 1, 1, 1, 1, 5, 1, 80, 8, 1, 10, + 1, 12, 1, 83, 9, 1, 1, 2, 1, 2, 1, 2, 5, 2, 88, 8, 2, 10, 2, 12, 2, 91, + 9, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 3, 3, 104, 8, 3, 1, 4, 1, 4, 1, 5, 1, 5, 3, 5, 110, 8, 5, 1, 6, 1, 6, 1, + 6, 1, 6, 1, 6, 5, 6, 117, 8, 6, 10, 6, 12, 6, 120, 9, 6, 1, 6, 3, 6, 123, + 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, + 1, 9, 1, 9, 1, 9, 3, 9, 139, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 3, + 11, 146, 8, 11, 1, 11, 3, 11, 149, 8, 11, 1, 11, 3, 11, 152, 8, 11, 1, + 12, 1, 12, 3, 12, 156, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, + 163, 8, 13, 10, 13, 12, 13, 166, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 3, + 14, 172, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 179, 8, 15, 10, + 15, 12, 15, 182, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 3, 16, 188, 8, 16, + 1, 17, 1, 17, 3, 17, 192, 8, 17, 1, 18, 1, 18, 1, 18, 3, 18, 197, 8, 18, + 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, + 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 215, 8, 22, 1, 22, 1, 22, + 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 227, 8, + 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, + 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 248, + 8, 23, 1, 23, 1, 23, 1, 23, 1, 23, 5, 23, 254, 8, 23, 10, 23, 12, 23, 257, + 9, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 0, 1, 46, 26, 0, 2, 4, 6, 8, + 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 0, 8, 1, 0, 34, 39, 1, 0, 17, 18, 2, 0, 21, 21, 23, 23, 2, + 0, 2, 2, 8, 9, 1, 0, 10, 12, 1, 0, 34, 37, 3, 0, 22, 22, 32, 33, 42, 42, + 2, 0, 14, 15, 17, 18, 284, 0, 55, 1, 0, 0, 0, 2, 76, 1, 0, 0, 0, 4, 84, + 1, 0, 0, 0, 6, 103, 1, 0, 0, 0, 8, 105, 1, 0, 0, 0, 10, 107, 1, 0, 0, 0, + 12, 111, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, 18, 138, + 1, 0, 0, 0, 20, 140, 1, 0, 0, 0, 22, 142, 1, 0, 0, 0, 24, 155, 1, 0, 0, + 0, 26, 157, 1, 0, 0, 0, 28, 169, 1, 0, 0, 0, 30, 173, 1, 0, 0, 0, 32, 185, + 1, 0, 0, 0, 34, 189, 1, 0, 0, 0, 36, 196, 1, 0, 0, 0, 38, 198, 1, 0, 0, + 0, 40, 200, 1, 0, 0, 0, 42, 203, 1, 0, 0, 0, 44, 205, 1, 0, 0, 0, 46, 226, + 1, 0, 0, 0, 48, 258, 1, 0, 0, 0, 50, 260, 1, 0, 0, 0, 52, 54, 5, 1, 0, + 0, 53, 52, 1, 0, 0, 0, 54, 57, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 56, + 1, 0, 0, 0, 56, 58, 1, 0, 0, 0, 57, 55, 1, 0, 0, 0, 58, 67, 3, 2, 1, 0, + 59, 61, 5, 1, 0, 0, 60, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 60, 1, + 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 66, 3, 2, 1, 0, 65, + 60, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, + 0, 68, 73, 1, 0, 0, 0, 69, 67, 1, 0, 0, 0, 70, 72, 5, 1, 0, 0, 71, 70, + 1, 0, 0, 0, 72, 75, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, + 74, 1, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 76, 81, 3, 4, 2, 0, 77, 78, 5, 30, + 0, 0, 78, 80, 3, 4, 2, 0, 79, 77, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, + 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 3, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, + 84, 89, 3, 6, 3, 0, 85, 86, 5, 29, 0, 0, 86, 88, 3, 6, 3, 0, 87, 85, 1, + 0, 0, 0, 88, 91, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, + 5, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 92, 104, 3, 40, 20, 0, 93, 104, 3, 42, + 21, 0, 94, 104, 3, 34, 17, 0, 95, 104, 3, 16, 8, 0, 96, 104, 3, 26, 13, + 0, 97, 104, 3, 30, 15, 0, 98, 104, 3, 44, 22, 0, 99, 104, 3, 20, 10, 0, + 100, 104, 3, 22, 11, 0, 101, 104, 3, 10, 5, 0, 102, 104, 3, 46, 23, 0, + 103, 92, 1, 0, 0, 0, 103, 93, 1, 0, 0, 0, 103, 94, 1, 0, 0, 0, 103, 95, + 1, 0, 0, 0, 103, 96, 1, 0, 0, 0, 103, 97, 1, 0, 0, 0, 103, 98, 1, 0, 0, + 0, 103, 99, 1, 0, 0, 0, 103, 100, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, + 102, 1, 0, 0, 0, 104, 7, 1, 0, 0, 0, 105, 106, 7, 0, 0, 0, 106, 9, 1, 0, + 0, 0, 107, 109, 3, 12, 6, 0, 108, 110, 3, 36, 18, 0, 109, 108, 1, 0, 0, + 0, 109, 110, 1, 0, 0, 0, 110, 11, 1, 0, 0, 0, 111, 112, 3, 14, 7, 0, 112, + 122, 5, 25, 0, 0, 113, 118, 3, 46, 23, 0, 114, 115, 5, 29, 0, 0, 115, 117, + 3, 46, 23, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, + 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 123, 1, 0, 0, 0, 120, 118, 1, 0, 0, + 0, 121, 123, 5, 2, 0, 0, 122, 113, 1, 0, 0, 0, 122, 121, 1, 0, 0, 0, 122, + 123, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 125, 5, 26, 0, 0, 125, 13, + 1, 0, 0, 0, 126, 127, 5, 23, 0, 0, 127, 15, 1, 0, 0, 0, 128, 129, 5, 3, + 0, 0, 129, 130, 5, 25, 0, 0, 130, 131, 3, 18, 9, 0, 131, 132, 5, 26, 0, + 0, 132, 17, 1, 0, 0, 0, 133, 134, 3, 32, 16, 0, 134, 135, 3, 8, 4, 0, 135, + 136, 3, 32, 16, 0, 136, 139, 1, 0, 0, 0, 137, 139, 3, 32, 16, 0, 138, 133, + 1, 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 19, 1, 0, 0, 0, 140, 141, 5, 4, + 0, 0, 141, 21, 1, 0, 0, 0, 142, 148, 5, 5, 0, 0, 143, 145, 5, 25, 0, 0, + 144, 146, 3, 32, 16, 0, 145, 144, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, + 147, 1, 0, 0, 0, 147, 149, 5, 26, 0, 0, 148, 143, 1, 0, 0, 0, 148, 149, + 1, 0, 0, 0, 149, 151, 1, 0, 0, 0, 150, 152, 3, 36, 18, 0, 151, 150, 1, + 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 23, 1, 0, 0, 0, 153, 156, 3, 32, 16, + 0, 154, 156, 3, 12, 6, 0, 155, 153, 1, 0, 0, 0, 155, 154, 1, 0, 0, 0, 156, + 25, 1, 0, 0, 0, 157, 158, 5, 16, 0, 0, 158, 159, 5, 25, 0, 0, 159, 164, + 3, 24, 12, 0, 160, 161, 5, 29, 0, 0, 161, 163, 3, 24, 12, 0, 162, 160, + 1, 0, 0, 0, 163, 166, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, + 0, 0, 165, 167, 1, 0, 0, 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 26, 0, 0, + 168, 27, 1, 0, 0, 0, 169, 171, 3, 32, 16, 0, 170, 172, 7, 1, 0, 0, 171, + 170, 1, 0, 0, 0, 171, 172, 1, 0, 0, 0, 172, 29, 1, 0, 0, 0, 173, 174, 5, + 19, 0, 0, 174, 175, 5, 25, 0, 0, 175, 180, 3, 28, 14, 0, 176, 177, 5, 29, + 0, 0, 177, 179, 3, 28, 14, 0, 178, 176, 1, 0, 0, 0, 179, 182, 1, 0, 0, + 0, 180, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 183, 1, 0, 0, 0, 182, + 180, 1, 0, 0, 0, 183, 184, 5, 26, 0, 0, 184, 31, 1, 0, 0, 0, 185, 187, + 5, 40, 0, 0, 186, 188, 5, 40, 0, 0, 187, 186, 1, 0, 0, 0, 187, 188, 1, + 0, 0, 0, 188, 33, 1, 0, 0, 0, 189, 191, 3, 32, 16, 0, 190, 192, 3, 36, + 18, 0, 191, 190, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 35, 1, 0, 0, 0, + 193, 197, 5, 20, 0, 0, 194, 195, 5, 31, 0, 0, 195, 197, 7, 2, 0, 0, 196, + 193, 1, 0, 0, 0, 196, 194, 1, 0, 0, 0, 197, 37, 1, 0, 0, 0, 198, 199, 5, + 21, 0, 0, 199, 39, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 202, 5, 40, + 0, 0, 202, 41, 1, 0, 0, 0, 203, 204, 5, 41, 0, 0, 204, 43, 1, 0, 0, 0, + 205, 214, 5, 6, 0, 0, 206, 207, 5, 32, 0, 0, 207, 208, 5, 31, 0, 0, 208, + 215, 5, 32, 0, 0, 209, 210, 5, 32, 0, 0, 210, 215, 5, 31, 0, 0, 211, 212, + 5, 31, 0, 0, 212, 215, 5, 32, 0, 0, 213, 215, 5, 32, 0, 0, 214, 206, 1, + 0, 0, 0, 214, 209, 1, 0, 0, 0, 214, 211, 1, 0, 0, 0, 214, 213, 1, 0, 0, + 0, 214, 215, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 217, 5, 28, 0, 0, 217, + 45, 1, 0, 0, 0, 218, 219, 6, 23, -1, 0, 219, 227, 3, 32, 16, 0, 220, 227, + 3, 48, 24, 0, 221, 227, 3, 38, 19, 0, 222, 223, 3, 50, 25, 0, 223, 224, + 3, 46, 23, 9, 224, 227, 1, 0, 0, 0, 225, 227, 3, 12, 6, 0, 226, 218, 1, + 0, 0, 0, 226, 220, 1, 0, 0, 0, 226, 221, 1, 0, 0, 0, 226, 222, 1, 0, 0, + 0, 226, 225, 1, 0, 0, 0, 227, 255, 1, 0, 0, 0, 228, 229, 10, 8, 0, 0, 229, + 230, 5, 7, 0, 0, 230, 254, 3, 46, 23, 9, 231, 232, 10, 7, 0, 0, 232, 233, + 7, 3, 0, 0, 233, 254, 3, 46, 23, 8, 234, 235, 10, 6, 0, 0, 235, 236, 7, + 1, 0, 0, 236, 254, 3, 46, 23, 7, 237, 238, 10, 5, 0, 0, 238, 239, 7, 4, + 0, 0, 239, 254, 3, 46, 23, 6, 240, 241, 10, 4, 0, 0, 241, 242, 7, 5, 0, + 0, 242, 254, 3, 46, 23, 5, 243, 247, 10, 3, 0, 0, 244, 248, 5, 39, 0, 0, + 245, 248, 5, 38, 0, 0, 246, 248, 1, 0, 0, 0, 247, 244, 1, 0, 0, 0, 247, + 245, 1, 0, 0, 0, 247, 246, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 254, + 3, 46, 23, 4, 250, 251, 10, 2, 0, 0, 251, 252, 5, 13, 0, 0, 252, 254, 3, + 46, 23, 3, 253, 228, 1, 0, 0, 0, 253, 231, 1, 0, 0, 0, 253, 234, 1, 0, + 0, 0, 253, 237, 1, 0, 0, 0, 253, 240, 1, 0, 0, 0, 253, 243, 1, 0, 0, 0, + 253, 250, 1, 0, 0, 0, 254, 257, 1, 0, 0, 0, 255, 253, 1, 0, 0, 0, 255, + 256, 1, 0, 0, 0, 256, 47, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 258, 259, 7, + 6, 0, 0, 259, 49, 1, 0, 0, 0, 260, 261, 7, 7, 0, 0, 261, 51, 1, 0, 0, 0, + 26, 55, 62, 67, 73, 81, 89, 103, 109, 118, 122, 138, 145, 148, 151, 155, + 164, 171, 180, 187, 191, 196, 214, 226, 247, 253, 255, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) @@ -227,16 +230,16 @@ const ( SLQParserORDER_BY = 19 SLQParserALIAS_RESERVED = 20 SLQParserARG = 21 - SLQParserID = 22 - SLQParserWS = 23 - SLQParserLPAR = 24 - SLQParserRPAR = 25 - SLQParserLBRA = 26 - SLQParserRBRA = 27 - SLQParserCOMMA = 28 - SLQParserPIPE = 29 - SLQParserCOLON = 30 - SLQParserNULL = 31 + SLQParserNULL = 22 + SLQParserID = 23 + SLQParserWS = 24 + SLQParserLPAR = 25 + SLQParserRPAR = 26 + SLQParserLBRA = 27 + SLQParserRBRA = 28 + SLQParserCOMMA = 29 + SLQParserPIPE = 30 + SLQParserCOLON = 31 SLQParserNN = 32 SLQParserNUMBER = 33 SLQParserLT_EQ = 34 @@ -272,12 +275,13 @@ const ( SLQParserRULE_selector = 16 SLQParserRULE_selectorElement = 17 SLQParserRULE_alias = 18 - SLQParserRULE_handleTable = 19 - SLQParserRULE_handle = 20 - SLQParserRULE_rowRange = 21 - SLQParserRULE_expr = 22 - SLQParserRULE_literal = 23 - SLQParserRULE_unaryOperator = 24 + SLQParserRULE_arg = 19 + SLQParserRULE_handleTable = 20 + SLQParserRULE_handle = 21 + SLQParserRULE_rowRange = 22 + SLQParserRULE_expr = 23 + SLQParserRULE_literal = 24 + SLQParserRULE_unaryOperator = 25 ) // IStmtListContext is an interface to support dynamic dispatch. @@ -420,65 +424,65 @@ func (p *SLQParser) StmtList() (localctx IStmtListContext) { var _alt int p.EnterOuterAlt(localctx, 1) - p.SetState(53) + p.SetState(55) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserT__0 { { - p.SetState(50) + p.SetState(52) p.Match(SLQParserT__0) } - p.SetState(55) + p.SetState(57) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } { - p.SetState(56) + p.SetState(58) p.Query() } - p.SetState(65) + p.SetState(67) p.GetErrorHandler().Sync(p) _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 2, p.GetParserRuleContext()) for _alt != 2 && _alt != antlr.ATNInvalidAltNumber { if _alt == 1 { - p.SetState(58) + p.SetState(60) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for ok := true; ok; ok = _la == SLQParserT__0 { { - p.SetState(57) + p.SetState(59) p.Match(SLQParserT__0) } - p.SetState(60) + p.SetState(62) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } { - p.SetState(62) + p.SetState(64) p.Query() } } - p.SetState(67) + p.SetState(69) p.GetErrorHandler().Sync(p) _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 2, p.GetParserRuleContext()) } - p.SetState(71) + p.SetState(73) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserT__0 { { - p.SetState(68) + p.SetState(70) p.Match(SLQParserT__0) } - p.SetState(73) + p.SetState(75) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } @@ -635,24 +639,24 @@ func (p *SLQParser) Query() (localctx IQueryContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(74) + p.SetState(76) p.Segment() } - p.SetState(79) + p.SetState(81) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserPIPE { { - p.SetState(75) + p.SetState(77) p.Match(SLQParserPIPE) } { - p.SetState(76) + p.SetState(78) p.Segment() } - p.SetState(81) + p.SetState(83) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } @@ -809,25 +813,25 @@ func (p *SLQParser) Segment() (localctx ISegmentContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(82) + p.SetState(84) p.Element() } - p.SetState(87) + p.SetState(89) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserCOMMA { { - p.SetState(83) + p.SetState(85) p.Match(SLQParserCOMMA) } { - p.SetState(84) + p.SetState(86) p.Element() } - p.SetState(89) + p.SetState(91) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } @@ -1115,83 +1119,83 @@ func (p *SLQParser) Element() (localctx IElementContext) { } }() - p.SetState(101) + p.SetState(103) p.GetErrorHandler().Sync(p) switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 6, p.GetParserRuleContext()) { case 1: p.EnterOuterAlt(localctx, 1) { - p.SetState(90) + p.SetState(92) p.HandleTable() } case 2: p.EnterOuterAlt(localctx, 2) { - p.SetState(91) + p.SetState(93) p.Handle() } case 3: p.EnterOuterAlt(localctx, 3) { - p.SetState(92) + p.SetState(94) p.SelectorElement() } case 4: p.EnterOuterAlt(localctx, 4) { - p.SetState(93) + p.SetState(95) p.Join() } case 5: p.EnterOuterAlt(localctx, 5) { - p.SetState(94) + p.SetState(96) p.GroupBy() } case 6: p.EnterOuterAlt(localctx, 6) { - p.SetState(95) + p.SetState(97) p.OrderBy() } case 7: p.EnterOuterAlt(localctx, 7) { - p.SetState(96) + p.SetState(98) p.RowRange() } case 8: p.EnterOuterAlt(localctx, 8) { - p.SetState(97) + p.SetState(99) p.UniqueFunc() } case 9: p.EnterOuterAlt(localctx, 9) { - p.SetState(98) + p.SetState(100) p.CountFunc() } case 10: p.EnterOuterAlt(localctx, 10) { - p.SetState(99) + p.SetState(101) p.FuncElement() } case 11: p.EnterOuterAlt(localctx, 11) { - p.SetState(100) + p.SetState(102) p.expr(0) } @@ -1326,7 +1330,7 @@ func (p *SLQParser) Cmpr() (localctx ICmprContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(103) + p.SetState(105) _la = p.GetTokenStream().LA(1) if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&1082331758592) != 0) { @@ -1470,16 +1474,16 @@ func (p *SLQParser) FuncElement() (localctx IFuncElementContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(105) + p.SetState(107) p.Func_() } - p.SetState(107) + p.SetState(109) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserALIAS_RESERVED || _la == SLQParserCOLON { { - p.SetState(106) + p.SetState(108) p.Alias() } @@ -1664,44 +1668,44 @@ func (p *SLQParser) Func_() (localctx IFuncContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(109) + p.SetState(111) p.FuncName() } { - p.SetState(110) + p.SetState(112) p.Match(SLQParserLPAR) } - p.SetState(120) + p.SetState(122) p.GetErrorHandler().Sync(p) switch p.GetTokenStream().LA(1) { - case SLQParserT__13, SLQParserT__14, SLQParserORDER_ASC, SLQParserORDER_DESC, SLQParserID, SLQParserNULL, SLQParserNN, SLQParserNUMBER, SLQParserNAME, SLQParserSTRING: + case SLQParserT__13, SLQParserT__14, SLQParserORDER_ASC, SLQParserORDER_DESC, SLQParserARG, SLQParserNULL, SLQParserID, SLQParserNN, SLQParserNUMBER, SLQParserNAME, SLQParserSTRING: { - p.SetState(111) + p.SetState(113) p.expr(0) } - p.SetState(116) + p.SetState(118) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserCOMMA { { - p.SetState(112) + p.SetState(114) p.Match(SLQParserCOMMA) } { - p.SetState(113) + p.SetState(115) p.expr(0) } - p.SetState(118) + p.SetState(120) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } case SLQParserT__1: { - p.SetState(119) + p.SetState(121) p.Match(SLQParserT__1) } @@ -1710,7 +1714,7 @@ func (p *SLQParser) Func_() (localctx IFuncContext) { default: } { - p.SetState(122) + p.SetState(124) p.Match(SLQParserRPAR) } @@ -1817,7 +1821,7 @@ func (p *SLQParser) FuncName() (localctx IFuncNameContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(124) + p.SetState(126) p.Match(SLQParserID) } @@ -1946,20 +1950,20 @@ func (p *SLQParser) Join() (localctx IJoinContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(126) + p.SetState(128) p.Match(SLQParserT__2) } { - p.SetState(127) + p.SetState(129) p.Match(SLQParserLPAR) } { - p.SetState(128) + p.SetState(130) p.JoinConstraint() } { - p.SetState(129) + p.SetState(131) p.Match(SLQParserRPAR) } @@ -2119,28 +2123,28 @@ func (p *SLQParser) JoinConstraint() (localctx IJoinConstraintContext) { } }() - p.SetState(136) + p.SetState(138) p.GetErrorHandler().Sync(p) switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 10, p.GetParserRuleContext()) { case 1: p.EnterOuterAlt(localctx, 1) { - p.SetState(131) + p.SetState(133) p.Selector() } { - p.SetState(132) + p.SetState(134) p.Cmpr() } { - p.SetState(133) + p.SetState(135) p.Selector() } case 2: p.EnterOuterAlt(localctx, 2) { - p.SetState(135) + p.SetState(137) p.Selector() } @@ -2240,7 +2244,7 @@ func (p *SLQParser) UniqueFunc() (localctx IUniqueFuncContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(138) + p.SetState(140) p.Match(SLQParserT__3) } @@ -2387,42 +2391,42 @@ func (p *SLQParser) CountFunc() (localctx ICountFuncContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(140) + p.SetState(142) p.Match(SLQParserT__4) } - p.SetState(146) + p.SetState(148) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserLPAR { { - p.SetState(141) + p.SetState(143) p.Match(SLQParserLPAR) } - p.SetState(143) + p.SetState(145) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserNAME { { - p.SetState(142) + p.SetState(144) p.Selector() } } { - p.SetState(145) + p.SetState(147) p.Match(SLQParserRPAR) } } - p.SetState(149) + p.SetState(151) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserALIAS_RESERVED || _la == SLQParserCOLON { { - p.SetState(148) + p.SetState(150) p.Alias() } @@ -2558,21 +2562,21 @@ func (p *SLQParser) GroupByTerm() (localctx IGroupByTermContext) { } }() - p.SetState(153) + p.SetState(155) p.GetErrorHandler().Sync(p) switch p.GetTokenStream().LA(1) { case SLQParserNAME: p.EnterOuterAlt(localctx, 1) { - p.SetState(151) + p.SetState(153) p.Selector() } case SLQParserID: p.EnterOuterAlt(localctx, 2) { - p.SetState(152) + p.SetState(154) p.Func_() } @@ -2747,37 +2751,37 @@ func (p *SLQParser) GroupBy() (localctx IGroupByContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(155) + p.SetState(157) p.Match(SLQParserGROUP_BY) } { - p.SetState(156) + p.SetState(158) p.Match(SLQParserLPAR) } { - p.SetState(157) + p.SetState(159) p.GroupByTerm() } - p.SetState(162) + p.SetState(164) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserCOMMA { { - p.SetState(158) + p.SetState(160) p.Match(SLQParserCOMMA) } { - p.SetState(159) + p.SetState(161) p.GroupByTerm() } - p.SetState(164) + p.SetState(166) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } { - p.SetState(165) + p.SetState(167) p.Match(SLQParserRPAR) } @@ -2907,16 +2911,16 @@ func (p *SLQParser) OrderByTerm() (localctx IOrderByTermContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(167) + p.SetState(169) p.Selector() } - p.SetState(169) + p.SetState(171) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserORDER_ASC || _la == SLQParserORDER_DESC { { - p.SetState(168) + p.SetState(170) _la = p.GetTokenStream().LA(1) if !(_la == SLQParserORDER_ASC || _la == SLQParserORDER_DESC) { @@ -3096,37 +3100,37 @@ func (p *SLQParser) OrderBy() (localctx IOrderByContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(171) + p.SetState(173) p.Match(SLQParserORDER_BY) } { - p.SetState(172) + p.SetState(174) p.Match(SLQParserLPAR) } { - p.SetState(173) + p.SetState(175) p.OrderByTerm() } - p.SetState(178) + p.SetState(180) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == SLQParserCOMMA { { - p.SetState(174) + p.SetState(176) p.Match(SLQParserCOMMA) } { - p.SetState(175) + p.SetState(177) p.OrderByTerm() } - p.SetState(180) + p.SetState(182) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } { - p.SetState(181) + p.SetState(183) p.Match(SLQParserRPAR) } @@ -3238,15 +3242,15 @@ func (p *SLQParser) Selector() (localctx ISelectorContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(183) + p.SetState(185) p.Match(SLQParserNAME) } - p.SetState(185) + p.SetState(187) p.GetErrorHandler().Sync(p) if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 18, p.GetParserRuleContext()) == 1 { { - p.SetState(184) + p.SetState(186) p.Match(SLQParserNAME) } @@ -3385,17 +3389,17 @@ func (p *SLQParser) SelectorElement() (localctx ISelectorElementContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(187) + p.SetState(189) p.Selector() } - p.SetState(189) + p.SetState(191) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == SLQParserALIAS_RESERVED || _la == SLQParserCOLON { { - p.SetState(188) + p.SetState(190) p.Alias() } @@ -3518,25 +3522,25 @@ func (p *SLQParser) Alias() (localctx IAliasContext) { } }() - p.SetState(194) + p.SetState(196) p.GetErrorHandler().Sync(p) switch p.GetTokenStream().LA(1) { case SLQParserALIAS_RESERVED: p.EnterOuterAlt(localctx, 1) { - p.SetState(191) + p.SetState(193) p.Match(SLQParserALIAS_RESERVED) } case SLQParserCOLON: p.EnterOuterAlt(localctx, 2) { - p.SetState(192) + p.SetState(194) p.Match(SLQParserCOLON) } { - p.SetState(193) + p.SetState(195) _la = p.GetTokenStream().LA(1) if !(_la == SLQParserARG || _la == SLQParserID) { @@ -3554,6 +3558,113 @@ func (p *SLQParser) Alias() (localctx IAliasContext) { return localctx } +// IArgContext is an interface to support dynamic dispatch. +type IArgContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + ARG() antlr.TerminalNode + + // IsArgContext differentiates from other interfaces. + IsArgContext() +} + +type ArgContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyArgContext() *ArgContext { + var p = new(ArgContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = SLQParserRULE_arg + return p +} + +func (*ArgContext) IsArgContext() {} + +func NewArgContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ArgContext { + var p = new(ArgContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = SLQParserRULE_arg + + return p +} + +func (s *ArgContext) GetParser() antlr.Parser { return s.parser } + +func (s *ArgContext) ARG() antlr.TerminalNode { + return s.GetToken(SLQParserARG, 0) +} + +func (s *ArgContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ArgContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ArgContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(SLQListener); ok { + listenerT.EnterArg(s) + } +} + +func (s *ArgContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(SLQListener); ok { + listenerT.ExitArg(s) + } +} + +func (s *ArgContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case SLQVisitor: + return t.VisitArg(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *SLQParser) Arg() (localctx IArgContext) { + this := p + _ = this + + localctx = NewArgContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 38, SLQParserRULE_arg) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(198) + p.Match(SLQParserARG) + } + + return localctx +} + // IHandleTableContext is an interface to support dynamic dispatch. type IHandleTableContext interface { antlr.ParserRuleContext @@ -3639,7 +3750,7 @@ func (p *SLQParser) HandleTable() (localctx IHandleTableContext) { _ = this localctx = NewHandleTableContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 38, SLQParserRULE_handleTable) + p.EnterRule(localctx, 40, SLQParserRULE_handleTable) defer func() { p.ExitRule() @@ -3659,11 +3770,11 @@ func (p *SLQParser) HandleTable() (localctx IHandleTableContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(196) + p.SetState(200) p.Match(SLQParserHANDLE) } { - p.SetState(197) + p.SetState(201) p.Match(SLQParserNAME) } @@ -3750,7 +3861,7 @@ func (p *SLQParser) Handle() (localctx IHandleContext) { _ = this localctx = NewHandleContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 40, SLQParserRULE_handle) + p.EnterRule(localctx, 42, SLQParserRULE_handle) defer func() { p.ExitRule() @@ -3770,7 +3881,7 @@ func (p *SLQParser) Handle() (localctx IHandleContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(199) + p.SetState(203) p.Match(SLQParserHANDLE) } @@ -3872,7 +3983,7 @@ func (p *SLQParser) RowRange() (localctx IRowRangeContext) { _ = this localctx = NewRowRangeContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 42, SLQParserRULE_rowRange) + p.EnterRule(localctx, 44, SLQParserRULE_rowRange) defer func() { p.ExitRule() @@ -3892,37 +4003,17 @@ func (p *SLQParser) RowRange() (localctx IRowRangeContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(201) + p.SetState(205) p.Match(SLQParserT__5) } - p.SetState(210) + p.SetState(214) p.GetErrorHandler().Sync(p) if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 1 { - { - p.SetState(202) - p.Match(SLQParserNN) - } - { - p.SetState(203) - p.Match(SLQParserCOLON) - } - { - p.SetState(204) - p.Match(SLQParserNN) - } - - } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 2 { - { - p.SetState(205) - p.Match(SLQParserNN) - } { p.SetState(206) - p.Match(SLQParserCOLON) + p.Match(SLQParserNN) } - - } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 3 { { p.SetState(207) p.Match(SLQParserCOLON) @@ -3932,15 +4023,35 @@ func (p *SLQParser) RowRange() (localctx IRowRangeContext) { p.Match(SLQParserNN) } - } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 4 { + } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 2 { { p.SetState(209) p.Match(SLQParserNN) } + { + p.SetState(210) + p.Match(SLQParserCOLON) + } + + } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 3 { + { + p.SetState(211) + p.Match(SLQParserCOLON) + } + { + p.SetState(212) + p.Match(SLQParserNN) + } + + } else if p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 21, p.GetParserRuleContext()) == 4 { + { + p.SetState(213) + p.Match(SLQParserNN) + } } { - p.SetState(212) + p.SetState(216) p.Match(SLQParserRBRA) } @@ -3957,6 +4068,7 @@ type IExprContext interface { // Getter signatures Selector() ISelectorContext Literal() ILiteralContext + Arg() IArgContext UnaryOperator() IUnaryOperatorContext AllExpr() []IExprContext Expr(i int) IExprContext @@ -4033,6 +4145,22 @@ func (s *ExprContext) Literal() ILiteralContext { return t.(ILiteralContext) } +func (s *ExprContext) Arg() IArgContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IArgContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IArgContext) +} + func (s *ExprContext) UnaryOperator() IUnaryOperatorContext { var t antlr.RuleContext for _, ctx := range s.GetChildren() { @@ -4181,8 +4309,8 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { localctx = NewExprContext(p, p.GetParserRuleContext(), _parentState) var _prevctx IExprContext = localctx var _ antlr.ParserRuleContext = _prevctx // TODO: To prevent unused variable warning. - _startState := 44 - p.EnterRecursionRule(localctx, 44, SLQParserRULE_expr, _p) + _startState := 46 + p.EnterRecursionRule(localctx, 46, SLQParserRULE_expr, _p) var _la int defer func() { @@ -4204,35 +4332,41 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { var _alt int p.EnterOuterAlt(localctx, 1) - p.SetState(221) + p.SetState(226) p.GetErrorHandler().Sync(p) switch p.GetTokenStream().LA(1) { case SLQParserNAME: { - p.SetState(215) + p.SetState(219) p.Selector() } case SLQParserNULL, SLQParserNN, SLQParserNUMBER, SLQParserSTRING: { - p.SetState(216) + p.SetState(220) p.Literal() } + case SLQParserARG: + { + p.SetState(221) + p.Arg() + } + case SLQParserT__13, SLQParserT__14, SLQParserORDER_ASC, SLQParserORDER_DESC: { - p.SetState(217) + p.SetState(222) p.UnaryOperator() } { - p.SetState(218) + p.SetState(223) p.expr(9) } case SLQParserID: { - p.SetState(220) + p.SetState(225) p.Func_() } @@ -4240,7 +4374,7 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) } p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) - p.SetState(250) + p.SetState(255) p.GetErrorHandler().Sync(p) _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 25, p.GetParserRuleContext()) @@ -4250,36 +4384,36 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { p.TriggerExitRuleEvent() } _prevctx = localctx - p.SetState(248) + p.SetState(253) p.GetErrorHandler().Sync(p) switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 24, p.GetParserRuleContext()) { case 1: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(223) + p.SetState(228) if !(p.Precpred(p.GetParserRuleContext(), 8)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 8)", "")) } { - p.SetState(224) + p.SetState(229) p.Match(SLQParserT__6) } { - p.SetState(225) + p.SetState(230) p.expr(9) } case 2: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(226) + p.SetState(231) if !(p.Precpred(p.GetParserRuleContext(), 7)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 7)", "")) } { - p.SetState(227) + p.SetState(232) _la = p.GetTokenStream().LA(1) if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&772) != 0) { @@ -4290,20 +4424,20 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { } } { - p.SetState(228) + p.SetState(233) p.expr(8) } case 3: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(229) + p.SetState(234) if !(p.Precpred(p.GetParserRuleContext(), 6)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 6)", "")) } { - p.SetState(230) + p.SetState(235) _la = p.GetTokenStream().LA(1) if !(_la == SLQParserORDER_ASC || _la == SLQParserORDER_DESC) { @@ -4314,20 +4448,20 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { } } { - p.SetState(231) + p.SetState(236) p.expr(7) } case 4: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(232) + p.SetState(237) if !(p.Precpred(p.GetParserRuleContext(), 5)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 5)", "")) } { - p.SetState(233) + p.SetState(238) _la = p.GetTokenStream().LA(1) if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&7168) != 0) { @@ -4338,20 +4472,20 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { } } { - p.SetState(234) + p.SetState(239) p.expr(6) } case 5: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(235) + p.SetState(240) if !(p.Precpred(p.GetParserRuleContext(), 4)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 4)", "")) } { - p.SetState(236) + p.SetState(241) _la = p.GetTokenStream().LA(1) if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&257698037760) != 0) { @@ -4362,65 +4496,65 @@ func (p *SLQParser) expr(_p int) (localctx IExprContext) { } } { - p.SetState(237) + p.SetState(242) p.expr(5) } case 6: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(238) + p.SetState(243) if !(p.Precpred(p.GetParserRuleContext(), 3)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 3)", "")) } - p.SetState(242) + p.SetState(247) p.GetErrorHandler().Sync(p) switch p.GetTokenStream().LA(1) { case SLQParserEQ: { - p.SetState(239) + p.SetState(244) p.Match(SLQParserEQ) } case SLQParserNEQ: { - p.SetState(240) + p.SetState(245) p.Match(SLQParserNEQ) } - case SLQParserT__13, SLQParserT__14, SLQParserORDER_ASC, SLQParserORDER_DESC, SLQParserID, SLQParserNULL, SLQParserNN, SLQParserNUMBER, SLQParserNAME, SLQParserSTRING: + case SLQParserT__13, SLQParserT__14, SLQParserORDER_ASC, SLQParserORDER_DESC, SLQParserARG, SLQParserNULL, SLQParserID, SLQParserNN, SLQParserNUMBER, SLQParserNAME, SLQParserSTRING: default: panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) } { - p.SetState(244) + p.SetState(249) p.expr(4) } case 7: localctx = NewExprContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, SLQParserRULE_expr) - p.SetState(245) + p.SetState(250) if !(p.Precpred(p.GetParserRuleContext(), 2)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 2)", "")) } { - p.SetState(246) + p.SetState(251) p.Match(SLQParserT__12) } { - p.SetState(247) + p.SetState(252) p.expr(3) } } } - p.SetState(252) + p.SetState(257) p.GetErrorHandler().Sync(p) _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 25, p.GetParserRuleContext()) } @@ -4523,7 +4657,7 @@ func (p *SLQParser) Literal() (localctx ILiteralContext) { _ = this localctx = NewLiteralContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 46, SLQParserRULE_literal) + p.EnterRule(localctx, 48, SLQParserRULE_literal) var _la int defer func() { @@ -4544,10 +4678,10 @@ func (p *SLQParser) Literal() (localctx ILiteralContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(253) + p.SetState(258) _la = p.GetTokenStream().LA(1) - if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&4413078896640) != 0) { + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&4410935607296) != 0) { p.GetErrorHandler().RecoverInline(p) } else { p.GetErrorHandler().ReportMatch(p) @@ -4643,7 +4777,7 @@ func (p *SLQParser) UnaryOperator() (localctx IUnaryOperatorContext) { _ = this localctx = NewUnaryOperatorContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 48, SLQParserRULE_unaryOperator) + p.EnterRule(localctx, 50, SLQParserRULE_unaryOperator) var _la int defer func() { @@ -4664,7 +4798,7 @@ func (p *SLQParser) UnaryOperator() (localctx IUnaryOperatorContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(255) + p.SetState(260) _la = p.GetTokenStream().LA(1) if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&442368) != 0) { @@ -4680,7 +4814,7 @@ func (p *SLQParser) UnaryOperator() (localctx IUnaryOperatorContext) { func (p *SLQParser) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex int) bool { switch ruleIndex { - case 22: + case 23: var t *ExprContext = nil if localctx != nil { t = localctx.(*ExprContext) diff --git a/libsq/ast/internal/slq/slq_visitor.go b/libsq/ast/internal/slq/slq_visitor.go index 252e1302..3477a94a 100644 --- a/libsq/ast/internal/slq/slq_visitor.go +++ b/libsq/ast/internal/slq/slq_visitor.go @@ -64,6 +64,9 @@ type SLQVisitor interface { // Visit a parse tree produced by SLQParser#alias. VisitAlias(ctx *AliasContext) interface{} + // Visit a parse tree produced by SLQParser#arg. + VisitArg(ctx *ArgContext) interface{} + // Visit a parse tree produced by SLQParser#handleTable. VisitHandleTable(ctx *HandleTableContext) interface{} diff --git a/libsq/ast/literal.go b/libsq/ast/literal.go new file mode 100644 index 00000000..3668514d --- /dev/null +++ b/libsq/ast/literal.go @@ -0,0 +1,57 @@ +package ast + +import ( + "github.com/neilotoole/sq/libsq/ast/internal/slq" +) + +// LiteralType is an enum of literal types. +type LiteralType string + +const ( + LiteralNull LiteralType = "null" + LiteralNaturalNumber LiteralType = "int" + LiteralAnyNumber LiteralType = "float" + LiteralString LiteralType = "string" +) + +// LiteralNode is a leaf node representing a literal such as a number or a string. +type LiteralNode struct { + baseNode + typ LiteralType +} + +// String returns a log/debug-friendly representation. +func (n *LiteralNode) String() string { + return nodeString(n) +} + +// LiteralType returns the literal type (number, string, etc). +func (n *LiteralNode) LiteralType() LiteralType { + return n.typ +} + +// VisitLiteral implements slq.SLQVisitor. +func (v *parseTreeVisitor) VisitLiteral(ctx *slq.LiteralContext) any { + node := &LiteralNode{} + node.ctx = ctx + node.text = ctx.GetText() + + switch { + case ctx.NN() != nil: + node.typ = LiteralNaturalNumber + case ctx.NUMBER() != nil: + node.typ = LiteralAnyNumber + case ctx.NULL() != nil: + node.typ = LiteralNull + case ctx.STRING() != nil: + node.typ = LiteralString + default: + // Shouldn't happen + return errorf("unable to determine literal type for: %s", ctx.GetText()) + } + + if err := node.SetParent(v.cur); err != nil { + return err + } + return v.cur.AddChild(node) +} diff --git a/libsq/ast/node.go b/libsq/ast/node.go index 2f6d3a55..c9d2cf22 100644 --- a/libsq/ast/node.go +++ b/libsq/ast/node.go @@ -34,7 +34,8 @@ type Node interface { // String returns a debug-friendly string representation. String() string - // Text returns the node's text representation. + // Text returns the node's text value. This is convenience + // method for Node.Context().GetText(). Text() string } @@ -185,6 +186,74 @@ func nodesAreOnlyOfType(nodes []Node, types ...reflect.Type) error { return nil } +// NodeNextSibling returns the node's next sibling, or nil. +func NodeNextSibling(node Node) Node { + if node == nil { + return nil + } + + parent := node.Parent() + if parent == nil { + return nil + } + + i := nodeChildIndex(parent, node) + if i < 0 { + return nil + } + + children := parent.Children() + if i >= len(children)-1 { + return nil + } + + return children[i+1] +} + +// NodePrevSibling returns the node's previous sibling, or nil. +func NodePrevSibling(node Node) Node { + if node == nil { + return nil + } + + parent := node.Parent() + if parent == nil { + return nil + } + + i := nodeChildIndex(parent, node) + if i < 1 { + return nil + } + + children := parent.Children() + return children[i-1] +} + +// NodesHavingText returns any node whose node.Text() +// method returns text. +func NodesHavingText(tree Node, text string) []Node { + if tree == nil { + return nil + } + + var nodes []Node + + w := NewWalker(tree) + w.AddVisitor(typeNode, func(w *Walker, node Node) error { + nodeText := node.Text() + if nodeText == text { + nodes = append(nodes, node) + } + return nil + }) + + if err := w.Walk(); err != nil { + panic(err) + } + return nodes +} + // nodeChildIndex returns the index of child in parent's children, or -1. func nodeChildIndex(parent, child Node) int { for i, node := range parent.Children() { @@ -270,16 +339,6 @@ func (n *OperatorNode) String() string { return nodeString(n) } -// LiteralNode is a leaf node representing a literal such as a number or a string. -type LiteralNode struct { - baseNode -} - -// String returns a log/debug-friendly representation. -func (n *LiteralNode) String() string { - return nodeString(n) -} - // WhereNode represents a SQL WHERE clause, i.e. a filter on the SELECT. type WhereNode struct { baseNode @@ -327,17 +386,21 @@ func isOperator(text string) bool { // Cached results from reflect.TypeOf for node types. var ( typeAST = reflect.TypeOf((*AST)(nil)) - typeSegmentNode = reflect.TypeOf((*SegmentNode)(nil)) - typeHandleNode = reflect.TypeOf((*HandleNode)(nil)) - typeSelectorNode = reflect.TypeOf((*SelectorNode)(nil)) - typeTblSelectorNode = reflect.TypeOf((*TblSelectorNode)(nil)) - typeTblColSelectorNode = reflect.TypeOf((*TblColSelectorNode)(nil)) typeColSelectorNode = reflect.TypeOf((*ColSelectorNode)(nil)) - typeJoinNode = reflect.TypeOf((*JoinNode)(nil)) - typeRowRangeNode = reflect.TypeOf((*RowRangeNode)(nil)) - typeOrderByNode = reflect.TypeOf((*OrderByNode)(nil)) - typeGroupByNode = reflect.TypeOf((*GroupByNode)(nil)) typeExprNode = reflect.TypeOf((*ExprNode)(nil)) typeFuncNode = reflect.TypeOf((*FuncNode)(nil)) + typeGroupByNode = reflect.TypeOf((*GroupByNode)(nil)) + typeHandleNode = reflect.TypeOf((*HandleNode)(nil)) + typeJoinNode = reflect.TypeOf((*JoinNode)(nil)) + typeNode = reflect.TypeOf((*Node)(nil)).Elem() + _ = reflect.TypeOf((*OperatorNode)(nil)) + typeOrderByNode = reflect.TypeOf((*OrderByNode)(nil)) + typeRowRangeNode = reflect.TypeOf((*RowRangeNode)(nil)) + typeSegmentNode = reflect.TypeOf((*SegmentNode)(nil)) + _ = reflect.TypeOf((*Selector)(nil)).Elem() + typeSelectorNode = reflect.TypeOf((*SelectorNode)(nil)) + _ = reflect.TypeOf((*Tabler)(nil)).Elem() + typeTblColSelectorNode = reflect.TypeOf((*TblColSelectorNode)(nil)) + typeTblSelectorNode = reflect.TypeOf((*TblSelectorNode)(nil)) typeUniqueNode = reflect.TypeOf((*UniqueNode)(nil)) ) diff --git a/libsq/ast/node_test.go b/libsq/ast/node_test.go index 1634dc60..45ab8d2f 100644 --- a/libsq/ast/node_test.go +++ b/libsq/ast/node_test.go @@ -39,3 +39,22 @@ func TestAvg(t *testing.T) { ast := mustParse(t, input) require.NotNil(t, ast) } + +func TestNodePrevNextSibling(t *testing.T) { + const in = `@sakila | .actor | .actor_id == 2` + + log := slogt.New(t) + + a, err := Parse(log, in) + require.NoError(t, err) + + equalsNode := NodesHavingText(a, "==")[0] + + gotPrev := NodePrevSibling(equalsNode) + require.Equal(t, ".actor_id", gotPrev.Text()) + require.Nil(t, NodePrevSibling(gotPrev)) + + gotNext := NodeNextSibling(equalsNode) + require.Equal(t, "2", gotNext.Text()) + require.Nil(t, NodeNextSibling(gotNext)) +} diff --git a/libsq/ast/parser.go b/libsq/ast/parser.go index 4bd8edeb..268467d6 100644 --- a/libsq/ast/parser.go +++ b/libsq/ast/parser.go @@ -200,6 +200,8 @@ func (v *parseTreeVisitor) Visit(ctx antlr.ParseTree) any { return v.VisitUniqueFunc(ctx) case *slq.CountFuncContext: return v.VisitCountFunc(ctx) + case *slq.ArgContext: + return v.VisitArg(ctx) } // should never be reached @@ -400,17 +402,6 @@ func (v *parseTreeVisitor) VisitStmtList(_ *slq.StmtListContext) any { return nil // not using StmtList just yet } -// VisitLiteral implements slq.SLQVisitor. -func (v *parseTreeVisitor) VisitLiteral(ctx *slq.LiteralContext) any { - node := &LiteralNode{} - node.ctx = ctx - node.text = ctx.GetText() - if err := node.SetParent(v.cur); err != nil { - return err - } - return v.cur.AddChild(node) -} - // VisitUnaryOperator implements slq.SLQVisitor. func (v *parseTreeVisitor) VisitUnaryOperator(_ *slq.UnaryOperatorContext) any { return nil diff --git a/libsq/ast/parser_test.go b/libsq/ast/parser_test.go index faf6b156..9063ef71 100644 --- a/libsq/ast/parser_test.go +++ b/libsq/ast/parser_test.go @@ -115,7 +115,7 @@ func TestInspector_FindWhereClauses(t *testing.T) { nRoot, err := buildAST(log, ptree) require.Nil(t, err) - insp := NewInspector(log, nRoot) + insp := NewInspector(nRoot) whereNodes, err := insp.FindWhereClauses() require.NoError(t, err) require.Len(t, whereNodes, 1) diff --git a/libsq/ast/range_test.go b/libsq/ast/range_test.go index ac2e7204..b19ac3b6 100644 --- a/libsq/ast/range_test.go +++ b/libsq/ast/range_test.go @@ -3,8 +3,6 @@ package ast import ( "testing" - "github.com/neilotoole/slogt" - "github.com/stretchr/testify/assert" ) @@ -15,18 +13,16 @@ import ( // [:15] same as above (0 thru 15) // [10:] select all rows from 10 onwards -func TestRowRange1(t *testing.T) { - log := slogt.New(t) +// TODO: Move this to libsq/query_range_test.go +func TestRowRange1(t *testing.T) { ast := mustParse(t, fixtRowRange1) - assert.Equal(t, 0, NewInspector(log, ast).CountNodes(typeRowRangeNode)) + assert.Equal(t, 0, NewInspector(ast).CountNodes(typeRowRangeNode)) } func TestRowRange2(t *testing.T) { - log := slogt.New(t) - ast := mustParse(t, fixtRowRange2) - insp := NewInspector(log, ast) + insp := NewInspector(ast) assert.Equal(t, 1, insp.CountNodes(typeRowRangeNode)) nodes := insp.FindNodes(typeRowRangeNode) assert.Equal(t, 1, len(nodes)) @@ -36,38 +32,32 @@ func TestRowRange2(t *testing.T) { } func TestRowRange3(t *testing.T) { - log := slogt.New(t) - ast := mustParse(t, fixtRowRange3) - insp := NewInspector(log, ast) + insp := NewInspector(ast) rr, _ := insp.FindNodes(typeRowRangeNode)[0].(*RowRangeNode) assert.Equal(t, 1, rr.Offset) assert.Equal(t, 2, rr.Limit) } func TestRowRange4(t *testing.T) { - log := slogt.New(t) - ast := mustParse(t, fixtRowRange4) - insp := NewInspector(log, ast) + insp := NewInspector(ast) rr, _ := insp.FindNodes(typeRowRangeNode)[0].(*RowRangeNode) assert.Equal(t, 0, rr.Offset) assert.Equal(t, 3, rr.Limit) } func TestRowRange5(t *testing.T) { - log := slogt.New(t) ast := mustParse(t, fixtRowRange5) - insp := NewInspector(log, ast) + insp := NewInspector(ast) rr, _ := insp.FindNodes(typeRowRangeNode)[0].(*RowRangeNode) assert.Equal(t, 0, rr.Offset) assert.Equal(t, 3, rr.Limit) } func TestRowRange6(t *testing.T) { - log := slogt.New(t) ast := mustParse(t, fixtRowRange6) - insp := NewInspector(log, ast) + insp := NewInspector(ast) rr, _ := insp.FindNodes(typeRowRangeNode)[0].(*RowRangeNode) assert.Equal(t, 2, rr.Offset) assert.Equal(t, -1, rr.Limit) diff --git a/libsq/ast/render/distinct.go b/libsq/ast/render/distinct.go new file mode 100644 index 00000000..ac502e11 --- /dev/null +++ b/libsq/ast/render/distinct.go @@ -0,0 +1,10 @@ +package render + +import "github.com/neilotoole/sq/libsq/ast" + +func doDistinct(_ *Context, n *ast.UniqueNode) (string, error) { + if n == nil { + return "", nil + } + return "DISTINCT", nil +} diff --git a/libsq/ast/render/expr.go b/libsq/ast/render/expr.go new file mode 100644 index 00000000..f7970657 --- /dev/null +++ b/libsq/ast/render/expr.go @@ -0,0 +1,67 @@ +package render + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" + "github.com/neilotoole/sq/libsq/core/stringz" +) + +// Expr implements FragmentBuilder. +func doExpr(rc *Context, expr *ast.ExprNode) (string, error) { + if expr == nil { + return "", nil + } + r := rc.Renderer + + var sb strings.Builder + for i, child := range expr.Children() { + if i > 0 { + sb.WriteRune(sp) + } + + switch child := child.(type) { + case *ast.TblColSelectorNode, *ast.ColSelectorNode: + val, err := renderSelectorNode(rc.Dialect, child) + if err != nil { + return "", err + } + sb.WriteString(val) + case *ast.OperatorNode: + val, err := r.Operator(rc, child) + if err != nil { + return "", err + } + + sb.WriteString(val) + case *ast.ArgNode: + if rc.Args != nil { + val, ok := rc.Args[child.Key()] + if ok { + sb.WriteString(stringz.SingleQuote(val)) + break + } + } + + // It's an error if the arg is not supplied. + return "", errz.Errorf("no --arg value found for query variable %s", child.Text()) + case *ast.ExprNode: + val, err := r.Expr(rc, child) + if err != nil { + return "", err + } + sb.WriteString(val) + case *ast.LiteralNode: + val, err := r.Literal(rc, child) + if err != nil { + return "", err + } + sb.WriteString(val) + default: + sb.WriteString(child.Text()) + } + } + + return sb.String(), nil +} diff --git a/libsq/ast/render/fromtable.go b/libsq/ast/render/fromtable.go new file mode 100644 index 00000000..d8f93b57 --- /dev/null +++ b/libsq/ast/render/fromtable.go @@ -0,0 +1,16 @@ +package render + +import ( + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doFromTable(rc *Context, tblSel *ast.TblSelectorNode) (string, error) { + tblName, _ := tblSel.SelValue() + if tblName == "" { + return "", errz.Errorf("selector has empty table name: {%s}", tblSel.Text()) + } + + clause := "FROM " + rc.Dialect.Enquote(tblSel.TblName()) + return clause, nil +} diff --git a/libsq/ast/render/function.go b/libsq/ast/render/function.go new file mode 100644 index 00000000..68e6414c --- /dev/null +++ b/libsq/ast/render/function.go @@ -0,0 +1,77 @@ +package render + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/core/stringz" + + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doFunction(rc *Context, fn *ast.FuncNode) (string, error) { + sb := strings.Builder{} + fnName := strings.ToLower(fn.FuncName()) + children := fn.Children() + + if len(children) == 0 { + sb.WriteString(fnName) + sb.WriteRune('(') + + if fnName == "count" { + // Special handling for the count function, because COUNT() + // isn't valid, but COUNT(*) is. + sb.WriteRune('*') + } + + sb.WriteRune(')') + return sb.String(), nil + } + + // Special handling for "count_unique(.col)" function. We translate + // it to "SELECT count(DISTINCT col)". + if fnName == "count_unique" { + sb.WriteString("count(DISTINCT ") + } else { + sb.WriteString(fnName) + sb.WriteRune('(') + } + + for i, child := range children { + if i > 0 { + sb.WriteString(", ") + } + + switch node := child.(type) { + case *ast.ColSelectorNode, *ast.TblColSelectorNode, *ast.TblSelectorNode: + s, err := renderSelectorNode(rc.Dialect, node) + if err != nil { + return "", err + } + sb.WriteString(s) + case *ast.OperatorNode: + sb.WriteString(node.Text()) + case *ast.LiteralNode: + // TODO: This is all a bit of a mess. We probably need to + // move to using bound parameters instead of inlining + // literal values. + val, wasQuoted, err := unquoteLiteral(node.Text()) + if err != nil { + return "", err + } + + if wasQuoted { + // The literal had quotes, so it's a regular string. + sb.WriteString(stringz.SingleQuote(val)) + } else { + sb.WriteString(val) + } + default: + return "", errz.Errorf("unknown AST child node %T: %s", node, node) + } + } + + sb.WriteRune(')') + sql := sb.String() + return sql, nil +} diff --git a/libsq/ast/render/groupby.go b/libsq/ast/render/groupby.go new file mode 100644 index 00000000..bdc742cd --- /dev/null +++ b/libsq/ast/render/groupby.go @@ -0,0 +1,45 @@ +package render + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doGroupBy(rc *Context, gb *ast.GroupByNode) (string, error) { + if gb == nil { + return "", nil + } + + var ( + term string + err error + sb strings.Builder + ) + + sb.WriteString("GROUP BY ") + for i, child := range gb.Children() { + if i > 0 { + sb.WriteString(", ") + } + + switch child := child.(type) { + case *ast.FuncNode: + if term, err = rc.Renderer.Function(rc, child); err != nil { + return "", err + } + case ast.Selector: + if term, err = renderSelectorNode(rc.Dialect, child); err != nil { + return "", err + } + default: + // Should never happen + return "", errz.Errorf("invalid child type: %T: %s", child, child) + } + + sb.WriteString(term) + } + + return sb.String(), nil +} diff --git a/libsq/ast/render/internal_test.go b/libsq/ast/render/internal_test.go new file mode 100644 index 00000000..da4cad77 --- /dev/null +++ b/libsq/ast/render/internal_test.go @@ -0,0 +1 @@ +package render diff --git a/libsq/ast/render/join.go b/libsq/ast/render/join.go new file mode 100644 index 00000000..94592074 --- /dev/null +++ b/libsq/ast/render/join.go @@ -0,0 +1,86 @@ +package render + +import ( + "fmt" + + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doJoin(rc *Context, fnJoin *ast.JoinNode) (string, error) { + enquote := rc.Dialect.Enquote + + joinType := "INNER JOIN" + onClause := "" + + if len(fnJoin.Children()) == 0 { + joinType = "NATURAL JOIN" + } else { + joinExpr, ok := fnJoin.Children()[0].(*ast.JoinConstraint) + if !ok { + return "", errz.Errorf("expected *FnJoinExpr but got %T", fnJoin.Children()[0]) + } + + leftOperand := "" + operator := "" + rightOperand := "" + + if len(joinExpr.Children()) == 1 { + // It's a single col selector + colSel, ok := joinExpr.Children()[0].(*ast.ColSelectorNode) + if !ok { + return "", errz.Errorf("expected *ColSelectorNode but got %T", joinExpr.Children()[0]) + } + + colVal, err := colSel.SelValue() + if err != nil { + return "", err + } + + leftTblVal := fnJoin.LeftTbl().TblName() + leftOperand = fmt.Sprintf( + "%s.%s", + enquote(leftTblVal), + enquote(colVal), + ) + + operator = "==" + + rightTblVal := fnJoin.RightTbl().TblName() + rightOperand = fmt.Sprintf( + "%s.%s", + enquote(rightTblVal), + enquote(colVal), + ) + } else { + var err error + leftOperand, err = renderSelectorNode(rc.Dialect, joinExpr.Children()[0]) + if err != nil { + return "", err + } + + operator = joinExpr.Children()[1].Text() + + rightOperand, err = renderSelectorNode(rc.Dialect, joinExpr.Children()[2]) + if err != nil { + return "", err + } + } + + if operator == "==" { + operator = "=" + } + + onClause = fmt.Sprintf("ON %s %s %s", leftOperand, operator, rightOperand) + } + + sql := fmt.Sprintf( + "FROM %s %s %s", + enquote(fnJoin.LeftTbl().TblName()), + joinType, + enquote(fnJoin.RightTbl().TblName()), + ) + sql = sqlAppend(sql, onClause) + + return sql, nil +} diff --git a/libsq/ast/render/literal.go b/libsq/ast/render/literal.go new file mode 100644 index 00000000..d2a9209b --- /dev/null +++ b/libsq/ast/render/literal.go @@ -0,0 +1,25 @@ +package render + +import ( + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/stringz" +) + +// Literal implement FragmentBuilder. +func doLiteral(_ *Context, lit *ast.LiteralNode) (string, error) { + switch lit.LiteralType() { + case ast.LiteralNull: + return "NULL", nil + case ast.LiteralNaturalNumber, ast.LiteralAnyNumber: + return lit.Text(), nil + case ast.LiteralString: + text, _, err := unquoteLiteral(lit.Text()) + if err != nil { + return "", err + } + return stringz.SingleQuote(text), nil + default: + // Should never happen. + panic("unknown literal type: " + string(lit.LiteralType())) + } +} diff --git a/libsq/ast/render/operator.go b/libsq/ast/render/operator.go new file mode 100644 index 00000000..f0efd482 --- /dev/null +++ b/libsq/ast/render/operator.go @@ -0,0 +1,31 @@ +package render + +import ( + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doOperator(rc *Context, op *ast.OperatorNode) (string, error) { + if op == nil { + return "", nil + } + + val, ok := rc.Dialect.Ops[op.Text()] + if !ok { + return "", errz.Errorf("invalid operator: %s", op.Text()) + } + + rhs := ast.NodeNextSibling(op) + if lit, ok := rhs.(*ast.LiteralNode); ok && lit.Text() == "null" { + switch op.Text() { + case "==": + val = "IS" + case "!=": + val = "IS NOT" + default: + return "", errz.Errorf("invalid operator for null") + } + } + + return val, nil +} diff --git a/libsq/ast/render/orderby.go b/libsq/ast/render/orderby.go new file mode 100644 index 00000000..fa2885e8 --- /dev/null +++ b/libsq/ast/render/orderby.go @@ -0,0 +1,40 @@ +package render + +import ( + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +func doOrderBy(rc *Context, ob *ast.OrderByNode) (string, error) { + if ob == nil { + return "", nil + } + + terms := ob.Terms() + if len(terms) == 0 { + return "", errz.Errorf("%T has no ordering terms: %s", ob, ob) + } + + clause := "ORDER BY " + for i := 0; i < len(terms); i++ { + if i > 0 { + clause += ", " + } + + sel, err := renderSelectorNode(rc.Dialect, terms[i].Selector()) + if err != nil { + return "", err + } + + clause += sel + switch terms[i].Direction() { //nolint:exhaustive + case ast.OrderByDirectionAsc: + clause += " ASC" + case ast.OrderByDirectionDesc: + clause += " DESC" + default: + } + } + + return clause, nil +} diff --git a/libsq/ast/render/range.go b/libsq/ast/render/range.go new file mode 100644 index 00000000..cc76cff2 --- /dev/null +++ b/libsq/ast/render/range.go @@ -0,0 +1,37 @@ +package render + +import ( + "fmt" + "math" + + "github.com/neilotoole/sq/libsq/ast" +) + +func doRange(_ *Context, rr *ast.RowRangeNode) (string, error) { + if rr == nil { + return "", nil + } + + if rr.Limit < 0 && rr.Offset < 0 { + return "", nil + } + + limit := "" + offset := "" + if rr.Limit > -1 { + limit = fmt.Sprintf(" LIMIT %d", rr.Limit) + } + if rr.Offset > -1 { + offset = fmt.Sprintf(" OFFSET %d", rr.Offset) + + if rr.Limit == -1 { + // MySQL requires a LIMIT if OFFSET is used. Therefore + // we make the LIMIT a very large number + limit = fmt.Sprintf(" LIMIT %d", math.MaxInt64) + } + } + + sql := limit + offset + + return sql, nil +} diff --git a/libsq/ast/render/render.go b/libsq/ast/render/render.go new file mode 100644 index 00000000..95117f14 --- /dev/null +++ b/libsq/ast/render/render.go @@ -0,0 +1,210 @@ +// Package render provides the mechanism for rendering ast into SQL. +package render + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/driver/dialect" + + "github.com/neilotoole/sq/libsq/core/errz" + + "github.com/neilotoole/sq/libsq/ast" +) + +// Context contains context for rendering a query. +type Context struct { + // Renderer holds the rendering functions. + Renderer *Renderer + + // Dialect is the driver dialect. + Dialect dialect.Dialect + + // The args map contains predefined variables that are + // substituted into the query. It may be empty or nil. + Args map[string]string +} + +// Renderer is a set of functions for rendering ast elements into SQL. +// Use NewDefaultRenderer to get a new instance. Each function can be +// swapped with a custom implementation for a SQL dialect. +type Renderer struct { + // FromTable renders a FROM table fragment. + FromTable func(rc *Context, tblSel *ast.TblSelectorNode) (string, error) + + // SelectCols renders a column names/expression fragment. + // It shouldn't render the actual SELECT keyword. Example return value: + // + // "first_name" AS "given_name", "last name" AS "family_name" + SelectCols func(rc *Context, cols []ast.ResultColumn) (string, error) + + // Range renders a row range fragment. + Range func(rc *Context, rr *ast.RowRangeNode) (string, error) + + // OrderBy renders the ORDER BY fragment. + OrderBy func(rc *Context, ob *ast.OrderByNode) (string, error) + + // GroupBy renders the GROUP BY fragment. + GroupBy func(rc *Context, gb *ast.GroupByNode) (string, error) + + // Join renders a join fragment. + Join func(rc *Context, fnJoin *ast.JoinNode) (string, error) + + // Function renders a function fragment. + Function func(rc *Context, fn *ast.FuncNode) (string, error) + + // Literal renders a literal fragment. + Literal func(rc *Context, lit *ast.LiteralNode) (string, error) + + // Where renders a WHERE fragment. + Where func(rc *Context, where *ast.WhereNode) (string, error) + + // Expr renders an expression fragment. + Expr func(rc *Context, expr *ast.ExprNode) (string, error) + + // Operator renders an operator fragment. + Operator func(rc *Context, op *ast.OperatorNode) (string, error) + + // Distinct renders the DISTINCT fragment. Returns an + // empty string if n is nil. + Distinct func(rc *Context, n *ast.UniqueNode) (string, error) + + // PreRender is a hook that is called before Render. It is a final + // opportunity to customize f before rendering. It is nil by default. + PreRender func(rc *Context, f *Fragments) error + + // Render renders f into a SQL query. + Render func(rc *Context, f *Fragments) (string, error) +} + +// NewDefaultRenderer returns a Renderer that works for most SQL dialects. +// Driver implementations can override specific rendering functions +// as needed. +func NewDefaultRenderer() *Renderer { + return &Renderer{ + FromTable: doFromTable, + SelectCols: doSelectCols, + Range: doRange, + OrderBy: doOrderBy, + GroupBy: doGroupBy, + Join: doJoin, + Function: doFunction, + Literal: doLiteral, + Where: doWhere, + Expr: doExpr, + Operator: doOperator, + Distinct: doDistinct, + Render: doRender, + } +} + +// Fragments holds the fragments of a SQL query. +// It is passed to Renderer.PreRender and Renderer.Render. +type Fragments struct { + Distinct string + Columns string + From string + Where string + GroupBy string + OrderBy string + Range string +} + +// Render implements QueryBuilder. +func doRender(_ *Context, f *Fragments) (string, error) { + sb := strings.Builder{} + + sb.WriteString("SELECT") + + if f.Distinct != "" { + sb.WriteRune(sp) + sb.WriteString(f.Distinct) + } + + sb.WriteRune(sp) + sb.WriteString(f.Columns) + sb.WriteRune(sp) + sb.WriteString(f.From) + + if f.Where != "" { + sb.WriteRune(sp) + sb.WriteString(f.Where) + } + + if f.OrderBy != "" { + sb.WriteRune(sp) + sb.WriteString(f.OrderBy) + } + + if f.GroupBy != "" { + sb.WriteRune(sp) + sb.WriteString(f.GroupBy) + } + + if f.Range != "" { + sb.WriteRune(sp) + sb.WriteString(f.Range) + } + + return sb.String(), nil +} + +const ( + singleQuote = '\'' + sp = ' ' +) + +// renderSelectorNode renders a selector such as ".actor.first_name" +// or ".last_name". +func renderSelectorNode(d dialect.Dialect, node ast.Node) (string, error) { + // FIXME: switch to using enquote + switch node := node.(type) { + case *ast.ColSelectorNode: + return d.Enquote(node.ColName()), nil + case *ast.TblColSelectorNode: + return d.Enquote(node.TblName()) + "." + d.Enquote(node.ColName()), nil + case *ast.TblSelectorNode: + return d.Enquote(node.TblName()), nil + default: + return "", errz.Errorf( + "expected selector node type, but got %T: %s", + node, + node.Text(), + ) + } +} + +// sqlAppend is a convenience function for building the SQL string. +// The main purpose is to ensure that there's always a consistent amount +// of whitespace. Thus, if existing has a space suffix and add has a +// space prefix, the returned string will only have one space. If add +// is the empty string or just whitespace, this function simply +// returns existing. +func sqlAppend(existing, add string) string { + add = strings.TrimSpace(add) + if add == "" { + return existing + } + + existing = strings.TrimSpace(existing) + return existing + " " + add +} + +// unquoteLiteral returns true if s is a double-quoted string, and also returns +// the value with the quotes stripped. An error is returned if the string +// is malformed. +func unquoteLiteral(s string) (val string, ok bool, err error) { + hasPrefix := strings.HasPrefix(s, `"`) + hasSuffix := strings.HasSuffix(s, `"`) + + if hasPrefix && hasSuffix { + val = strings.TrimPrefix(s, `"`) + val = strings.TrimSuffix(val, `"`) + return val, true, nil + } + + if hasPrefix != hasSuffix { + return "", false, errz.Errorf("malformed literal: %s", s) + } + + return s, false, nil +} diff --git a/libsq/ast/render/selectcols.go b/libsq/ast/render/selectcols.go new file mode 100644 index 00000000..dfd765f8 --- /dev/null +++ b/libsq/ast/render/selectcols.go @@ -0,0 +1,50 @@ +package render + +import ( + "strings" + + "github.com/neilotoole/sq/libsq/ast" +) + +func doSelectCols(rc *Context, cols []ast.ResultColumn) (string, error) { + var err error + + if len(cols) == 0 { + return "*", nil + } + + vals := make([]string, len(cols)) + for i, col := range cols { + // aliasFrag holds the "AS alias" fragment (if applicable). + // For example: "@sakila | .actor | .first_name:given_name" becomes + // "SELECT first_name AS given_name FROM actor". + var aliasFrag string + if col.Alias() != "" { + aliasFrag = " AS " + rc.Dialect.Enquote(col.Alias()) + } + + switch col := col.(type) { + case *ast.ColSelectorNode: + if vals[i], err = renderSelectorNode(rc.Dialect, col); err != nil { + return "", err + } + case *ast.TblColSelectorNode: + if vals[i], err = renderSelectorNode(rc.Dialect, col); err != nil { + return "", err + } + case *ast.FuncNode: + if vals[i], err = rc.Renderer.Function(rc, col); err != nil { + return "", err + } + default: + // FIXME: We should be exhaustively checking the cases. + // Here, it's probably an ExprNode? + vals[i] = col.Text() // for now, we just return the raw text + } + + vals[i] += aliasFrag + } + + text := strings.Join(vals, ", ") + return text, nil +} diff --git a/libsq/ast/render/where.go b/libsq/ast/render/where.go new file mode 100644 index 00000000..3cd90d1f --- /dev/null +++ b/libsq/ast/render/where.go @@ -0,0 +1,16 @@ +package render + +import "github.com/neilotoole/sq/libsq/ast" + +func doWhere(rc *Context, where *ast.WhereNode) (string, error) { + if where == nil { + return "", nil + } + sql, err := rc.Renderer.Expr(rc, where.Expr()) + if err != nil { + return "", err + } + + sql = "WHERE " + sql + return sql, nil +} diff --git a/libsq/ast/selector_test.go b/libsq/ast/selector_test.go index 9ed0ad6c..9fadb2a0 100644 --- a/libsq/ast/selector_test.go +++ b/libsq/ast/selector_test.go @@ -41,7 +41,7 @@ func TestColumnAlias(t *testing.T) { require.NoError(t, err) - insp := NewInspector(log, ast) + insp := NewInspector(ast) nodes := insp.FindNodes(typeColSelectorNode) require.Equal(t, 1, len(nodes)) colSel, ok := nodes[0].(*ColSelectorNode) diff --git a/libsq/ast/sqlbuilder/basebuilder.go b/libsq/ast/sqlbuilder/basebuilder.go deleted file mode 100644 index 753a04bb..00000000 --- a/libsq/ast/sqlbuilder/basebuilder.go +++ /dev/null @@ -1,637 +0,0 @@ -package sqlbuilder - -import ( - "fmt" - "math" - "strings" - - "golang.org/x/exp/slog" - - "github.com/neilotoole/sq/libsq/ast" - "github.com/neilotoole/sq/libsq/core/errz" -) - -const ( - singleQuote = '\'' - sp = ' ' -) - -// baseOps is a map of SLQ operator (e.g. "==" or "!=") to its default SQL rendering. -var baseOps = map[string]string{ - `==`: `=`, -} - -// BaseOps returns a default map of SLQ operator (e.g. "==" or "!=") to its default SQL rendering. -// The returned map is a copy and can be safely modified by the caller. -func BaseOps() map[string]string { - ops := make(map[string]string, len(baseOps)) - for k, v := range baseOps { - ops[k] = v - } - return ops -} - -var _ FragmentBuilder = (*BaseFragmentBuilder)(nil) - -// BaseFragmentBuilder is a default implementation of sqlbuilder.FragmentBuilder. -type BaseFragmentBuilder struct { - Log *slog.Logger - // Quote is the driver-specific quote rune, e.g. " or ` - Quote string - - // QuoteFn quotes an identifier. - QuoteFn func(string) string - Ops map[string]string -} - -// Distinct implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Distinct(n *ast.UniqueNode) (string, error) { - if n == nil { - return "", nil - } - return "DISTINCT", nil -} - -// GroupBy implements FragmentBuilder. -func (fb *BaseFragmentBuilder) GroupBy(gb *ast.GroupByNode) (string, error) { - if gb == nil { - return "", nil - } - - var ( - term string - err error - sb strings.Builder - ) - - sb.WriteString("GROUP BY ") - for i, child := range gb.Children() { - if i > 0 { - sb.WriteString(", ") - } - - switch child := child.(type) { - case *ast.FuncNode: - if term, err = fb.Function(child); err != nil { - return "", err - } - case ast.Selector: - if term, err = renderSelectorNode(fb.Quote, child); err != nil { - return "", err - } - default: - // Should never happen - return "", errz.Errorf("invalid child type: %T: %s", child, child) - } - - sb.WriteString(term) - } - - return sb.String(), nil -} - -// OrderBy implements FragmentBuilder. -func (fb *BaseFragmentBuilder) OrderBy(ob *ast.OrderByNode) (string, error) { - if ob == nil { - return "", nil - } - - terms := ob.Terms() - if len(terms) == 0 { - return "", errz.Errorf("%T has no ordering terms: %s", ob, ob) - } - - clause := "ORDER BY " - for i := 0; i < len(terms); i++ { - if i > 0 { - clause += ", " - } - - sel, err := renderSelectorNode(fb.Quote, terms[i].Selector()) - if err != nil { - return "", err - } - - clause += sel - switch terms[i].Direction() { //nolint:exhaustive - case ast.OrderByDirectionAsc: - clause += " ASC" - case ast.OrderByDirectionDesc: - clause += " DESC" - default: - } - } - - return clause, nil -} - -// Operator implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Operator(op *ast.OperatorNode) (string, error) { - if op == nil { - return "", nil - } - - if val, ok := fb.Ops[op.Text()]; ok { - return val, nil - } - - return op.Text(), nil -} - -// Where implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Where(where *ast.WhereNode) (string, error) { - if where == nil { - return "", nil - } - sql, err := fb.Expr(where.Expr()) - if err != nil { - return "", err - } - - sql = "WHERE " + sql - return sql, nil -} - -// Expr implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Expr(expr *ast.ExprNode) (string, error) { - if expr == nil { - return "", nil - } - var sb strings.Builder - - for _, child := range expr.Children() { - switch child := child.(type) { - case *ast.TblColSelectorNode, *ast.ColSelectorNode: - val, err := renderSelectorNode(fb.Quote, child) - if err != nil { - return "", err - } - sb.WriteString(val) - case *ast.OperatorNode: - val, err := fb.Operator(child) - if err != nil { - return "", err - } - - sb.WriteRune(sp) - sb.WriteString(val) - case *ast.ExprNode: - val, err := fb.Expr(child) - if err != nil { - return "", err - } - sb.WriteRune(sp) - sb.WriteString(val) - default: - sb.WriteRune(sp) - sb.WriteString(child.Text()) - } - } - - return sb.String(), nil -} - -// Function implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Function(fn *ast.FuncNode) (string, error) { - sb := strings.Builder{} - fnName := strings.ToLower(fn.FuncName()) - children := fn.Children() - - if len(children) == 0 { - sb.WriteString(fnName) - sb.WriteRune('(') - - if fnName == "count" { - // Special handling for the count function, because COUNT() - // isn't valid, but COUNT(*) is. - sb.WriteRune('*') - } - - sb.WriteRune(')') - return sb.String(), nil - } - - // Special handling for "count_unique(.col)" function. We translate - // it to "SELECT count(DISTINCT col)". - if fnName == "count_unique" { - sb.WriteString("count(DISTINCT ") - } else { - sb.WriteString(fnName) - sb.WriteRune('(') - } - - for i, child := range children { - if i > 0 { - sb.WriteString(", ") - } - - switch node := child.(type) { - case *ast.ColSelectorNode, *ast.TblColSelectorNode, *ast.TblSelectorNode: - s, err := renderSelectorNode(fb.Quote, node) - if err != nil { - return "", err - } - sb.WriteString(s) - case *ast.OperatorNode: - sb.WriteString(node.Text()) - case *ast.LiteralNode: - // TODO: This is all a bit of a mess. We probably need to - // move to using bound parameters instead of inlining - // literal values. - val, wasQuoted, err := unquoteLiteral(node.Text()) - if err != nil { - return "", err - } - - if wasQuoted { - // The literal had quotes, so it's a regular string. - // FIXME: replace with stringz.SingleQuote - sb.WriteRune(singleQuote) - sb.WriteString(escapeLiteral(val)) - sb.WriteRune(singleQuote) - } else { - sb.WriteString(val) - } - default: - return "", errz.Errorf("unknown AST child node %T: %s", node, node) - } - } - - sb.WriteRune(')') - sql := sb.String() - return sql, nil -} - -// FromTable implements FragmentBuilder. -func (fb *BaseFragmentBuilder) FromTable(tblSel *ast.TblSelectorNode) (string, error) { - tblName, _ := tblSel.SelValue() - if tblName == "" { - return "", errz.Errorf("selector has empty table name: {%s}", tblSel.Text()) - } - - clause := fmt.Sprintf("FROM %v%s%v", fb.Quote, tblSel.TblName(), fb.Quote) - return clause, nil -} - -// Join implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Join(fnJoin *ast.JoinNode) (string, error) { - joinType := "INNER JOIN" - onClause := "" - - if len(fnJoin.Children()) == 0 { - joinType = "NATURAL JOIN" - } else { - joinExpr, ok := fnJoin.Children()[0].(*ast.JoinConstraint) - if !ok { - return "", errz.Errorf("expected *FnJoinExpr but got %T", fnJoin.Children()[0]) - } - - leftOperand := "" - operator := "" - rightOperand := "" - - if len(joinExpr.Children()) == 1 { - // It's a single col selector - colSel, ok := joinExpr.Children()[0].(*ast.ColSelectorNode) - if !ok { - return "", errz.Errorf("expected *ColSelectorNode but got %T", joinExpr.Children()[0]) - } - - colVal, err := colSel.SelValue() - if err != nil { - return "", err - } - - leftTblVal := fnJoin.LeftTbl().TblName() - leftOperand = fmt.Sprintf( - "%s%s%s.%s%s%s", - fb.Quote, - leftTblVal, - fb.Quote, - fb.Quote, - colVal, - fb.Quote, - ) - - operator = "==" - - rightTblVal := fnJoin.RightTbl().TblName() - rightOperand = fmt.Sprintf( - "%s%s%s.%s%s%s", - fb.Quote, - rightTblVal, - fb.Quote, - fb.Quote, - colVal, - fb.Quote, - ) - } else { - var err error - leftOperand, err = renderSelectorNode(fb.Quote, joinExpr.Children()[0]) - if err != nil { - return "", err - } - - operator = joinExpr.Children()[1].Text() - - rightOperand, err = renderSelectorNode(fb.Quote, joinExpr.Children()[2]) - if err != nil { - return "", err - } - } - - if operator == "==" { - operator = "=" - } - - onClause = fmt.Sprintf("ON %s %s %s", leftOperand, operator, rightOperand) - } - - sql := fmt.Sprintf( - "FROM %s%s%s %s %s%s%s", - fb.Quote, - fnJoin.LeftTbl().TblName(), - fb.Quote, - joinType, - fb.Quote, - fnJoin.RightTbl().TblName(), - fb.Quote, - ) - sql = sqlAppend(sql, onClause) - - return sql, nil -} - -// renderSelectorNode renders a selector such as ".actor.first_name" -// or ".last_name". -func renderSelectorNode(quote string, node ast.Node) (string, error) { - switch node := node.(type) { - case *ast.ColSelectorNode: - return fmt.Sprintf( - "%s%s%s", - quote, - node.ColName(), - quote, - ), nil - case *ast.TblColSelectorNode: - return fmt.Sprintf( - "%s%s%s.%s%s%s", - quote, - node.TblName(), - quote, - quote, - node.ColName(), - quote, - ), nil - case *ast.TblSelectorNode: - return fmt.Sprintf( - "%s%s%s", - quote, - node.TblName(), - quote, - ), nil - - default: - return "", errz.Errorf( - "expected selector node type, but got %T: %s", - node, - node.Text(), - ) - } -} - -// sqlAppend is a convenience function for building the SQL string. -// The main purpose is to ensure that there's always a consistent amount -// of whitespace. Thus, if existing has a space suffix and add has a -// space prefix, the returned string will only have one space. If add -// is the empty string or just whitespace, this function simply -// returns existing. -func sqlAppend(existing, add string) string { - add = strings.TrimSpace(add) - if add == "" { - return existing - } - - existing = strings.TrimSpace(existing) - return existing + " " + add -} - -// quoteTableOrColSelector returns a quote table, col, or table/col -// selector for use in a SQL statement. For example: -// -// .table --> "table" -// .col --> "col" -// .table.col --> "table"."col" -// -// Thus, the selector must have exactly one or two periods. -func quoteTableOrColSelector(quote, selector string) (string, error) { - if len(selector) < 2 || selector[0] != '.' { - return "", errz.Errorf("invalid selector: %s", selector) - } - - parts := strings.Split(selector[1:], ".") - switch len(parts) { - case 1: - return quote + parts[0] + quote, nil - case 2: - return quote + parts[0] + quote + "." + quote + parts[1] + quote, nil - default: - return "", errz.Errorf("invalid selector: %s", selector) - } -} - -// Range implements FragmentBuilder. -func (fb *BaseFragmentBuilder) Range(rr *ast.RowRangeNode) (string, error) { - if rr == nil { - return "", nil - } - - if rr.Limit < 0 && rr.Offset < 0 { - return "", nil - } - - limit := "" - offset := "" - if rr.Limit > -1 { - limit = fmt.Sprintf(" LIMIT %d", rr.Limit) - } - if rr.Offset > -1 { - offset = fmt.Sprintf(" OFFSET %d", rr.Offset) - - if rr.Limit == -1 { - // MySQL requires a LIMIT if OFFSET is used. Therefore - // we make the LIMIT a very large number - limit = fmt.Sprintf(" LIMIT %d", math.MaxInt64) - } - } - - sql := limit + offset - - return sql, nil -} - -// SelectCols implements FragmentBuilder. -func (fb *BaseFragmentBuilder) SelectCols(cols []ast.ResultColumn) (string, error) { - if len(cols) == 0 { - return "*", nil - } - - vals := make([]string, len(cols)) - for i, col := range cols { - // aliasFrag holds the "AS alias" fragment (if applicable). - // For example: "@sakila | .actor | .first_name:given_name" becomes - // "SELECT first_name AS given_name FROM actor". - var aliasFrag string - if col.Alias() != "" { - aliasFrag = " AS " + fb.QuoteFn(col.Alias()) - } - - switch col := col.(type) { - case *ast.ColSelectorNode: - vals[i] = fmt.Sprintf("%s%s%s", fb.Quote, col.ColName(), fb.Quote) - case *ast.TblColSelectorNode: - vals[i] = fmt.Sprintf("%s%s%s.%s%s%s", fb.Quote, col.TblName(), fb.Quote, fb.Quote, col.ColName(), fb.Quote) - case *ast.FuncNode: - // it's a function - var err error - if vals[i], err = fb.Function(col); err != nil { - return "", err - } - default: - // FIXME: We should be exhaustively checking the cases. - // Here, it's probably an ExprNode? - vals[i] = col.Text() // for now, we just return the raw text - } - - vals[i] += aliasFrag - } - - text := strings.Join(vals, ", ") - return text, nil -} - -var _ QueryBuilder = (*BaseQueryBuilder)(nil) - -// BaseQueryBuilder is a default implementation -// of sqlbuilder.QueryBuilder. -type BaseQueryBuilder struct { - Distinct string - Columns string - From string - Where string - GroupBy string - OrderBy string - Range string -} - -// SetDistinct implements QueryBuilder. -func (qb *BaseQueryBuilder) SetDistinct(d string) { - qb.Distinct = d -} - -// SetGroupBy implements QueryBuilder. -func (qb *BaseQueryBuilder) SetGroupBy(gb string) { - qb.GroupBy = gb -} - -// SetOrderBy implements QueryBuilder. -func (qb *BaseQueryBuilder) SetOrderBy(ob string) { - qb.OrderBy = ob -} - -// SetColumns implements QueryBuilder. -func (qb *BaseQueryBuilder) SetColumns(cols string) { - qb.Columns = cols -} - -// SetFrom implements QueryBuilder. -func (qb *BaseQueryBuilder) SetFrom(from string) { - qb.From = from -} - -// SetWhere implements QueryBuilder. -func (qb *BaseQueryBuilder) SetWhere(where string) { - qb.Where = where -} - -// SetRange implements QueryBuilder. -func (qb *BaseQueryBuilder) SetRange(rng string) { - qb.Range = rng -} - -// Render implements QueryBuilder. -func (qb *BaseQueryBuilder) Render() (string, error) { - sb := strings.Builder{} - - sb.WriteString("SELECT") - - if qb.Distinct != "" { - sb.WriteRune(sp) - sb.WriteString(qb.Distinct) - } - - sb.WriteRune(sp) - sb.WriteString(qb.Columns) - sb.WriteRune(sp) - sb.WriteString(qb.From) - - if qb.Where != "" { - sb.WriteRune(sp) - sb.WriteString(qb.Where) - } - - if qb.OrderBy != "" { - sb.WriteRune(sp) - sb.WriteString(qb.OrderBy) - } - - if qb.GroupBy != "" { - sb.WriteRune(sp) - sb.WriteString(qb.GroupBy) - } - - if qb.Range != "" { - sb.WriteRune(sp) - sb.WriteString(qb.Range) - } - - return sb.String(), nil -} - -// escapeLiteral escapes the single quotes in s. -// -// jessie's girl --> jessie''s girl -func escapeLiteral(s string) string { - sb := strings.Builder{} - for _, r := range s { - if r == singleQuote { - _, _ = sb.WriteRune(singleQuote) - } - - _, _ = sb.WriteRune(r) - } - - return sb.String() -} - -// unquoteLiteral returns true if s is a double-quoted string, and also returns -// the value with the quotes stripped. An error is returned if the string -// is malformed. -// -// REVISIT: why not use strconv.Unquote or such? -func unquoteLiteral(s string) (val string, ok bool, err error) { - hasPrefix := strings.HasPrefix(s, `"`) - hasSuffix := strings.HasSuffix(s, `"`) - - if hasPrefix && hasSuffix { - val = strings.TrimPrefix(s, `"`) - val = strings.TrimSuffix(val, `"`) - return val, true, nil - } - - if hasPrefix != hasSuffix { - return "", false, errz.Errorf("malformed literal: %s", s) - } - - return s, false, nil -} diff --git a/libsq/ast/sqlbuilder/internal_test.go b/libsq/ast/sqlbuilder/internal_test.go deleted file mode 100644 index a9de4fd1..00000000 --- a/libsq/ast/sqlbuilder/internal_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package sqlbuilder - -import ( - "testing" - - "github.com/neilotoole/sq/testh/tutil" - - "github.com/stretchr/testify/require" -) - -func TestQuoteTableOrColSelector(t *testing.T) { - testCases := []struct { - in string - want string - wantErr bool - }{ - {in: "", wantErr: true}, - {in: " ", wantErr: true}, - {in: "not_start_with_period", wantErr: true}, - {in: ".table", want: `"table"`}, - {in: ".table.col", want: `"table"."col"`}, - {in: ".table.col.other", wantErr: true}, - } - - const quote = `"` - - for _, tc := range testCases { - tc := tc - t.Run(tc.in, func(t *testing.T) { - got, gotErr := quoteTableOrColSelector(quote, tc.in) - if tc.wantErr { - require.Error(t, gotErr) - return - } - - require.NoError(t, gotErr) - require.Equal(t, tc.want, got) - }) - } -} - -func TestEscapeLiteralString(t *testing.T) { - testCases := []struct { - in string - want string - }{ - {in: ``, want: ``}, - {in: ` `, want: ` `}, - {in: `hello`, want: `hello`}, - {in: `"hello"`, want: `"hello"`}, - {in: `there's`, want: `there''s`}, - {in: `double''`, want: `double''''`}, - } - - for i, tc := range testCases { - tc := tc - - t.Run(tutil.Name(i, tc.in), func(t *testing.T) { - got := escapeLiteral(tc.in) - require.Equal(t, tc.want, got) - }) - } -} diff --git a/libsq/ast/sqlbuilder/sqlbuilder.go b/libsq/ast/sqlbuilder/sqlbuilder.go deleted file mode 100644 index fd1c7d5d..00000000 --- a/libsq/ast/sqlbuilder/sqlbuilder.go +++ /dev/null @@ -1,74 +0,0 @@ -// Package sqlbuilder contains functionality for building SQL from -// the ast. -package sqlbuilder - -import ( - "github.com/neilotoole/sq/libsq/ast" -) - -// FragmentBuilder renders driver-specific SQL fragments. -type FragmentBuilder interface { - // FromTable renders a FROM table fragment. - FromTable(tblSel *ast.TblSelectorNode) (string, error) - - // SelectCols renders a column names/expression fragment. - // It shouldn't render the actual SELECT keyword. Example: - // - // "first_name", "last name" AS given_name - SelectCols(cols []ast.ResultColumn) (string, error) - - // Range renders a row range fragment. - Range(rr *ast.RowRangeNode) (string, error) - - // OrderBy renders the ORDER BY fragment. - OrderBy(ob *ast.OrderByNode) (string, error) - - // GroupBy renders the GROUP BY fragment. - GroupBy(gb *ast.GroupByNode) (string, error) - - // Join renders a join fragment. - Join(fnJoin *ast.JoinNode) (string, error) - - // Function renders a function fragment. - Function(fn *ast.FuncNode) (string, error) - - // Where renders a WHERE fragment. - Where(where *ast.WhereNode) (string, error) - - // Expr renders an expression fragment. - Expr(expr *ast.ExprNode) (string, error) - - // Operator renders an operator fragment. - Operator(op *ast.OperatorNode) (string, error) - - // Distinct renders the DISTINCT fragment. Returns an - // empty string if n is nil. - Distinct(n *ast.UniqueNode) (string, error) -} - -// QueryBuilder provides an abstraction for building a SQL query. -type QueryBuilder interface { - // SetColumns sets the columns to select. - SetColumns(cols string) - - // SetFrom sets the FROM clause. - SetFrom(from string) - - // SetWhere sets the WHERE clause. - SetWhere(where string) - - // SetRange sets the LIMIT ... OFFSET clause. - SetRange(rng string) - - // SetOrderBy sets the ORDER BY clause. - SetOrderBy(ob string) - - // SetGroupBy sets the GROUP BY clause. - SetGroupBy(gb string) - - // SetDistinct sets the DISTINCT clause. - SetDistinct(d string) - - // Render renders the SQL query. - Render() (string, error) -} diff --git a/libsq/ast/walker.go b/libsq/ast/walker.go index 53bff628..45c02df0 100644 --- a/libsq/ast/walker.go +++ b/libsq/ast/walker.go @@ -2,19 +2,13 @@ package ast import ( "reflect" - - "github.com/neilotoole/sq/libsq/core/lg/lga" - "github.com/neilotoole/sq/libsq/core/stringz" - - "golang.org/x/exp/slog" ) // nodeVisitorFn is a visitor function that the walker invokes for each node it visits. -type nodeVisitorFn func(*slog.Logger, *Walker, Node) error +type nodeVisitorFn func(*Walker, Node) error // Walker traverses a node tree (the AST, or a subset thereof). type Walker struct { - log *slog.Logger root Node visitors map[reflect.Type][]nodeVisitorFn // state is a generic field to hold any data that a visitor function @@ -23,14 +17,14 @@ type Walker struct { } // NewWalker returns a new Walker instance. -func NewWalker(log *slog.Logger, node Node) *Walker { - w := &Walker{log: log, root: node} +func NewWalker(node Node) *Walker { + w := &Walker{root: node} w.visitors = map[reflect.Type][]nodeVisitorFn{} return w } -// AddVisitor adds a visitor function for the specified node type (and returns -// the receiver Walker, to enabled chaining). +// AddVisitor adds a visitor function for any node that is assignable +// to typ. func (w *Walker) AddVisitor(typ reflect.Type, visitor nodeVisitorFn) *Walker { funcs := w.visitors[typ] if funcs == nil { @@ -48,17 +42,19 @@ func (w *Walker) Walk() error { } func (w *Walker) visit(node Node) error { - typ := reflect.TypeOf(node) - visitFns, ok := w.visitors[typ] - - if ok { - for _, visitFn := range visitFns { - err := visitFn(w.log, w, node) - if err != nil { - return err - } + var visitFns []nodeVisitorFn + nodeType := reflect.TypeOf(node) + for fnType, fns := range w.visitors { + if nodeType.AssignableTo(fnType) { + visitFns = append(visitFns, fns...) + } + } + + for _, visitFn := range visitFns { + err := visitFn(w, node) + if err != nil { + return err } - return nil } return w.visitChildren(node) @@ -76,12 +72,12 @@ func (w *Walker) visitChildren(node Node) error { } // walkWith is a convenience function for using Walker. -func walkWith(log *slog.Logger, ast *AST, typ reflect.Type, fn nodeVisitorFn) error { - return NewWalker(log, ast).AddVisitor(typ, fn).Walk() +func walkWith(ast *AST, typ reflect.Type, fn nodeVisitorFn) error { + return NewWalker(ast).AddVisitor(typ, fn).Walk() } // narrowTblSel takes a generic selector, and if appropriate, converts it to a TblSel. -func narrowTblSel(_ *slog.Logger, _ *Walker, node Node) error { +func narrowTblSel(_ *Walker, node Node) error { // node is guaranteed to be typeSelectorNode sel, ok := node.(*SelectorNode) if !ok { @@ -125,7 +121,7 @@ func narrowTblSel(_ *slog.Logger, _ *Walker, node Node) error { // narrowTblColSel takes a generic selector, and if appropriate, replaces it // with a TblColSelectorNode. -func narrowTblColSel(log *slog.Logger, w *Walker, node Node) error { +func narrowTblColSel(w *Walker, node Node) error { // node is guaranteed to be type SelectorNode sel, ok := node.(*SelectorNode) if !ok { @@ -148,13 +144,13 @@ func narrowTblColSel(log *slog.Logger, w *Walker, node Node) error { // if the parent is a segment, this is a "top-level" selector. // Only top-level selectors after the final selectable seg are // convert to TblColSelectorNode. - selectableSeg, err := NewInspector(log, w.root.(*AST)).FindFinalTablerSegment() + selectableSeg, err := NewInspector(w.root.(*AST)).FindFinalTablerSegment() if err != nil { return err } if parent.SegIndex() <= selectableSeg.SegIndex() { - log.Debug("skipping this selector because it's not after the final selectable segment") + // Skipping this selector because it's not after the final selectable segment return nil } @@ -177,7 +173,7 @@ func narrowTblColSel(log *slog.Logger, w *Walker, node Node) error { } // narrowColSel takes a generic selector, and if appropriate, converts it to a ColSel. -func narrowColSel(log *slog.Logger, w *Walker, node Node) error { +func narrowColSel(w *Walker, node Node) error { // node is guaranteed to be type SelectorNode sel, ok := node.(*SelectorNode) if !ok { @@ -197,13 +193,13 @@ func narrowColSel(log *slog.Logger, w *Walker, node Node) error { // if the parent is a segment, this is a "top-level" selector. // Only top-level selectors after the final selectable seg are // convert to colSels. - selectableSeg, err := NewInspector(log, w.root.(*AST)).FindFinalTablerSegment() + selectableSeg, err := NewInspector(w.root.(*AST)).FindFinalTablerSegment() if err != nil { return err } if parent.SegIndex() <= selectableSeg.SegIndex() { - log.Debug("Skipping this selector because it's not after the final selectable segment") + // Skipping this selector because it's not after the final selectable segment return nil } @@ -214,21 +210,23 @@ func narrowColSel(log *slog.Logger, w *Walker, node Node) error { return nodeReplace(sel, colSel) default: - log.Warn("Skipping this selector, as parent is not of a relevant type", lga.Type, stringz.Type(parent)) + // Skipping this selector, as parent is not of a relevant type } return nil } -// findWhereClause locates any expressions that represent the WHERE clause of the SQL SELECT stmt, and -// inserts a SetWhere node into the AST for that expression. +// findWhereClause locates any expressions that represent the WHERE clause +// of the SQL SELECT stmt, and inserts a WhereNode +// into the AST for that expression. // -// In practice, a WHERE clause is an *ExprNode that is the only child of a segment. For example: +// In practice, a WHERE clause is an *ExprNode that +// is the only child of a segment. For example: // -// @my1 | .tbluser | .uid > 4 | .uid, .email +// @sakila | .actor | .actor_id > 4 | .first_name, .last_name // -// In this case, ".uid > 4" is the WHERE clause. -func findWhereClause(_ *slog.Logger, _ *Walker, node Node) error { +// In this case, ".actor_id > 4" is the WHERE clause. +func findWhereClause(_ *Walker, node Node) error { // node is guaranteed to be *ExprNode expr, ok := node.(*ExprNode) if !ok { @@ -263,7 +261,7 @@ func findWhereClause(_ *slog.Logger, _ *Walker, node Node) error { } // determineJoinTables attempts to determine the tables that a JOIN refers to. -func determineJoinTables(_ *slog.Logger, _ *Walker, node Node) error { +func determineJoinTables(_ *Walker, node Node) error { // node is guaranteed to be FnJoin fnJoin, ok := node.(*JoinNode) if !ok { @@ -298,7 +296,7 @@ func determineJoinTables(_ *slog.Logger, _ *Walker, node Node) error { } // visitCheckRowRange validates the RowRangeNode element. -func visitCheckRowRange(_ *slog.Logger, w *Walker, node Node) error { +func visitCheckRowRange(w *Walker, node Node) error { // node is guaranteed to be FnJoin rr, ok := node.(*RowRangeNode) if !ok { diff --git a/libsq/ast/walker_test.go b/libsq/ast/walker_test.go index 271119bc..4d7dcffb 100644 --- a/libsq/ast/walker_test.go +++ b/libsq/ast/walker_test.go @@ -4,8 +4,6 @@ import ( "testing" "github.com/neilotoole/slogt" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" ) @@ -20,10 +18,10 @@ func TestWalker(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, ast) - walker := NewWalker(log, ast) + walker := NewWalker(ast) count := 0 - visitor := func(log *slog.Logger, w *Walker, node Node) error { + visitor := func(w *Walker, node Node) error { count++ return w.visitChildren(node) } @@ -34,14 +32,14 @@ func TestWalker(t *testing.T) { assert.Equal(t, 1, count) // test multiple visitors on the same node type - walker = NewWalker(log, ast) + walker = NewWalker(ast) countA := 0 - visitorA := func(log *slog.Logger, w *Walker, node Node) error { + visitorA := func(w *Walker, node Node) error { countA++ return w.visitChildren(node) } countB := 0 - visitorB := func(log *slog.Logger, w *Walker, node Node) error { + visitorB := func(w *Walker, node Node) error { countB++ return w.visitChildren(node) } diff --git a/libsq/core/stringz/stringz.go b/libsq/core/stringz/stringz.go index 0836cdfc..2628023c 100644 --- a/libsq/core/stringz/stringz.go +++ b/libsq/core/stringz/stringz.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "math/rand" + "regexp" "strconv" "strings" "time" @@ -595,3 +596,16 @@ func SingleQuote(s string) string { func Type(v any) string { return fmt.Sprintf("%T", v) } + +var identRegex = regexp.MustCompile(`\A[a-zA-Z][a-zA-Z0-9_]*$`) + +// ValidIdent returns an error if s is not a valid identifier. +// And identifier must start with a letter, and may contain letters, +// numbers, and underscore. +func ValidIdent(s string) error { + if identRegex.Match([]byte(s)) { + return nil + } + + return errz.Errorf("invalid identifier: %s", s) +} diff --git a/libsq/core/stringz/stringz_test.go b/libsq/core/stringz/stringz_test.go index d7274a49..e6411052 100644 --- a/libsq/core/stringz/stringz_test.go +++ b/libsq/core/stringz/stringz_test.go @@ -409,3 +409,32 @@ func TestSingleQuote(t *testing.T) { }) } } + +func TestValidIdent(t *testing.T) { + testCases := []struct { + in string + wantErr bool + }{ + {in: "", wantErr: true}, + {in: "hello world", wantErr: true}, + {in: "hello", wantErr: false}, + {in: "1", wantErr: true}, + {in: "$hello", wantErr: true}, + {in: "_hello", wantErr: true}, + {in: "hello_", wantErr: false}, + {in: "Hello_", wantErr: false}, + {in: "Hello_1", wantErr: false}, + {in: "Hello_!!", wantErr: true}, + } + for _, tc := range testCases { + tc := tc + t.Run(tutil.Name(tc.in), func(t *testing.T) { + gotErr := stringz.ValidIdent(tc.in) + if tc.wantErr { + require.Error(t, gotErr) + } else { + require.NoError(t, gotErr) + } + }) + } +} diff --git a/libsq/driver/dialect/dialect.go b/libsq/driver/dialect/dialect.go new file mode 100644 index 00000000..1de1963e --- /dev/null +++ b/libsq/driver/dialect/dialect.go @@ -0,0 +1,61 @@ +// Package dialect contains functionality for SQL dialects. +package dialect + +import "github.com/neilotoole/sq/libsq/source" + +// Dialect holds driver-specific SQL dialect values and functions. +type Dialect struct { + // Type is the dialect's driver source type. + Type source.Type `json:"type"` + + // Placeholders returns a string a SQL placeholders string. + // For example "(?, ?, ?)" or "($1, $2, $3), ($4, $5, $6)". + Placeholders func(numCols, numRows int) string + + // IdentQuote is the identifier quote rune. Most often this is + // double-quote, e.g. SELECT * FROM "my_table", but can be other + // values such as backtick, e.g. SELECT * FROM `my_table`. + // + // Arguably, this field should be deprecated. There's probably + // no reason not to always use Enquote. + IdentQuote rune `json:"quote"` + + // Enquote is a function that quotes and escapes an + // identifier (such as a table or column name). + Enquote func(string) string + + // IntBool is true if BOOLEAN is handled as an INT by the DB driver. + IntBool bool `json:"int_bool"` + + // MaxBatchValues is the maximum number of values in a batch insert. + MaxBatchValues int + + // Ops is a map of SLQ operator (e.g. "==" or "!=") to + // its default SQL rendering. + Ops map[string]string +} + +// String returns a log/debug-friendly representation. +func (d Dialect) String() string { + return d.Type.String() +} + +// defaultOps is a map of SLQ operator (e.g. "==" or "!=") to +// its default SQL rendering. +var defaultOps = map[string]string{ + `==`: `=`, + `&&`: `AND`, + `||`: `OR`, + `!=`: `!=`, +} + +// DefaultOps returns a default map of SLQ operator (e.g. "==" or "!=") to +// its SQL rendering. The returned map is a copy and can be safely +// modified by the caller. +func DefaultOps() map[string]string { + ops := make(map[string]string, len(defaultOps)) + for k, v := range defaultOps { + ops[k] = v + } + return ops +} diff --git a/libsq/driver/driver.go b/libsq/driver/driver.go index 28b938a3..45c9fc8a 100644 --- a/libsq/driver/driver.go +++ b/libsq/driver/driver.go @@ -6,20 +6,20 @@ import ( "strings" "sync" + "github.com/neilotoole/sq/libsq/driver/dialect" + "github.com/neilotoole/sq/libsq/core/lg/lga" "github.com/neilotoole/sq/libsq/core/lg" "golang.org/x/exp/slog" - "github.com/neilotoole/sq/libsq/core/kind" - "github.com/neilotoole/sq/libsq/core/stringz" - "github.com/neilotoole/sq/libsq/core/cleanup" + "github.com/neilotoole/sq/libsq/core/kind" "github.com/neilotoole/sq/libsq/core/errz" - "github.com/neilotoole/sq/libsq/ast/sqlbuilder" + "github.com/neilotoole/sq/libsq/ast/render" "github.com/neilotoole/sq/libsq/core/sqlmodel" "github.com/neilotoole/sq/libsq/core/sqlz" "github.com/neilotoole/sq/libsq/source" @@ -82,10 +82,10 @@ type SQLDriver interface { Driver // Dialect returns the SQL dialect. - Dialect() Dialect + Dialect() dialect.Dialect - // SQLBuilder returns the SQL builder for this driver. - SQLBuilder() (sqlbuilder.FragmentBuilder, sqlbuilder.QueryBuilder) + // Renderer returns the SQL renderer for this driver. + Renderer() *render.Renderer // CurrentSchema returns the current schema name. CurrentSchema(ctx context.Context, db sqlz.DB) (string, error) @@ -218,34 +218,6 @@ type Metadata struct { Monotable bool `json:"monotable"` } -// Dialect holds driver-specific SQL dialect values. -type Dialect struct { - // Type is the dialect's driver source type. - Type source.Type `json:"type"` - - // Placeholders returns a string a SQL placeholders string. - // For example "(?, ?, ?)" or "($1, $2, $3), ($4, $5, $6)". - Placeholders func(numCols, numRows int) string - - // Quote is the quote rune, typically the double quote rune. - Quote rune `json:"quote"` - - // IntBool is true if BOOLEAN is handled as an INT by the DB driver. - IntBool bool `json:"int_bool"` - - // MaxBatchValues is the maximum number of values in a batch insert. - MaxBatchValues int -} - -// Enquote returns s surrounded by d.Quote. -func (d Dialect) Enquote(s string) string { - return stringz.Surround(s, string(d.Quote)) -} - -func (d Dialect) String() string { - return d.Type.String() -} - // Databases provides a mechanism for getting Database instances. // Note that at this time instances returned by Open are cached // and then closed by Close. This may be a bad approach. diff --git a/libsq/driver/driver_test.go b/libsq/driver/driver_test.go index 0b56bd9f..c0bbf956 100644 --- a/libsq/driver/driver_test.go +++ b/libsq/driver/driver_test.go @@ -400,7 +400,7 @@ func TestRegistry_DriversMetadata_SQL(t *testing.T) { dialect := sqlDrvr.Dialect() require.Equal(t, typ, dialect.Type) - require.NotEmpty(t, dialect.Quote) + require.NotEmpty(t, dialect.IdentQuote) require.NotNil(t, dialect.Placeholders) }) } diff --git a/libsq/driver/record.go b/libsq/driver/record.go index b9f87875..ea87962e 100644 --- a/libsq/driver/record.go +++ b/libsq/driver/record.go @@ -354,7 +354,7 @@ func PrepareInsertStmt(ctx context.Context, drvr SQLDriver, db sqlz.Preparer, de } dialect := drvr.Dialect() - quote := string(dialect.Quote) + quote := string(dialect.IdentQuote) tblNameQuoted, colNamesQuoted := stringz.Surround(destTbl, quote), stringz.SurroundSlice(destCols, quote) colsJoined := strings.Join(colNamesQuoted, Comma) placeholders := dialect.Placeholders(len(colNamesQuoted), numRows) diff --git a/libsq/engine.go b/libsq/engine.go index 6783f1e1..8c1b433c 100644 --- a/libsq/engine.go +++ b/libsq/engine.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/neilotoole/sq/libsq/ast/render" + "github.com/neilotoole/sq/libsq/core/lg" "github.com/neilotoole/sq/libsq/core/lg/lga" @@ -22,15 +24,21 @@ import ( type engine struct { log *slog.Logger + // qc is the context in which the query is executed. qc *QueryContext + // rc is the Context for rendering SQL. + // This field is set during engine.prepare. It can't be set before + // then because the target DB to use is calculated during engine.prepare, + // based on the input query and other context. + rc *render.Context + // tasks contains tasks that must be completed before targetSQL // is executed against targetDB. Typically tasks is used to // set up the joindb before it is queried. tasks []tasker - // targetSQL is the ultimate SQL query to be executed against - // targetDB. + // targetSQL is the ultimate SQL query to be executed against targetDB. targetSQL string // targetDB is the destination for the ultimate SQL query to @@ -63,87 +71,6 @@ func newEngine(ctx context.Context, qc *QueryContext, query string) (*engine, er return ng, nil } -// prepare prepares the engine to execute queryModel. -// When this method returns, targetDB and targetSQL will be set, -// as will any tasks (which may be empty). The tasks must be executed -// against targetDB before targetSQL is executed (the engine.execute -// method does this work). -func (ng *engine) prepare(ctx context.Context, qm *queryModel) error { - var ( - s string - err error - ) - - switch node := qm.Table.(type) { - case *ast.TblSelectorNode: - s, ng.targetDB, err = ng.buildTableFromClause(ctx, node) - if err != nil { - return err - } - case *ast.JoinNode: - s, ng.targetDB, err = ng.buildJoinFromClause(ctx, node) - if err != nil { - return err - } - default: - return errz.Errorf("unknown selectable %T(%s)", node, node) - } - - fb, qb := ng.targetDB.SQLDriver().SQLBuilder() - qb.SetFrom(s) - - if s, err = fb.SelectCols(qm.Cols); err != nil { - return err - } - qb.SetColumns(s) - - if qm.Distinct != nil { - if s, err = fb.Distinct(qm.Distinct); err != nil { - return err - } - - qb.SetDistinct(s) - } - - if qm.Range != nil { - if s, err = fb.Range(qm.Range); err != nil { - return err - } - - qb.SetRange(s) - } - - if qm.Where != nil { - if s, err = fb.Where(qm.Where); err != nil { - return err - } - - qb.SetWhere(s) - } - - if qm.OrderBy != nil { - if s, err = fb.OrderBy(qm.OrderBy); err != nil { - return err - } - - qb.SetOrderBy(s) - } - - if qm.GroupBy != nil { - if s, err = fb.GroupBy(qm.GroupBy); err != nil { - return err - } - qb.SetGroupBy(s) - } - - ng.targetSQL, err = qb.Render() - if err != nil { - return err - } - - return nil -} - // execute executes the plan that was built by engine.prepare. func (ng *engine) execute(ctx context.Context, recw RecordWriter) error { ng.log.Debug( @@ -186,6 +113,9 @@ func (ng *engine) executeTasks(ctx context.Context) error { return g.Wait() } +// buildTableFromClause builds the "FROM table" fragment. +// +// When this function returns, ng.rc will be set. func (ng *engine) buildTableFromClause(ctx context.Context, tblSel *ast.TblSelectorNode) (fromClause string, fromConn driver.Database, err error, ) { @@ -199,8 +129,14 @@ func (ng *engine) buildTableFromClause(ctx context.Context, tblSel *ast.TblSelec return "", nil, err } - fragBuilder, _ := fromConn.SQLDriver().SQLBuilder() - fromClause, err = fragBuilder.FromTable(tblSel) + rndr := fromConn.SQLDriver().Renderer() + ng.rc = &render.Context{ + Renderer: rndr, + Args: ng.qc.Args, + Dialect: fromConn.SQLDriver().Dialect(), + } + + fromClause, err = rndr.FromTable(ng.rc, tblSel) if err != nil { return "", nil, err } @@ -208,6 +144,9 @@ func (ng *engine) buildTableFromClause(ctx context.Context, tblSel *ast.TblSelec return fromClause, fromConn, nil } +// buildJoinFromClause builds the "JOIN" clause. +// +// When this function returns, ng.rc will be set. func (ng *engine) buildJoinFromClause(ctx context.Context, fnJoin *ast.JoinNode) (fromClause string, fromConn driver.Database, err error, ) { @@ -226,6 +165,9 @@ func (ng *engine) buildJoinFromClause(ctx context.Context, fnJoin *ast.JoinNode) return ng.singleSourceJoin(ctx, fnJoin) } +// singleSourceJoin sets up a join against a single source. +// +// On return, ng.rc will be set. func (ng *engine) singleSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (fromClause string, fromDB driver.Database, err error, ) { @@ -239,8 +181,14 @@ func (ng *engine) singleSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (f return "", nil, err } - fragBuilder, _ := fromDB.SQLDriver().SQLBuilder() - fromClause, err = fragBuilder.Join(fnJoin) + rndr := fromDB.SQLDriver().Renderer() + ng.rc = &render.Context{ + Renderer: rndr, + Args: ng.qc.Args, + Dialect: fromDB.SQLDriver().Dialect(), + } + + fromClause, err = rndr.Join(ng.rc, fnJoin) if err != nil { return "", nil, err } @@ -250,6 +198,8 @@ func (ng *engine) singleSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (f // crossSourceJoin returns a FROM clause that forms part of // the SQL SELECT statement against fromDB. +// +// On return, ng.rc will be set. func (ng *engine) crossSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (fromClause string, fromDB driver.Database, err error, ) { @@ -275,6 +225,13 @@ func (ng *engine) crossSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (fr return "", nil, err } + rndr := joinDB.SQLDriver().Renderer() + ng.rc = &render.Context{ + Renderer: rndr, + Args: ng.qc.Args, + Dialect: joinDB.SQLDriver().Dialect(), + } + leftDB, err := ng.qc.DBOpener.Open(ctx, leftSrc) if err != nil { return "", nil, err @@ -300,8 +257,7 @@ func (ng *engine) crossSourceJoin(ctx context.Context, fnJoin *ast.JoinNode) (fr ng.tasks = append(ng.tasks, leftCopyTask) ng.tasks = append(ng.tasks, rightCopyTask) - joinDBFragBuilder, _ := joinDB.SQLDriver().SQLBuilder() - fromClause, err = joinDBFragBuilder.Join(fnJoin) + fromClause, err = rndr.Join(ng.rc, fnJoin) if err != nil { return "", nil, err } @@ -389,7 +345,7 @@ func buildQueryModel(log *slog.Logger, a *ast.AST) (*queryModel, error) { return nil, errz.Errorf("query model error: query does not have enough segments") } - insp := ast.NewInspector(log, a) + insp := ast.NewInspector(a) tablerSeg, err := insp.FindFinalTablerSegment() if err != nil { return nil, err diff --git a/libsq/prepare.go b/libsq/prepare.go new file mode 100644 index 00000000..5f0661e8 --- /dev/null +++ b/libsq/prepare.go @@ -0,0 +1,82 @@ +package libsq + +import ( + "context" + + "github.com/neilotoole/sq/libsq/ast/render" + + "github.com/neilotoole/sq/libsq/ast" + "github.com/neilotoole/sq/libsq/core/errz" +) + +// prepare prepares the engine to execute queryModel. +// When this method returns, targetDB and targetSQL will be set, +// as will any tasks (which may be empty). The tasks must be executed +// against targetDB before targetSQL is executed (the engine.execute +// method does this work). +func (ng *engine) prepare(ctx context.Context, qm *queryModel) error { + var ( + err error + frags = &render.Fragments{} + ) + + // After this switch, ng.rc will be set. + switch node := qm.Table.(type) { + case *ast.TblSelectorNode: + if frags.From, ng.targetDB, err = ng.buildTableFromClause(ctx, node); err != nil { + return err + } + case *ast.JoinNode: + if frags.From, ng.targetDB, err = ng.buildJoinFromClause(ctx, node); err != nil { + return err + } + default: + // Should never happen + return errz.Errorf("unknown ast.Tabler %T: %s", node, node) + } + + rndr := ng.targetDB.SQLDriver().Renderer() + + if frags.Columns, err = rndr.SelectCols(ng.rc, qm.Cols); err != nil { + return err + } + + if qm.Distinct != nil { + if frags.Distinct, err = rndr.Distinct(ng.rc, qm.Distinct); err != nil { + return err + } + } + + if qm.Range != nil { + if frags.Range, err = rndr.Range(ng.rc, qm.Range); err != nil { + return err + } + } + + if qm.Where != nil { + if frags.Where, err = rndr.Where(ng.rc, qm.Where); err != nil { + return err + } + } + + if qm.OrderBy != nil { + if frags.OrderBy, err = rndr.OrderBy(ng.rc, qm.OrderBy); err != nil { + return err + } + } + + if qm.GroupBy != nil { + if frags.GroupBy, err = rndr.GroupBy(ng.rc, qm.GroupBy); err != nil { + return err + } + } + + if rndr.PreRender != nil { + if err = rndr.PreRender(ng.rc, frags); err != nil { + return err + } + } + + ng.targetSQL, err = rndr.Render(ng.rc, frags) + return err +} diff --git a/libsq/query_args_test.go b/libsq/query_args_test.go index 803083c3..1c93ebe7 100644 --- a/libsq/query_args_test.go +++ b/libsq/query_args_test.go @@ -8,20 +8,35 @@ import ( "github.com/neilotoole/sq/libsq/source" _ "github.com/mattn/go-sqlite3" - "github.com/neilotoole/sq/testh/sakila" ) -//nolint:exhaustive +//nolint:exhaustive,lll func TestQuery_args(t *testing.T) { testCases := []queryTestCase{ { - name: "cols", - in: `@sakila | .actor | .$a`, - args: map[string]string{"a": "first_name"}, - wantSQL: `SELECT "first_name", "last_name" FROM "actor"`, - override: map[source.Type]string{mysql.Type: "SELECT `first_name`, `last_name` FROM `actor`"}, - wantRecs: sakila.TblActorCount, - skip: true, + name: "arg_value_string", + in: `@sakila | .actor | .first_name == $first`, + args: map[string]string{"first": "TOM"}, + wantSQL: `SELECT * FROM "actor" WHERE "first_name" = 'TOM'`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `first_name` = 'TOM'"}, + wantRecs: 2, + }, + { + name: "arg_value_string_2", + in: `@sakila | .actor | .first_name == $first && .last_name == $last`, + args: map[string]string{"first": "TOM", "last": "MIRANDA"}, + wantSQL: `SELECT * FROM "actor" WHERE "first_name" = 'TOM' AND "last_name" = 'MIRANDA'`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `first_name` = 'TOM' AND `last_name` = 'MIRANDA'"}, + wantRecs: 1, + }, + { + name: "arg_value_int", + in: `@sakila | .actor | .actor_id == int($id)`, + args: map[string]string{"id": "1"}, + wantSQL: `SELECT * FROM "actor" WHERE "actor_id" = 1`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `actor_id` = 1"}, + skip: true, // Skip until we implement casting, e.g. .actor_id == int($id) + wantRecs: 1, }, } diff --git a/libsq/query_expr_test.go b/libsq/query_expr_test.go new file mode 100644 index 00000000..f66381c5 --- /dev/null +++ b/libsq/query_expr_test.go @@ -0,0 +1,65 @@ +package libsq_test + +import ( + "testing" + + "github.com/neilotoole/sq/drivers/mysql" + + "github.com/neilotoole/sq/libsq/source" + + _ "github.com/mattn/go-sqlite3" +) + +//nolint:exhaustive,lll +func TestQuery_expr(t *testing.T) { + testCases := []queryTestCase{ + { + name: "literal/string", + in: `@sakila | .actor | .first_name == "TOM"`, + wantSQL: `SELECT * FROM "actor" WHERE "first_name" = 'TOM'`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `first_name` = 'TOM'"}, + wantRecs: 2, + }, + { + name: "literal/two-strings", + in: `@sakila | .actor | .first_name == "TOM" && .last_name == "MIRANDA"`, + wantSQL: `SELECT * FROM "actor" WHERE "first_name" = 'TOM' AND "last_name" = 'MIRANDA'`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `first_name` = 'TOM' AND `last_name` = 'MIRANDA'"}, + wantRecs: 1, + }, + { + name: "literal/integer", + in: `@sakila | .actor | .actor_id == 1`, + wantSQL: `SELECT * FROM "actor" WHERE "actor_id" = 1`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `actor` WHERE `actor_id` = 1"}, + wantRecs: 1, + }, + { + name: "is_null", + in: `@sakila | .address | .postal_code == null`, + wantSQL: `SELECT * FROM "address" WHERE "postal_code" IS NULL`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `address` WHERE `postal_code` IS NULL"}, + wantRecs: 4, + // skipExec because mysql sakila db doesn't have the same null values. + // This is a bug in the dataset. + skipExec: true, + }, + { + name: "is_not_null", + in: `@sakila | .address | .postal_code != null`, + wantSQL: `SELECT * FROM "address" WHERE "postal_code" IS NOT NULL`, + override: map[source.Type]string{mysql.Type: "SELECT * FROM `address` WHERE `postal_code` IS NOT NULL"}, + wantRecs: 599, + // skipExec because mysql sakila db doesn't have the same null values. + // This is a bug in the dataset. + skipExec: true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + execQueryTestCase(t, tc) + }) + } +} diff --git a/libsq/query_test.go b/libsq/query_test.go index 6c7b9706..1527fdc4 100644 --- a/libsq/query_test.go +++ b/libsq/query_test.go @@ -65,11 +65,14 @@ func execQueryTestCase(t *testing.T, tc queryTestCase) { t.Skip() } + t.Helper() srcs := testh.New(t).NewSourceSet(sakila.SQLLatest()...) for _, src := range srcs.Items() { src := src t.Run(string(src.Type), func(t *testing.T) { + t.Helper() + if len(tc.onlyFor) > 0 { if !slices.Contains(tc.onlyFor, src.Type) { t.Skip() @@ -110,7 +113,7 @@ func execQueryTestCase(t *testing.T, tc queryTestCase) { return } - sink, err := th.QuerySLQ(in) + sink, err := th.QuerySLQ(in, tc.args) require.NoError(t, err) require.Equal(t, tc.wantRecs, len(sink.Recs)) }) diff --git a/testh/testh.go b/testh/testh.go index f3347b73..25ec4b38 100644 --- a/testh/testh.go +++ b/testh/testh.go @@ -466,13 +466,14 @@ func (h *Helper) QuerySQL(src *source.Source, query string, args ...any) (*Recor return sink, nil } -// QuerySLQ executes the SLQ query. -func (h *Helper) QuerySLQ(query string) (*RecordSink, error) { +// QuerySLQ executes the SLQ query. Args are predefined variables for +// substitution. +func (h *Helper) QuerySLQ(query string, args map[string]string) (*RecordSink, error) { // We need to ensure that each of the handles in the query is loaded. a, err := ast.Parse(h.Log, query) require.NoError(h.T, err) - for _, handle := range ast.NewInspector(h.Log, a).FindHandles() { + for _, handle := range ast.NewInspector(a).FindHandles() { // This triggers handle loading _ = h.Source(handle) } @@ -481,6 +482,7 @@ func (h *Helper) QuerySLQ(query string) (*RecordSink, error) { Sources: h.srcs, DBOpener: h.databases, JoinDBOpener: h.databases, + Args: args, } sink := &RecordSink{}