From cb77511aa52408a0e70042cd1adfaa9993ad18db Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 26 Jun 2022 21:22:21 +0900 Subject: [PATCH 01/17] Fix a bug that causes incorrect output of results in TEXT or BOX format when the --without-header option is specified. --- lib/query/encode.go | 2 +- lib/query/encode_test.go | 46 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/query/encode.go b/lib/query/encode.go index 9b0113f..8a23853 100644 --- a/lib/query/encode.go +++ b/lib/query/encode.go @@ -327,7 +327,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.Expor fieldLen := view.FieldLen() - if !options.WithoutHeader { + if !options.WithoutHeader || (options.Format != cmd.GFM && options.Format != cmd.ORG) { hfields := make([]table.Field, fieldLen) for i := range view.Header { hfields[i] = table.NewField(view.Header[i].Column, text.Centering) diff --git a/lib/query/encode_test.go b/lib/query/encode_test.go index 4273494..53d9a3d 100644 --- a/lib/query/encode_test.go +++ b/lib/query/encode_test.go @@ -73,6 +73,29 @@ var encodeViewTests = []struct { "| | | |\n" + "+----------+-------------------------------------+--------+", }, + { + Name: "Text, --without--header option is ignored", + View: &View{ + Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), + RecordSet: []Record{ + NewRecord([]value.Primary{value.NewInteger(-1), value.NewTernary(ternary.UNKNOWN), value.NewBoolean(true)}), + NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), + NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), + }, + }, + Format: cmd.TEXT, + WithoutHeader: true, + Result: "+----------+-------------------------------------+--------+\n" + + "| c1 | c2 | c3 |\n" + + "| | second line | |\n" + + "+----------+-------------------------------------+--------+\n" + + "| -1 | UNKNOWN | true |\n" + + "| 2.0123 | 2016-02-01T16:00:00.123456-07:00 | abcdef |\n" + + "| 34567890 | abcdefghijklmnopqrstuvwxyzabcdefg | NULL |\n" + + "| | hi\"jk日本語あアアA( | |\n" + + "| | | |\n" + + "+----------+-------------------------------------+--------+", + }, { Name: "Text with colors", View: &View{ @@ -115,6 +138,29 @@ var encodeViewTests = []struct { "│ │ │ │\n" + "└──────────┴─────────────────────────────────────┴────────┘", }, + { + Name: "Box, --without-header option is ignored", + View: &View{ + Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), + RecordSet: []Record{ + NewRecord([]value.Primary{value.NewInteger(-1), value.NewTernary(ternary.UNKNOWN), value.NewBoolean(true)}), + NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), + NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), + }, + }, + Format: cmd.BOX, + WithoutHeader: true, + Result: "┌──────────┬─────────────────────────────────────┬────────┐\n" + + "│ c1 │ c2 │ c3 │\n" + + "│ │ second line │ │\n" + + "├──────────┼─────────────────────────────────────┼────────┤\n" + + "│ -1 │ UNKNOWN │ true │\n" + + "│ 2.0123 │ 2016-02-01T16:00:00.123456-07:00 │ abcdef │\n" + + "│ 34567890 │ abcdefghijklmnopqrstuvwxyzabcdefg │ NULL │\n" + + "│ │ hi\"jk日本語あアアA( │ │\n" + + "│ │ │ │\n" + + "└──────────┴─────────────────────────────────────┴────────┘", + }, { Name: "Box with colors", View: &View{ From fafd4d905bf4ef5de6ef473d7d6f1243480127f0 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 12:46:31 +0900 Subject: [PATCH 02/17] Update the version of github.com/urfave/cli to v2. --- go.mod | 9 +- go.sum | 13 +- main.go | 448 ++++++++++++++++++++++++++++++-------------------------- 3 files changed, 258 insertions(+), 212 deletions(-) diff --git a/go.mod b/go.mod index cdb226c..5be257e 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,17 @@ require ( github.com/mithrandie/go-text v1.5.3 github.com/mithrandie/readline-csvq v1.2.0 github.com/mithrandie/ternary v1.1.1 - github.com/urfave/cli v1.20.0 + github.com/urfave/cli/v2 v2.10.3 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c golang.org/x/text v0.3.7 ) -require golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect +) go 1.17 diff --git a/go.sum b/go.sum index b429346..023ffc3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,6 @@ +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mithrandie/go-file/v2 v2.1.0 h1:XA5Tl+73GXMDvgwSE3Sg0uC5FkLr3hnXs8SpUas0hyg= @@ -8,8 +11,12 @@ github.com/mithrandie/readline-csvq v1.2.0 h1:5GFbdWFP+2m57Yz+XLtKVIfyH0SjN9du51 github.com/mithrandie/readline-csvq v1.2.0/go.mod h1:6Grnfrl8PHC448fV7f8RJNlHeoM+Z3w2QlYW+J9mA2I= github.com/mithrandie/ternary v1.1.1 h1:k/joD6UGVYxHixYmSR8EGgDFNONBMqyD373xT4QRdC4= github.com/mithrandie/ternary v1.1.1/go.mod h1:0D9Ba3+09K2TdSZO7/bFCC0GjSXetCvYuYq0u8FY/1g= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/urfave/cli/v2 v2.10.3 h1:oi571Fxz5aHugfBAJd5nkwSk3fzATXtMlpxdLylSCMo= +github.com/urfave/cli/v2 v2.10.3/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -24,3 +31,5 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index e8b5d14..62f44f4 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,7 @@ import ( "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func main() { @@ -32,156 +32,188 @@ func main() { app.Version = query.Version app.OnUsageError = onUsageError app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "repository, r", - Usage: "directory `PATH` where files are located", - }, - cli.StringFlag{ - Name: "timezone, z", - Value: "Local", - Usage: "default timezone", - }, - cli.StringFlag{ - Name: "datetime-format, t", - Usage: "datetime format to parse strings", - }, - cli.BoolFlag{ - Name: "ansi-quotes, k", - Usage: "use double quotation mark as identifier enclosure", - }, - cli.BoolFlag{ - Name: "strict-equal, g", - Usage: "compare strictly that two values are equal for DISTINCT, GROUP BY and ORDER BY", - }, - cli.Float64Flag{ - Name: "wait-timeout, w", - Value: 10, - Usage: "limit of the waiting time in seconds to wait for locked files to be released", - }, - cli.StringFlag{ - Name: "source, s", - Usage: "load query or statements from `FILE`", - }, - cli.StringFlag{ - Name: "import-format, i", - Value: "CSV", - Usage: "default format to load files", - }, - cli.StringFlag{ - Name: "delimiter, d", - Value: ",", - Usage: "field delimiter for CSV", - }, - cli.BoolFlag{ + &cli.StringFlag{ + Name: "repository", + Aliases: []string{"r"}, + Usage: "directory `PATH` where files are located", + }, + &cli.StringFlag{ + Name: "timezone", + Aliases: []string{"z"}, + Value: "Local", + Usage: "default timezone", + }, + &cli.StringFlag{ + Name: "datetime-format", + Aliases: []string{"t"}, + Usage: "datetime format to parse strings", + }, + &cli.BoolFlag{ + Name: "ansi-quotes", + Aliases: []string{"k"}, + Usage: "use double quotation mark as identifier enclosure", + }, + &cli.BoolFlag{ + Name: "strict-equal", + Aliases: []string{"g"}, + Usage: "compare strictly that two values are equal for DISTINCT, GROUP BY and ORDER BY", + }, + &cli.Float64Flag{ + Name: "wait-timeout", + Aliases: []string{"w"}, + Value: 10, + Usage: "limit of the waiting time in seconds to wait for locked files to be released", + }, + &cli.StringFlag{ + Name: "source", + Aliases: []string{"s"}, + Usage: "load query or statements from `FILE`", + }, + &cli.StringFlag{ + Name: "import-format", + Aliases: []string{"i"}, + Value: "CSV", + Usage: "default format to load files", + }, + &cli.StringFlag{ + Name: "delimiter", + Aliases: []string{"d"}, + Value: ",", + Usage: "field delimiter for CSV", + }, + &cli.BoolFlag{ Name: "allow-uneven-fields", Usage: "allow loading CSV files with uneven field length", }, - cli.StringFlag{ - Name: "delimiter-positions, m", - Usage: "delimiter positions for FIXED", - }, - cli.StringFlag{ - Name: "json-query, j", - Usage: "`QUERY` for JSON", - }, - cli.StringFlag{ - Name: "encoding, e", - Value: "AUTO", - Usage: "file encoding", - }, - cli.BoolFlag{ - Name: "no-header, n", - Usage: "import the first line as a record", - }, - cli.BoolFlag{ - Name: "without-null, a", - Usage: "parse empty fields as empty strings", - }, - cli.StringFlag{ - Name: "out, o", - Usage: "export result sets of select queries to `FILE`", - }, - cli.BoolFlag{ - Name: "strip-ending-line-break, T", - Usage: "strip line break from the end of files and query results", - }, - cli.StringFlag{ - Name: "format, f", - Usage: "format of query results. (default: \"CSV\" for output to pipe, \"TEXT\" otherwise)", - }, - cli.StringFlag{ - Name: "write-encoding, E", - Value: "UTF8", - Usage: "character encoding of query results", - }, - cli.StringFlag{ - Name: "write-delimiter, D", - Value: ",", - Usage: "field delimiter for CSV in query results", - }, - cli.StringFlag{ - Name: "write-delimiter-positions, M", - Usage: "delimiter positions for FIXED in query results", - }, - cli.BoolFlag{ - Name: "without-header, N", - Usage: "export result sets of select queries without the header line", - }, - cli.StringFlag{ - Name: "line-break, l", - Value: "LF", - Usage: "line break in query results", - }, - cli.BoolFlag{ - Name: "enclose-all, Q", - Usage: "enclose all string values in CSV and TSV", - }, - cli.StringFlag{ - Name: "json-escape, J", - Value: "BACKSLASH", - Usage: "JSON escape type", - }, - cli.BoolFlag{ - Name: "pretty-print, P", - Usage: "make JSON output easier to read in query results", - }, - cli.BoolFlag{ - Name: "east-asian-encoding, W", - Usage: "count ambiguous characters as fullwidth", - }, - cli.BoolFlag{ - Name: "count-diacritical-sign, S", - Usage: "count diacritical signs as halfwidth", - }, - cli.BoolFlag{ - Name: "count-format-code, A", - Usage: "count format characters and zero-width spaces as halfwidth", - }, - cli.BoolFlag{ - Name: "color, c", - Usage: "use ANSI color escape sequences", - }, - cli.BoolFlag{ - Name: "quiet, q", - Usage: "suppress operation log output", - }, - cli.IntFlag{ + &cli.StringFlag{ + Name: "delimiter-positions", + Aliases: []string{"m"}, + Usage: "delimiter positions for FIXED", + }, + &cli.StringFlag{ + Name: "json-query", + Aliases: []string{"j"}, + Usage: "`QUERY` for JSON", + }, + &cli.StringFlag{ + Name: "encoding", + Aliases: []string{"e"}, + Value: "AUTO", + Usage: "file encoding", + }, + &cli.BoolFlag{ + Name: "no-header", + Aliases: []string{"n"}, + Usage: "import the first line as a record", + }, + &cli.BoolFlag{ + Name: "without-null", + Aliases: []string{"a"}, + Usage: "parse empty fields as empty strings", + }, + &cli.StringFlag{ + Name: "out", + Aliases: []string{"o"}, + Usage: "export result sets of select queries to `FILE`", + }, + &cli.BoolFlag{ + Name: "strip-ending-line-break", + Aliases: []string{"T"}, + Usage: "strip line break from the end of files and query results", + }, + &cli.StringFlag{ + Name: "format", + Aliases: []string{"f"}, + Usage: "format of query results. (default: \"CSV\" for output to pipe, \"TEXT\" otherwise)", + }, + &cli.StringFlag{ + Name: "write-encoding", + Aliases: []string{"E"}, + Value: "UTF8", + Usage: "character encoding of query results", + }, + &cli.StringFlag{ + Name: "write-delimiter", + Aliases: []string{"D"}, + Value: ",", + Usage: "field delimiter for CSV in query results", + }, + &cli.StringFlag{ + Name: "write-delimiter-positions", + Aliases: []string{"M"}, + Usage: "delimiter positions for FIXED in query results", + }, + &cli.BoolFlag{ + Name: "without-header", + Aliases: []string{"N"}, + Usage: "export result sets of select queries without the header line", + }, + &cli.StringFlag{ + Name: "line-break", + Aliases: []string{"l"}, + Value: "LF", + Usage: "line break in query results", + }, + &cli.BoolFlag{ + Name: "enclose-all", + Aliases: []string{"Q"}, + Usage: "enclose all string values in CSV and TSV", + }, + &cli.StringFlag{ + Name: "json-escape", + Aliases: []string{"J"}, + Value: "BACKSLASH", + Usage: "JSON escape type", + }, + &cli.BoolFlag{ + Name: "pretty-print", + Aliases: []string{"P"}, + Usage: "make JSON output easier to read in query results", + }, + &cli.BoolFlag{ + Name: "east-asian-encoding", + Aliases: []string{"W"}, + Usage: "count ambiguous characters as fullwidth", + }, + &cli.BoolFlag{ + Name: "count-diacritical-sign", + Aliases: []string{"S"}, + Usage: "count diacritical signs as halfwidth", + }, + &cli.BoolFlag{ + Name: "count-format-code", + Aliases: []string{"A"}, + Usage: "count format characters and zero-width spaces as halfwidth", + }, + &cli.BoolFlag{ + Name: "color", + Aliases: []string{"c"}, + Usage: "use ANSI color escape sequences", + }, + &cli.BoolFlag{ + Name: "quiet", + Aliases: []string{"q"}, + Usage: "suppress operation log output", + }, + &cli.IntFlag{ Name: "limit-recursion", Value: 1000, Usage: "maximum number of iterations for recursive queries", }, - cli.IntFlag{ - Name: "cpu, p", - Value: cmd.GetDefaultNumberOfCPU(), - Usage: "hint for the number of cpu cores to be used", + &cli.IntFlag{ + Name: "cpu", + Aliases: []string{"p"}, + Value: cmd.GetDefaultNumberOfCPU(), + Usage: "hint for the number of cpu cores to be used", }, - cli.BoolFlag{ - Name: "stats, x", - Usage: "show execution time and memory statistics", + &cli.BoolFlag{ + Name: "stats", + Aliases: []string{"x"}, + Usage: "show execution time and memory statistics", }, } - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "fields", Usage: "Show fields in a file", @@ -223,7 +255,7 @@ func main() { Usage: "Check for updates", ArgsUsage: " ", Flags: []cli.Flag{ - cli.BoolFlag{ + &cli.BoolFlag{ Name: "include-pre-release", Usage: "check including pre-release version", }, @@ -255,7 +287,7 @@ func main() { if len(queryString) < 1 { err = action.LaunchInteractiveShell(ctx, proc) } else { - err = action.Run(ctx, proc, queryString, path, c.GlobalString("out")) + err = action.Run(ctx, proc, queryString, path, c.String("out")) } return err @@ -337,130 +369,130 @@ func commandAction(fn func(ctx context.Context, c *cli.Context, proc *query.Proc } func overwriteFlags(c *cli.Context, tx *query.Transaction) error { - if c.GlobalIsSet("repository") { - if err := tx.SetFlag(cmd.RepositoryFlag, c.GlobalString("repository")); err != nil { + if c.IsSet("repository") { + if err := tx.SetFlag(cmd.RepositoryFlag, c.String("repository")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("timezone") { - if err := tx.SetFlag(cmd.TimezoneFlag, c.GlobalString("timezone")); err != nil { + if c.IsSet("timezone") { + if err := tx.SetFlag(cmd.TimezoneFlag, c.String("timezone")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("datetime-format") { - _ = tx.SetFlag(cmd.DatetimeFormatFlag, c.GlobalString("datetime-format")) + if c.IsSet("datetime-format") { + _ = tx.SetFlag(cmd.DatetimeFormatFlag, c.String("datetime-format")) } - if c.GlobalIsSet("ansi-quotes") { - _ = tx.SetFlag(cmd.AnsiQuotesFlag, c.GlobalBool("ansi-quotes")) + if c.IsSet("ansi-quotes") { + _ = tx.SetFlag(cmd.AnsiQuotesFlag, c.Bool("ansi-quotes")) } - if c.GlobalIsSet("strict-equal") { - _ = tx.SetFlag(cmd.StrictEqualFlag, c.GlobalBool("strict-equal")) + if c.IsSet("strict-equal") { + _ = tx.SetFlag(cmd.StrictEqualFlag, c.Bool("strict-equal")) } - if c.GlobalIsSet("wait-timeout") { - _ = tx.SetFlag(cmd.WaitTimeoutFlag, c.GlobalFloat64("wait-timeout")) + if c.IsSet("wait-timeout") { + _ = tx.SetFlag(cmd.WaitTimeoutFlag, c.Float64("wait-timeout")) } - if c.GlobalIsSet("color") { - _ = tx.SetFlag(cmd.ColorFlag, c.GlobalBool("color")) + if c.IsSet("color") { + _ = tx.SetFlag(cmd.ColorFlag, c.Bool("color")) } - if c.GlobalIsSet("import-format") { - if err := tx.SetFlag(cmd.ImportFormatFlag, c.GlobalString("import-format")); err != nil { + if c.IsSet("import-format") { + if err := tx.SetFlag(cmd.ImportFormatFlag, c.String("import-format")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("delimiter") { - if err := tx.SetFlag(cmd.DelimiterFlag, c.GlobalString("delimiter")); err != nil { + if c.IsSet("delimiter") { + if err := tx.SetFlag(cmd.DelimiterFlag, c.String("delimiter")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("allow-uneven-fields") { - _ = tx.SetFlag(cmd.AllowUnevenFieldsFlag, c.GlobalBool("allow-uneven-fields")) + if c.IsSet("allow-uneven-fields") { + _ = tx.SetFlag(cmd.AllowUnevenFieldsFlag, c.Bool("allow-uneven-fields")) } - if c.GlobalIsSet("delimiter-positions") { - if err := tx.SetFlag(cmd.DelimiterPositionsFlag, c.GlobalString("delimiter-positions")); err != nil { + if c.IsSet("delimiter-positions") { + if err := tx.SetFlag(cmd.DelimiterPositionsFlag, c.String("delimiter-positions")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("json-query") { - _ = tx.SetFlag(cmd.JsonQueryFlag, c.GlobalString("json-query")) + if c.IsSet("json-query") { + _ = tx.SetFlag(cmd.JsonQueryFlag, c.String("json-query")) } - if c.GlobalIsSet("encoding") { - if err := tx.SetFlag(cmd.EncodingFlag, c.GlobalString("encoding")); err != nil { + if c.IsSet("encoding") { + if err := tx.SetFlag(cmd.EncodingFlag, c.String("encoding")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("no-header") { - _ = tx.SetFlag(cmd.NoHeaderFlag, c.GlobalBool("no-header")) + if c.IsSet("no-header") { + _ = tx.SetFlag(cmd.NoHeaderFlag, c.Bool("no-header")) } - if c.GlobalIsSet("without-null") { - _ = tx.SetFlag(cmd.WithoutNullFlag, c.GlobalBool("without-null")) + if c.IsSet("without-null") { + _ = tx.SetFlag(cmd.WithoutNullFlag, c.Bool("without-null")) } - if c.GlobalIsSet("strip-ending-line-break") { - _ = tx.SetFlag(cmd.StripEndingLineBreakFlag, c.GlobalBool("strip-ending-line-break")) + if c.IsSet("strip-ending-line-break") { + _ = tx.SetFlag(cmd.StripEndingLineBreakFlag, c.Bool("strip-ending-line-break")) } - if err := tx.SetFormatFlag(c.GlobalString("format"), c.GlobalString("out")); err != nil { + if err := tx.SetFormatFlag(c.String("format"), c.String("out")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } - if c.GlobalIsSet("write-encoding") { - if err := tx.SetFlag(cmd.ExportEncodingFlag, c.GlobalString("write-encoding")); err != nil { + if c.IsSet("write-encoding") { + if err := tx.SetFlag(cmd.ExportEncodingFlag, c.String("write-encoding")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("write-delimiter") { - if err := tx.SetFlag(cmd.ExportDelimiterFlag, c.GlobalString("write-delimiter")); err != nil { + if c.IsSet("write-delimiter") { + if err := tx.SetFlag(cmd.ExportDelimiterFlag, c.String("write-delimiter")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("write-delimiter-positions") { - if err := tx.SetFlag(cmd.ExportDelimiterPositionsFlag, c.GlobalString("write-delimiter-positions")); err != nil { + if c.IsSet("write-delimiter-positions") { + if err := tx.SetFlag(cmd.ExportDelimiterPositionsFlag, c.String("write-delimiter-positions")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("without-header") { - _ = tx.SetFlag(cmd.WithoutHeaderFlag, c.GlobalBool("without-header")) + if c.IsSet("without-header") { + _ = tx.SetFlag(cmd.WithoutHeaderFlag, c.Bool("without-header")) } - if c.GlobalIsSet("line-break") { - if err := tx.SetFlag(cmd.LineBreakFlag, c.GlobalString("line-break")); err != nil { + if c.IsSet("line-break") { + if err := tx.SetFlag(cmd.LineBreakFlag, c.String("line-break")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("enclose-all") { - _ = tx.SetFlag(cmd.EncloseAllFlag, c.GlobalBool("enclose-all")) + if c.IsSet("enclose-all") { + _ = tx.SetFlag(cmd.EncloseAllFlag, c.Bool("enclose-all")) } - if c.GlobalIsSet("json-escape") { - if err := tx.SetFlag(cmd.JsonEscapeFlag, c.GlobalString("json-escape")); err != nil { + if c.IsSet("json-escape") { + if err := tx.SetFlag(cmd.JsonEscapeFlag, c.String("json-escape")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } - if c.GlobalIsSet("pretty-print") { - _ = tx.SetFlag(cmd.PrettyPrintFlag, c.GlobalBool("pretty-print")) + if c.IsSet("pretty-print") { + _ = tx.SetFlag(cmd.PrettyPrintFlag, c.Bool("pretty-print")) } - if c.GlobalIsSet("east-asian-encoding") { - _ = tx.SetFlag(cmd.EastAsianEncodingFlag, c.GlobalBool("east-asian-encoding")) + if c.IsSet("east-asian-encoding") { + _ = tx.SetFlag(cmd.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) } - if c.GlobalIsSet("count-diacritical-sign") { - _ = tx.SetFlag(cmd.CountDiacriticalSignFlag, c.GlobalBool("count-diacritical-sign")) + if c.IsSet("count-diacritical-sign") { + _ = tx.SetFlag(cmd.CountDiacriticalSignFlag, c.Bool("count-diacritical-sign")) } - if c.GlobalIsSet("count-format-code") { - _ = tx.SetFlag(cmd.CountFormatCodeFlag, c.GlobalBool("count-format-code")) + if c.IsSet("count-format-code") { + _ = tx.SetFlag(cmd.CountFormatCodeFlag, c.Bool("count-format-code")) } - if c.GlobalIsSet("quiet") { - _ = tx.SetFlag(cmd.QuietFlag, c.GlobalBool("quiet")) + if c.IsSet("quiet") { + _ = tx.SetFlag(cmd.QuietFlag, c.Bool("quiet")) } - if c.GlobalIsSet("limit-recursion") { - _ = tx.SetFlag(cmd.LimitRecursion, c.GlobalInt64("limit-recursion")) + if c.IsSet("limit-recursion") { + _ = tx.SetFlag(cmd.LimitRecursion, c.Int64("limit-recursion")) } - if c.GlobalIsSet("cpu") { - _ = tx.SetFlag(cmd.CPUFlag, c.GlobalInt64("cpu")) + if c.IsSet("cpu") { + _ = tx.SetFlag(cmd.CPUFlag, c.Int64("cpu")) } - if c.GlobalIsSet("stats") { - _ = tx.SetFlag(cmd.StatsFlag, c.GlobalBool("stats")) + if c.IsSet("stats") { + _ = tx.SetFlag(cmd.StatsFlag, c.Bool("stats")) } return nil @@ -486,11 +518,11 @@ func runPreloadCommands(ctx context.Context, proc *query.Processor) (err error) } func readQuery(ctx context.Context, c *cli.Context, tx *query.Transaction) (queryString string, path string, err error) { - if c.GlobalIsSet("source") && 0 < len(c.GlobalString("source")) { + if c.IsSet("source") && 0 < len(c.String("source")) { if 0 < c.NArg() { err = query.NewIncorrectCommandUsageError("no argument can be passed when \"--source\" option is specified") } else { - path = c.GlobalString("source") + path = c.String("source") queryString, err = query.LoadContentsFromFile(ctx, tx, parser.Identifier{Literal: path}) } } else { @@ -524,5 +556,5 @@ func Exit(err error, tx *query.Transaction) error { code = apperr.Code() } - return cli.NewExitError(message, code) + return cli.Exit(message, code) } From 2634df8c4a6bf96f55184fc6c00a8659793cfadb Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 13:48:20 +0900 Subject: [PATCH 03/17] Add build tags to build flags. --- Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 103b60c..a12018a 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ GOPATH := $(shell pwd)/build BINARY := csvq RELEASE_ARCH := darwin/amd64 darwin/arm64 linux/amd64 linux/386 linux/arm linux/arm64 freebsd/amd64 freebsd/386 freebsd/arm netbsd/amd64 netbsd/386 netbsd/arm openbsd/amd64 openbsd/386 windows/amd64 windows/386 PRERELEASE_ARCH := darwin/amd64 darwin/arm64 linux/amd64 windows/amd64 +BUILD_TAGS := -tags urfave_cli_no_docs ifneq ($(shell command -v git && git remote -v 2>/dev/null | grep mithrandie/csvq.git && echo true),true) VERSION := $(shell git describe --tags --always 2>/dev/null) @@ -19,11 +20,11 @@ $(BINARY): build .PHONY: build build: - go build -trimpath $(LDFLAGS) -o $(GOPATH)/bin/ + go build $(BUILD_TAGS) -trimpath $(LDFLAGS) -o $(GOPATH)/bin/ .PHONY: install install: - go install $(LDFLAGS) + go install $(BUILD_TAGS) -trimpath $(LDFLAGS) .PHONY: clean clean: @@ -35,7 +36,7 @@ build-all: for TARGET in $(RELEASE_ARCH); \ do \ set -- $$TARGET; \ - GOOS=$$1 GOARCH=$$2 go build -trimpath $(LDFLAGS) -o "dist/$(BINARY)-$(VERSION)-$${1}-$${2}/"; \ + GOOS=$$1 GOARCH=$$2 go build $(BUILD_TAGS) -trimpath $(LDFLAGS) -o "dist/$(BINARY)-$(VERSION)-$${1}-$${2}/"; \ done .PHONY: build-pre-release @@ -44,7 +45,7 @@ build-pre-release: for TARGET in $(PRERELEASE_ARCH); \ do \ set -- $$TARGET; \ - GOOS=$$1 GOARCH=$$2 go build -trimpath $(LDFLAGS) -o "dist/$(BINARY)-$(VERSION)-$${1}-$${2}/"; \ + GOOS=$$1 GOARCH=$$2 go build $(BUILD_TAGS) -trimpath $(LDFLAGS) -o "dist/$(BINARY)-$(VERSION)-$${1}-$${2}/"; \ done .PHONY: dist - From b191fba0687592354e865568a762abe5ca92b29c Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 20:20:51 +0900 Subject: [PATCH 04/17] Refactor: Separate terminal-related files from package query into package terminal. --- lib/action/run.go | 5 +- lib/query/built_in_command.go | 14 +- lib/query/built_in_command_test.go | 30 ++-- lib/query/cursor.go | 6 +- lib/query/cursor_test.go | 106 ++++++------ lib/query/eval_test.go | 4 +- lib/query/inline_tables_test.go | 4 +- lib/query/main_test.go | 29 ++-- lib/query/processor.go | 18 +- lib/query/processor_test.go | 24 +-- lib/query/query.go | 22 +-- lib/query/query_test.go | 118 ++++++------- lib/query/reference_scope.go | 158 +++++++++--------- lib/query/reference_scope_test.go | 46 ++--- lib/query/runtime_information.go | 10 +- lib/query/runtime_information_test.go | 8 +- lib/query/transaction.go | 32 ++-- lib/query/transaction_test.go | 14 +- lib/query/user_defined_function.go | 2 +- lib/query/view.go | 20 +-- lib/query/view_test.go | 10 +- lib/query/virtual_terminal.go | 18 ++ lib/{query => terminal}/completer_readline.go | 93 ++++++----- .../completer_readline_test.go | 109 ++++++------ lib/terminal/main_test.go | 118 +++++++++++++ lib/{query => terminal}/terminal.go | 38 ++--- lib/{query => terminal}/terminal_functions.go | 5 +- .../terminal_functions_windows.go | 2 +- lib/{query => terminal}/terminal_general.go | 17 +- lib/{query => terminal}/terminal_readline.go | 7 +- .../terminal_readline_test.go | 2 +- lib/{query => terminal}/terminal_test.go | 17 +- 32 files changed, 616 insertions(+), 490 deletions(-) create mode 100644 lib/query/virtual_terminal.go rename lib/{query => terminal}/completer_readline.go (96%) rename lib/{query => terminal}/completer_readline_test.go (97%) create mode 100644 lib/terminal/main_test.go rename lib/{query => terminal}/terminal.go (82%) rename lib/{query => terminal}/terminal_functions.go (66%) rename lib/{query => terminal}/terminal_functions_windows.go (89%) rename lib/{query => terminal}/terminal_general.go (86%) rename lib/{query => terminal}/terminal_readline.go (95%) rename lib/{query => terminal}/terminal_readline_test.go (98%) rename lib/{query => terminal}/terminal_test.go (95%) diff --git a/lib/action/run.go b/lib/action/run.go index 26de06d..d6c9f7f 100644 --- a/lib/action/run.go +++ b/lib/action/run.go @@ -14,6 +14,7 @@ import ( csvqfile "github.com/mithrandie/csvq/lib/file" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" + "github.com/mithrandie/csvq/lib/terminal" "github.com/mithrandie/go-file/v2" ) @@ -65,11 +66,11 @@ func LaunchInteractiveShell(ctx context.Context, proc *query.Processor) error { return query.NewIncorrectCommandUsageError("input from pipe or redirection cannot be used in interactive shell") } - if err := proc.Tx.Session.SetStdin(query.GetStdinForREPL()); err != nil { + if err := proc.Tx.Session.SetStdin(terminal.GetStdinForREPL()); err != nil { return query.NewIOError(nil, err.Error()) } - term, err := query.NewTerminal(ctx, proc.ReferenceScope) + term, err := terminal.NewTerminal(ctx, proc.ReferenceScope) if err != nil { return query.ConvertLoadConfigurationError(err) } diff --git a/lib/query/built_in_command.go b/lib/query/built_in_command.go index 1d8188b..1809e9c 100644 --- a/lib/query/built_in_command.go +++ b/lib/query/built_in_command.go @@ -471,15 +471,15 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) switch strings.ToUpper(expr.Type.Literal) { case ShowTables: - keys := scope.Tx.cachedViews.SortedKeys() + keys := scope.Tx.CachedViews.SortedKeys() if len(keys) < 1 { s = scope.Tx.Warn("No table is loaded") } else { - createdFiles, updatedFiles := scope.Tx.uncommittedViews.UncommittedFiles() + createdFiles, updatedFiles := scope.Tx.UncommittedViews.UncommittedFiles() for _, key := range keys { - if view, ok := scope.Tx.cachedViews.Load(key); ok { + if view, ok := scope.Tx.CachedViews.Load(key); ok { fields := view.Header.TableColumnNames() info := view.FileInfo ufpath := strings.ToUpper(info.Path) @@ -516,7 +516,7 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) } else { keys := views.SortedKeys() - updatedViews := scope.Tx.uncommittedViews.UncommittedTempViews() + updatedViews := scope.Tx.UncommittedViews.UncommittedTempViews() for _, key := range keys { if view, ok := views.Load(key); ok { @@ -554,7 +554,7 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) if cur, ok := cursors.Load(key); ok { isOpen := cur.IsOpen() - w.WriteColor(cur.name, cmd.ObjectEffect) + w.WriteColor(cur.Name, cmd.ObjectEffect) w.BeginBlock() w.NewLine() @@ -874,14 +874,14 @@ func ShowFields(ctx context.Context, scope *ReferenceScope, expr parser.ShowFiel } if !view.FileInfo.IsFile() { - updatedViews := scope.Tx.uncommittedViews.UncommittedTempViews() + updatedViews := scope.Tx.UncommittedViews.UncommittedTempViews() ufpath := strings.ToUpper(view.FileInfo.Path) if _, ok := updatedViews[ufpath]; ok { status = ObjectUpdated } } else { - createdViews, updatedView := scope.Tx.uncommittedViews.UncommittedFiles() + createdViews, updatedView := scope.Tx.UncommittedViews.UncommittedFiles() ufpath := strings.ToUpper(view.FileInfo.Path) if _, ok := createdViews[ufpath]; ok { diff --git a/lib/query/built_in_command_test.go b/lib/query/built_in_command_test.go index 40333f5..65b9dd2 100644 --- a/lib/query/built_in_command_test.go +++ b/lib/query/built_in_command_test.go @@ -2017,11 +2017,11 @@ var showObjectsTests = []struct { { scopeNameCursors: { "CUR": &Cursor{ - name: "cur", + Name: "cur", query: selectQueryForCursorTest, }, "CUR2": &Cursor{ - name: "cur2", + Name: "cur2", query: selectQueryForCursorTest, view: &View{ RecordSet: RecordSet{ @@ -2039,7 +2039,7 @@ var showObjectsTests = []struct { index: -1, }, "CUR3": &Cursor{ - name: "cur3", + Name: "cur3", query: selectQueryForCursorTest, view: &View{ RecordSet: RecordSet{ @@ -2057,7 +2057,7 @@ var showObjectsTests = []struct { index: 1, }, "CUR4": &Cursor{ - name: "cur4", + Name: "cur4", query: selectQueryForCursorTest, view: &View{ RecordSet: RecordSet{ @@ -2075,7 +2075,7 @@ var showObjectsTests = []struct { index: 2, }, "CUR5": &Cursor{ - name: "stmtcur", + Name: "stmtcur", statement: parser.Identifier{Literal: "stmt"}, }, }, @@ -2305,7 +2305,7 @@ var showObjectsTests = []struct { func TestShowObjects(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - TestTx.uncommittedViews.Clean() + TestTx.UncommittedViews.Clean() TestTx.PreparedStatements = NewPreparedStatementMap() initFlag(TestTx.Flags) }() @@ -2330,14 +2330,14 @@ func TestShowObjects(t *testing.T) { TestTx.Flags.ExportOptions.DelimiterPositions = v.WriteDelimiterPositions TestTx.Flags.ExportOptions.SingleLine = v.WriteAsSingleLine TestTx.Flags.ExportOptions.Format = v.Format - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) if v.ViewCache.SyncMap != nil { - TestTx.cachedViews = v.ViewCache + TestTx.CachedViews = v.ViewCache } if v.UncommittedViews.mtx == nil { - TestTx.uncommittedViews = NewUncommittedViews() + TestTx.UncommittedViews = NewUncommittedViews() } else { - TestTx.uncommittedViews = v.UncommittedViews + TestTx.UncommittedViews = v.UncommittedViews } TestTx.PreparedStatements = NewPreparedStatementMap() if v.PreparedStatements.SyncMap != nil { @@ -2644,7 +2644,7 @@ func calcShowRuninfoWidth(wd string) int { func TestShowFields(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - TestTx.uncommittedViews.Clean() + TestTx.UncommittedViews.Clean() initFlag(TestTx.Flags) }() @@ -2653,14 +2653,14 @@ func TestShowFields(t *testing.T) { ctx := context.Background() for _, v := range showFieldsTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) if v.ViewCache.SyncMap != nil { - TestTx.cachedViews = v.ViewCache + TestTx.CachedViews = v.ViewCache } if v.UncommittedViews.mtx == nil { - TestTx.uncommittedViews = NewUncommittedViews() + TestTx.UncommittedViews = NewUncommittedViews() } else { - TestTx.uncommittedViews = v.UncommittedViews + TestTx.UncommittedViews = v.UncommittedViews } if v.Scope == nil { diff --git a/lib/query/cursor.go b/lib/query/cursor.go index d84a252..85d4159 100644 --- a/lib/query/cursor.go +++ b/lib/query/cursor.go @@ -131,7 +131,7 @@ func (m CursorMap) Count(name parser.Identifier) (int, error) { } type Cursor struct { - name string + Name string query parser.SelectQuery statement parser.Identifier view *View @@ -145,7 +145,7 @@ type Cursor struct { func NewCursor(e parser.CursorDeclaration) *Cursor { return &Cursor{ - name: e.Cursor.Literal, + Name: e.Cursor.Literal, query: e.Query, statement: e.Statement, mtx: &sync.Mutex{}, @@ -164,7 +164,7 @@ func NewPseudoCursor(name string, values []value.Primary) *Cursor { view.RecordSet = records return &Cursor{ - name: name, + Name: name, view: view, index: -1, fetched: false, diff --git a/lib/query/cursor_test.go b/lib/query/cursor_test.go index 3980005..2ec429e 100644 --- a/lib/query/cursor_test.go +++ b/lib/query/cursor_test.go @@ -60,7 +60,7 @@ var cursorMapDeclareTests = []struct { }, Result: GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, @@ -74,12 +74,12 @@ var cursorMapDeclareTests = []struct { }, Result: GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "stmtcur", + Name: "stmtcur", statement: parser.Identifier{Literal: "stmt"}, mtx: &sync.Mutex{}, }, @@ -134,7 +134,7 @@ var cursorMapAddPseudoCursorTests = []struct { }, Result: GenerateCursorMap([]*Cursor{ { - name: "pcur", + Name: "pcur", view: &View{ Header: NewHeader("", []string{"c1"}), RecordSet: RecordSet{ @@ -189,7 +189,7 @@ var cursorMapDisposeTests = []struct { CurName: parser.Identifier{Literal: "cur"}, Result: GenerateCursorMap([]*Cursor{ { - name: "pcur", + Name: "pcur", view: &View{ Header: NewHeader("", []string{"c1"}), RecordSet: RecordSet{ @@ -218,7 +218,7 @@ var cursorMapDisposeTests = []struct { func TestCursorMap_Dispose(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, @@ -263,7 +263,7 @@ var cursorMapOpenTests = []struct { CurName: parser.Identifier{Literal: "cur"}, Result: GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, view: &View{ Header: NewHeader("table1", []string{"column1", "column2"}), @@ -293,12 +293,12 @@ var cursorMapOpenTests = []struct { mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorQueryErrorTest, mtx: &sync.Mutex{}, }, { - name: "pcur", + Name: "pcur", view: &View{ Header: NewHeader("", []string{"c1"}), RecordSet: RecordSet{ @@ -311,22 +311,22 @@ var cursorMapOpenTests = []struct { mtx: &sync.Mutex{}, }, { - name: "stmt", + Name: "stmt", statement: parser.Identifier{Literal: "stmt"}, mtx: &sync.Mutex{}, }, { - name: "not_exist_stmt", + Name: "not_exist_stmt", statement: parser.Identifier{Literal: "not_exist_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt", + Name: "invalid_stmt", statement: parser.Identifier{Literal: "invalid_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt2", + Name: "invalid_stmt2", statement: parser.Identifier{Literal: "invalid_stmt2"}, mtx: &sync.Mutex{}, }, @@ -340,7 +340,7 @@ var cursorMapOpenTests = []struct { }, Result: GenerateCursorMap([]*Cursor{ { - name: "stmt", + Name: "stmt", statement: parser.Identifier{Literal: "stmt"}, view: &View{ Header: NewHeader("table1", []string{"column1", "column2"}), @@ -362,7 +362,7 @@ var cursorMapOpenTests = []struct { mtx: &sync.Mutex{}, }, { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, view: &View{ Header: NewHeader("table1", []string{"column1", "column2"}), @@ -392,12 +392,12 @@ var cursorMapOpenTests = []struct { mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorQueryErrorTest, mtx: &sync.Mutex{}, }, { - name: "pcur", + Name: "pcur", view: &View{ Header: NewHeader("", []string{"c1"}), RecordSet: RecordSet{ @@ -410,17 +410,17 @@ var cursorMapOpenTests = []struct { mtx: &sync.Mutex{}, }, { - name: "not_exist_stmt", + Name: "not_exist_stmt", statement: parser.Identifier{Literal: "not_exist_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt", + Name: "invalid_stmt", statement: parser.Identifier{Literal: "invalid_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt2", + Name: "invalid_stmt2", statement: parser.Identifier{Literal: "invalid_stmt2"}, mtx: &sync.Mutex{}, }, @@ -466,7 +466,7 @@ var cursorMapOpenTests = []struct { func TestCursorMap_Open(t *testing.T) { defer func() { TestTx.PreparedStatements = NewPreparedStatementMap() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -485,39 +485,39 @@ func TestCursorMap_Open(t *testing.T) { Statement: value.NewString("select 1; insert into table1 values (?, ?);"), }) - scope.blocks[0].cursors = GenerateCursorMap([]*Cursor{ + scope.Blocks[0].Cursors = GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorQueryErrorTest, mtx: &sync.Mutex{}, }, { - name: "stmt", + Name: "stmt", statement: parser.Identifier{Literal: "stmt"}, mtx: &sync.Mutex{}, }, { - name: "not_exist_stmt", + Name: "not_exist_stmt", statement: parser.Identifier{Literal: "not_exist_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt", + Name: "invalid_stmt", statement: parser.Identifier{Literal: "invalid_stmt"}, mtx: &sync.Mutex{}, }, { - name: "invalid_stmt2", + Name: "invalid_stmt2", statement: parser.Identifier{Literal: "invalid_stmt2"}, mtx: &sync.Mutex{}, }, }) - _ = scope.blocks[0].cursors.AddPseudoCursor( + _ = scope.Blocks[0].Cursors.AddPseudoCursor( parser.Identifier{Literal: "pcur"}, []value.Primary{ value.NewInteger(1), @@ -527,8 +527,8 @@ func TestCursorMap_Open(t *testing.T) { ctx := context.Background() for _, v := range cursorMapOpenTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) - err := scope.blocks[0].cursors.Open(ctx, scope, v.CurName, v.CurValues) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) + err := scope.Blocks[0].Cursors.Open(ctx, scope, v.CurName, v.CurValues) if err != nil { if len(v.Error) < 1 { t.Errorf("%s: unexpected error %q", v.Name, err) @@ -541,8 +541,8 @@ func TestCursorMap_Open(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !SyncMapEqual(scope.blocks[0].cursors, v.Result) { - t.Errorf("%s: result = %v, want %v", v.Name, scope.blocks[0].cursors, v.Result) + if !SyncMapEqual(scope.Blocks[0].Cursors, v.Result) { + t.Errorf("%s: result = %v, want %v", v.Name, scope.Blocks[0].Cursors, v.Result) } } } @@ -558,12 +558,12 @@ var cursorMapCloseTests = []struct { CurName: parser.Identifier{Literal: "cur"}, Result: GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "pcur", + Name: "pcur", view: &View{ Header: NewHeader("", []string{"c1"}), RecordSet: RecordSet{ @@ -591,7 +591,7 @@ var cursorMapCloseTests = []struct { func TestCursorMap_Close(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -599,7 +599,7 @@ func TestCursorMap_Close(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, @@ -753,7 +753,7 @@ var cursorMapFetchTests = []struct { func TestCursorMap_Fetch(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -761,12 +761,12 @@ func TestCursorMap_Fetch(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, @@ -820,7 +820,7 @@ var cursorMapIsOpenTests = []struct { func TestCursorMap_IsOpen(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -828,12 +828,12 @@ func TestCursorMap_IsOpen(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, @@ -900,7 +900,7 @@ var cursorMapIsInRangeTests = []struct { func TestCursorMap_IsInRange(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -908,26 +908,26 @@ func TestCursorMap_IsInRange(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur3", + Name: "cur3", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, }) scope := NewReferenceScope(TestTx) ctx := context.Background() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = cursors.Open(ctx, scope, parser.Identifier{Literal: "cur"}, nil) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = cursors.Open(ctx, scope, parser.Identifier{Literal: "cur2"}, nil) _, _ = cursors.Fetch(parser.Identifier{Literal: "cur2"}, parser.NEXT, 0) @@ -980,7 +980,7 @@ var cursorMapCountTests = []struct { func TestCursorMap_Count(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -988,17 +988,17 @@ func TestCursorMap_Count(t *testing.T) { cursors := GenerateCursorMap([]*Cursor{ { - name: "cur", + Name: "cur", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, { - name: "cur2", + Name: "cur2", query: selectQueryForCursorTest, mtx: &sync.Mutex{}, }, }) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) scope := NewReferenceScope(TestTx) ctx := context.Background() _ = cursors.Open(ctx, scope, parser.Identifier{Literal: "cur"}, nil) diff --git a/lib/query/eval_test.go b/lib/query/eval_test.go index 9ef65c0..0ab653c 100644 --- a/lib/query/eval_test.go +++ b/lib/query/eval_test.go @@ -4144,7 +4144,7 @@ var evaluateTests = []struct { func TestEvaluate(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -4165,7 +4165,7 @@ func TestEvaluate(t *testing.T) { _, _ = scope.FetchCursor(parser.Identifier{Literal: "cur"}, parser.NEXT, 0) for _, v := range evaluateTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) if v.Scope == nil { v.Scope = scope diff --git a/lib/query/inline_tables_test.go b/lib/query/inline_tables_test.go index 010ae51..7eddbbe 100644 --- a/lib/query/inline_tables_test.go +++ b/lib/query/inline_tables_test.go @@ -261,7 +261,7 @@ var inlineTableMapSetTests = []struct { func TestInlineTableMap_Set(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -272,7 +272,7 @@ func TestInlineTableMap_Set(t *testing.T) { scope := NewReferenceScope(TestTx) ctx := context.Background() for _, v := range inlineTableMapSetTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) err := it.Set(ctx, scope, v.Expr) if err != nil { if len(v.Error) < 1 { diff --git a/lib/query/main_test.go b/lib/query/main_test.go index 9234d44..b64b361 100644 --- a/lib/query/main_test.go +++ b/lib/query/main_test.go @@ -13,8 +13,6 @@ import ( "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" "github.com/mithrandie/csvq/lib/value" - - "github.com/mitchellh/go-homedir" ) type syncMapStruct interface { @@ -44,16 +42,16 @@ func BlockScopeListEqual(s1 []BlockScope, s2 []BlockScope) bool { return false } for i := range s1 { - if !SyncMapEqual(s1[i].variables, s2[i].variables) { + if !SyncMapEqual(s1[i].Variables, s2[i].Variables) { return false } - if !SyncMapEqual(s1[i].temporaryTables, s2[i].temporaryTables) { + if !SyncMapEqual(s1[i].TemporaryTables, s2[i].TemporaryTables) { return false } - if !SyncMapEqual(s1[i].cursors, s2[i].cursors) { + if !SyncMapEqual(s1[i].Cursors, s2[i].Cursors) { return false } - if !reflect.DeepEqual(s1[i].functions, s2[i].functions) { + if !reflect.DeepEqual(s1[i].Functions, s2[i].Functions) { return false } } @@ -86,7 +84,6 @@ var CompletionTestDir = filepath.Join(TestDir, "completion") var CompletionTestSubDir = filepath.Join(TestDir, "completion", "sub") var TestLocation = "UTC" var NowForTest = time.Date(2012, 2, 3, 9, 18, 15, 0, GetTestLocation()) -var HomeDir string var TestTx, _ = NewTransaction(context.Background(), file.DefaultWaitTimeout, file.DefaultRetryDelay, NewSession()) @@ -115,6 +112,9 @@ func setup() { if _, err := os.Stat(TestDir); err == nil { _ = os.RemoveAll(TestDir) } + if _, err := os.Stat(TestDir); os.IsNotExist(err) { + _ = os.Mkdir(TestDir, 0755) + } cmd.TestTime = NowForTest @@ -123,10 +123,6 @@ func setup() { r, _ := os.Open(filepath.Join(TestDataDir, "empty.txt")) os.Stdin = r - if _, err := os.Stat(TestDir); os.IsNotExist(err) { - _ = os.Mkdir(TestDir, 0755) - } - _ = copyfile(filepath.Join(TestDir, "table_sjis.csv"), filepath.Join(TestDataDir, "table_sjis.csv")) _ = copyfile(filepath.Join(TestDir, "table_noheader.csv"), filepath.Join(TestDataDir, "table_noheader.csv")) _ = copyfile(filepath.Join(TestDir, "table_broken.csv"), filepath.Join(TestDataDir, "table_broken.csv")) @@ -181,7 +177,6 @@ func setup() { _ = copyfile(filepath.Join(CompletionTestSubDir, "table2.csv"), filepath.Join(TestDataDir, "table2.csv")) Version = "v1.0.0" - HomeDir, _ = homedir.Dir() TestTx.Session.SetStdout(NewDiscard()) TestTx.Session.SetStderr(NewDiscard()) initFlag(TestTx.Flags) @@ -255,13 +250,13 @@ func GenerateReferenceScope(blocks []map[string]map[string]interface{}, nodes [] for k, v := range blocks[i][n] { switch n { case scopeNameVariables: - rs.blocks[i].variables.Store(k, v.(value.Primary)) + rs.Blocks[i].Variables.Store(k, v.(value.Primary)) case scopeNameTempTables: - rs.blocks[i].temporaryTables.Store(k, v.(*View)) + rs.Blocks[i].TemporaryTables.Store(k, v.(*View)) case scopeNameCursors: - rs.blocks[i].cursors.Store(k, v.(*Cursor)) + rs.Blocks[i].Cursors.Store(k, v.(*Cursor)) case scopeNameFunctions: - rs.blocks[i].functions.Store(k, v.(*UserDefinedFunction)) + rs.Blocks[i].Functions.Store(k, v.(*UserDefinedFunction)) } } } @@ -307,7 +302,7 @@ func GenerateViewMap(values []*View) ViewMap { func GenerateCursorMap(values []*Cursor) CursorMap { m := NewCursorMap() for _, v := range values { - m.Store(v.name, v) + m.Store(v.Name, v) } return m } diff --git a/lib/query/processor.go b/lib/query/processor.go index d8ff773..c8b3495 100644 --- a/lib/query/processor.go +++ b/lib/query/processor.go @@ -242,7 +242,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme fileInfo, cnt, e := Insert(ctx, proc.ReferenceScope, stmt.(parser.InsertQuery)) if e == nil { if 0 < cnt { - proc.Tx.uncommittedViews.SetForUpdatedView(fileInfo) + proc.Tx.UncommittedViews.SetForUpdatedView(fileInfo) } proc.Log(fmt.Sprintf("%s inserted on %q.", FormatCount(cnt, "record"), fileInfo.Path), proc.Tx.Flags.Quiet) if proc.storeResults { @@ -265,7 +265,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme cntTotal := 0 for i, info := range infos { if 0 < cnts[i] { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) cntTotal += cnts[i] } proc.Log(fmt.Sprintf("%s updated on %q.", FormatCount(cnts[i], "record"), info.Path), proc.Tx.Flags.Quiet) @@ -288,7 +288,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme fileInfo, cnt, e := Replace(ctx, proc.ReferenceScope, stmt.(parser.ReplaceQuery)) if e == nil { if 0 < cnt { - proc.Tx.uncommittedViews.SetForUpdatedView(fileInfo) + proc.Tx.UncommittedViews.SetForUpdatedView(fileInfo) } proc.Log(fmt.Sprintf("%s replaced on %q.", FormatCount(cnt, "record"), fileInfo.Path), proc.Tx.Flags.Quiet) if proc.storeResults { @@ -311,7 +311,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme cntTotal := 0 for i, info := range infos { if 0 < cnts[i] { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) cntTotal += cnts[i] } proc.Log(fmt.Sprintf("%s deleted on %q.", FormatCount(cnts[i], "record"), info.Path), proc.Tx.Flags.Quiet) @@ -330,7 +330,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme createTableStatement := stmt.(parser.CreateTable) info, e := CreateTable(ctx, proc.ReferenceScope, createTableStatement) if e == nil { - proc.Tx.uncommittedViews.SetForCreatedView(info) + proc.Tx.UncommittedViews.SetForCreatedView(info) proc.Log(fmt.Sprintf("file %q is created.", info.Path), proc.Tx.Flags.Quiet) } else if _, ok := e.(*FileAlreadyExistError); ok && createTableStatement.IfNotExists { e := func() error { @@ -380,7 +380,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme case parser.AddColumns: info, cnt, e := AddColumns(ctx, proc.ReferenceScope, stmt.(parser.AddColumns)) if e == nil { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) proc.Log(fmt.Sprintf("%s added on %q.", FormatCount(cnt, "field"), info.Path), proc.Tx.Flags.Quiet) } else { err = e @@ -388,7 +388,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme case parser.DropColumns: info, cnt, e := DropColumns(ctx, proc.ReferenceScope, stmt.(parser.DropColumns)) if e == nil { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) proc.Log(fmt.Sprintf("%s dropped on %q.", FormatCount(cnt, "field"), info.Path), proc.Tx.Flags.Quiet) } else { err = e @@ -396,7 +396,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme case parser.RenameColumn: info, e := RenameColumn(ctx, proc.ReferenceScope, stmt.(parser.RenameColumn)) if e == nil { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) proc.Log(fmt.Sprintf("%s renamed on %q.", FormatCount(1, "field"), info.Path), proc.Tx.Flags.Quiet) } else { err = e @@ -405,7 +405,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme expr := stmt.(parser.SetTableAttribute) info, log, e := SetTableAttribute(ctx, proc.ReferenceScope, expr) if e == nil { - proc.Tx.uncommittedViews.SetForUpdatedView(info) + proc.Tx.UncommittedViews.SetForUpdatedView(info) proc.Log(log, proc.Tx.Flags.Quiet) } else { if unchanged, ok := e.(*TableAttributeUnchangedError); ok { diff --git a/lib/query/processor_test.go b/lib/query/processor_test.go index 7fd6c7a..863506b 100644 --- a/lib/query/processor_test.go +++ b/lib/query/processor_test.go @@ -1088,7 +1088,7 @@ var processorExecuteStatementTests = []struct { func TestProcessor_ExecuteStatement(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - TestTx.uncommittedViews.Clean() + TestTx.UncommittedViews.Clean() TestTx.Session.SetStdout(NewDiscard()) initFlag(TestTx.Flags) }() @@ -1103,7 +1103,7 @@ func TestProcessor_ExecuteStatement(t *testing.T) { for _, v := range processorExecuteStatementTests { _ = TestTx.ReleaseResources() - TestTx.uncommittedViews = NewUncommittedViews() + TestTx.UncommittedViews = NewUncommittedViews() out := NewOutput() tx.Session.SetStdout(out) @@ -1132,7 +1132,7 @@ func TestProcessor_ExecuteStatement(t *testing.T) { } if v.UncommittedViews.mtx != nil { - for _, r := range TestTx.uncommittedViews.Created { + for _, r := range TestTx.UncommittedViews.Created { if r.Handler != nil { if r.Path != r.Handler.Path() { t.Errorf("file pointer = %q, want %q for %q", r.Handler.Path(), r.Path, v.Input) @@ -1141,7 +1141,7 @@ func TestProcessor_ExecuteStatement(t *testing.T) { r.Handler = nil } } - for _, r := range TestTx.uncommittedViews.Updated { + for _, r := range TestTx.UncommittedViews.Updated { if r.Handler != nil { if r.Path != r.Handler.Path() { t.Errorf("file pointer = %q, want %q for %q", r.Handler.Path(), r.Path, v.Input) @@ -1151,8 +1151,8 @@ func TestProcessor_ExecuteStatement(t *testing.T) { } } - if !reflect.DeepEqual(TestTx.uncommittedViews, v.UncommittedViews) { - t.Errorf("uncomitted views = %v, want %v for %q", TestTx.uncommittedViews, v.UncommittedViews, v.Input) + if !reflect.DeepEqual(TestTx.UncommittedViews, v.UncommittedViews) { + t.Errorf("uncomitted views = %v, want %v for %q", TestTx.UncommittedViews, v.UncommittedViews, v.Input) } } if 0 < len(v.Logs) { @@ -1741,15 +1741,15 @@ func TestProcessor_While(t *testing.T) { for _, v := range processorWhileTests { proc.returnVal = nil - if _, ok := proc.ReferenceScope.CurrentBlock().variables.Get(parser.Variable{Name: "while_test"}); !ok { + if _, ok := proc.ReferenceScope.CurrentBlock().Variables.Get(parser.Variable{Name: "while_test"}); !ok { _ = proc.ReferenceScope.DeclareVariableDirectly(parser.Variable{Name: "while_test"}, value.NewInteger(0)) } - _ = proc.ReferenceScope.CurrentBlock().variables.Set(parser.Variable{Name: "while_test"}, value.NewInteger(0)) + _ = proc.ReferenceScope.CurrentBlock().Variables.Set(parser.Variable{Name: "while_test"}, value.NewInteger(0)) - if _, ok := proc.ReferenceScope.CurrentBlock().variables.Get(parser.Variable{Name: "while_test_count"}); !ok { + if _, ok := proc.ReferenceScope.CurrentBlock().Variables.Get(parser.Variable{Name: "while_test_count"}); !ok { _ = proc.ReferenceScope.DeclareVariableDirectly(parser.Variable{Name: "while_test_count"}, value.NewInteger(0)) } - _ = proc.ReferenceScope.CurrentBlock().variables.Set(parser.Variable{Name: "while_test_count"}, value.NewInteger(0)) + _ = proc.ReferenceScope.CurrentBlock().Variables.Set(parser.Variable{Name: "while_test_count"}, value.NewInteger(0)) out := NewOutput() tx.Session.SetStdout(out) @@ -1960,7 +1960,7 @@ var processorWhileInCursorTests = []struct { func TestProcessor_WhileInCursor(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) TestTx.Session.SetStdout(NewDiscard()) initFlag(TestTx.Flags) }() @@ -1986,7 +1986,7 @@ func TestProcessor_WhileInCursor(t *testing.T) { }, }, }, nil, time.Time{}, nil) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = proc.ReferenceScope.OpenCursor(ctx, parser.Identifier{Literal: "cur"}, nil) out := NewOutput() diff --git a/lib/query/query.go b/lib/query/query.go index 138f7a1..4f14ed4 100644 --- a/lib/query/query.go +++ b/lib/query/query.go @@ -392,7 +392,7 @@ func Insert(ctx context.Context, scope *ReferenceScope, query parser.InsertQuery if !view.FileInfo.IsFile() { scope.ReplaceTemporaryTable(view) } else { - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) } return view.FileInfo, insertRecords, err @@ -440,7 +440,7 @@ func Update(ctx context.Context, scope *ReferenceScope, query parser.UpdateQuery if queryScope.TemporaryTableExists(fpath) { viewsToUpdate[viewKey], _ = queryScope.GetTemporaryTable(parser.Identifier{Literal: fpath}) } else { - viewsToUpdate[viewKey], _ = queryScope.Tx.cachedViews.Get(parser.Identifier{Literal: fpath}) + viewsToUpdate[viewKey], _ = queryScope.Tx.CachedViews.Get(parser.Identifier{Literal: fpath}) } if err = viewsToUpdate[viewKey].Header.Update(tableName.Literal, nil); err != nil { return nil, nil, err @@ -509,7 +509,7 @@ func Update(ctx context.Context, scope *ReferenceScope, query parser.UpdateQuery if !v.FileInfo.IsFile() { scope.ReplaceTemporaryTable(v) } else { - scope.Tx.cachedViews.Set(v) + scope.Tx.CachedViews.Set(v) } fileInfos = append(fileInfos, v.FileInfo) @@ -565,7 +565,7 @@ func Replace(ctx context.Context, scope *ReferenceScope, query parser.ReplaceQue if !view.FileInfo.IsFile() { scope.ReplaceTemporaryTable(view) } else { - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) } return view.FileInfo, replaceRecords, err @@ -623,7 +623,7 @@ func Delete(ctx context.Context, scope *ReferenceScope, query parser.DeleteQuery if queryScope.TemporaryTableExists(fpath) { viewsToDelete[viewKey], _ = queryScope.GetTemporaryTable(parser.Identifier{Literal: fpath}) } else { - viewsToDelete[viewKey], _ = queryScope.Tx.cachedViews.Get(parser.Identifier{Literal: fpath}) + viewsToDelete[viewKey], _ = queryScope.Tx.CachedViews.Get(parser.Identifier{Literal: fpath}) } if err = viewsToDelete[viewKey].Header.Update(tableName.Literal, nil); err != nil { return nil, nil, err @@ -669,7 +669,7 @@ func Delete(ctx context.Context, scope *ReferenceScope, query parser.DeleteQuery if !v.FileInfo.IsFile() { scope.ReplaceTemporaryTable(v) } else { - scope.Tx.cachedViews.Set(v) + scope.Tx.CachedViews.Set(v) } fileInfos = append(fileInfos, v.FileInfo) @@ -737,7 +737,7 @@ func CreateTable(ctx context.Context, scope *ReferenceScope, query parser.Create view.FileInfo = fileInfo - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) return view.FileInfo, nil } @@ -855,7 +855,7 @@ func AddColumns(ctx context.Context, scope *ReferenceScope, query parser.AddColu if !view.FileInfo.IsFile() { scope.ReplaceTemporaryTable(view) } else { - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) } return view.FileInfo, len(fields), err @@ -898,7 +898,7 @@ func DropColumns(ctx context.Context, scope *ReferenceScope, query parser.DropCo if !view.FileInfo.IsFile() { scope.ReplaceTemporaryTable(view) } else { - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) } return view.FileInfo, dropIndices.Len(), err @@ -936,7 +936,7 @@ func RenameColumn(ctx context.Context, scope *ReferenceScope, query parser.Renam if !view.FileInfo.IsFile() { scope.ReplaceTemporaryTable(view) } else { - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) } return view.FileInfo, err @@ -1034,6 +1034,6 @@ func SetTableAttribute(ctx context.Context, scope *ReferenceScope, query parser. w.Title2Effect = cmd.IdentifierEffect log = "\n" + w.String() + "\n" - scope.Tx.cachedViews.Set(view) + scope.Tx.CachedViews.Set(view) return view.FileInfo, log, err } diff --git a/lib/query/query_test.go b/lib/query/query_test.go index 5d0b1d1..350711f 100644 --- a/lib/query/query_test.go +++ b/lib/query/query_test.go @@ -170,7 +170,7 @@ var fetchCursorTests = []struct { func TestFetchCursor(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -196,9 +196,9 @@ func TestFetchCursor(t *testing.T) { }, nil, time.Time{}, nil) ctx := context.Background() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = scope.OpenCursor(ctx, parser.Identifier{Literal: "cur"}, nil) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = scope.OpenCursor(ctx, parser.Identifier{Literal: "cur2"}, nil) for _, v := range fetchCursorTests { @@ -219,8 +219,8 @@ func TestFetchCursor(t *testing.T) { t.Errorf("%s: success = %t, want %t", v.Name, success, v.Success) } - if !SyncMapEqual(scope.blocks[0].variables, v.ResultScopes.blocks[0].variables) { - t.Errorf("%s: variables = %v, want %v", v.Name, scope.blocks, v.ResultScopes.blocks) + if !SyncMapEqual(scope.Blocks[0].Variables, v.ResultScopes.Blocks[0].Variables) { + t.Errorf("%s: variables = %v, want %v", v.Name, scope.Blocks, v.ResultScopes.Blocks) } } } @@ -396,9 +396,9 @@ func TestDeclareView(t *testing.T) { for _, v := range declareViewTests { if v.ViewMap.SyncMap == nil { - scope.blocks[0].temporaryTables = NewViewMap() + scope.Blocks[0].TemporaryTables = NewViewMap() } else { - scope.blocks[0].temporaryTables = v.ViewMap + scope.Blocks[0].TemporaryTables = v.ViewMap } err := DeclareView(ctx, scope, v.Expr) @@ -414,8 +414,8 @@ func TestDeclareView(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.Result) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.Result) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.Result) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.Result) } } } @@ -1389,7 +1389,7 @@ var selectTests = []struct { func TestSelect(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -1403,7 +1403,7 @@ func TestSelect(t *testing.T) { }}) for _, v := range selectTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) result, err := Select(ctx, scope, v.Query) if err != nil { if len(v.Error) < 1 { @@ -1757,7 +1757,7 @@ var insertTests = []struct { func TestInsert(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -1806,7 +1806,7 @@ func TestInsert(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -1827,13 +1827,13 @@ func TestInsert(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -2232,7 +2232,7 @@ var updateTests = []struct { func TestUpdate(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -2281,7 +2281,7 @@ func TestUpdate(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -2302,13 +2302,13 @@ func TestUpdate(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -2652,7 +2652,7 @@ var replaceTests = []struct { func TestReplace(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -2701,7 +2701,7 @@ func TestReplace(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -2722,13 +2722,13 @@ func TestReplace(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -3020,7 +3020,7 @@ var deleteTests = []struct { func TestDelete(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -3069,7 +3069,7 @@ func TestDelete(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -3090,13 +3090,13 @@ func TestDelete(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -3277,7 +3277,7 @@ var createTableTests = []struct { func TestCreateTable(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -3295,7 +3295,7 @@ func TestCreateTable(t *testing.T) { _ = TestTx.FileContainer.Close(result.Handler) result.Handler = nil } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo != nil { _ = TestTx.FileContainer.Close(view.FileInfo.Handler) @@ -3322,8 +3322,8 @@ func TestCreateTable(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } } @@ -3697,7 +3697,7 @@ var addColumnsTests = []struct { func TestAddColumns(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -3746,7 +3746,7 @@ func TestAddColumns(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -3767,13 +3767,13 @@ func TestAddColumns(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -3892,7 +3892,7 @@ var dropColumnsTests = []struct { func TestDropColumns(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -3941,7 +3941,7 @@ func TestDropColumns(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -3962,13 +3962,13 @@ func TestDropColumns(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -4094,7 +4094,7 @@ var renameColumnTests = []struct { func TestRenameColumn(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -4143,7 +4143,7 @@ func TestRenameColumn(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { @@ -4160,13 +4160,13 @@ func TestRenameColumn(t *testing.T) { } if v.ViewCache.SyncMap != nil { - if !SyncMapEqual(TestTx.cachedViews, v.ViewCache) { - t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.cachedViews, v.ViewCache) + if !SyncMapEqual(TestTx.CachedViews, v.ViewCache) { + t.Errorf("%s: view cache = %v, want %v", v.Name, TestTx.CachedViews, v.ViewCache) } } if v.ResultScopes != nil { - if !SyncMapEqual(scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) { - t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.blocks[0].temporaryTables, v.ResultScopes.blocks[0].temporaryTables) + if !SyncMapEqual(scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) { + t.Errorf("%s: temporary views list = %v, want %v", v.Name, scope.Blocks[0].TemporaryTables, v.ResultScopes.Blocks[0].TemporaryTables) } } } @@ -4535,7 +4535,7 @@ var setTableAttributeTests = []struct { func TestSetTableAttribute(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -4585,7 +4585,7 @@ func TestSetTableAttribute(t *testing.T) { continue } - TestTx.cachedViews.Range(func(key, value interface{}) bool { + TestTx.CachedViews.Range(func(key, value interface{}) bool { view := value.(*View) if view.FileInfo.Handler != nil { if view.FileInfo.Path != view.FileInfo.Handler.Path() { diff --git a/lib/query/reference_scope.go b/lib/query/reference_scope.go index ab1d8fe..530a904 100644 --- a/lib/query/reference_scope.go +++ b/lib/query/reference_scope.go @@ -48,26 +48,26 @@ func PutNodeScope(scope NodeScope) { } type BlockScope struct { - variables VariableMap - temporaryTables ViewMap - cursors CursorMap - functions UserDefinedFunctionMap + Variables VariableMap + TemporaryTables ViewMap + Cursors CursorMap + Functions UserDefinedFunctionMap } func NewBlockScope() BlockScope { return BlockScope{ - variables: NewVariableMap(), - temporaryTables: NewViewMap(), - cursors: NewCursorMap(), - functions: NewUserDefinedFunctionMap(), + Variables: NewVariableMap(), + TemporaryTables: NewViewMap(), + Cursors: NewCursorMap(), + Functions: NewUserDefinedFunctionMap(), } } func (scope BlockScope) Clear() { - scope.variables.Clear() - scope.temporaryTables.Clear() - scope.cursors.Clear() - scope.functions.Clear() + scope.Variables.Clear() + scope.TemporaryTables.Clear() + scope.Cursors.Clear() + scope.Functions.Clear() } type NodeScope struct { @@ -157,7 +157,7 @@ func (c *FieldIndexCache) Add(expr parser.QueryExpression, idx int) { type ReferenceScope struct { Tx *Transaction - blocks []BlockScope + Blocks []BlockScope nodes []NodeScope cachedFilePath map[string]string @@ -177,7 +177,7 @@ func NewReferenceScope(tx *Transaction) *ReferenceScope { func NewReferenceScopeWithBlock(tx *Transaction, scope BlockScope) *ReferenceScope { return &ReferenceScope{ Tx: tx, - blocks: []BlockScope{scope}, + Blocks: []BlockScope{scope}, nodes: nil, } } @@ -207,7 +207,7 @@ func (rs *ReferenceScope) CreateScopeForAnalytics() *ReferenceScope { func (rs *ReferenceScope) createScope(referenceRecords []ReferenceRecord) *ReferenceScope { return &ReferenceScope{ Tx: rs.Tx, - blocks: rs.blocks, + Blocks: rs.Blocks, nodes: rs.nodes, cachedFilePath: rs.cachedFilePath, now: rs.now, @@ -219,15 +219,15 @@ func (rs *ReferenceScope) createScope(referenceRecords []ReferenceRecord) *Refer } func (rs *ReferenceScope) CreateChild() *ReferenceScope { - blocks := make([]BlockScope, len(rs.blocks)+1) + blocks := make([]BlockScope, len(rs.Blocks)+1) blocks[0] = GetBlockScope() - for i := range rs.blocks { - blocks[i+1] = rs.blocks[i] + for i := range rs.Blocks { + blocks[i+1] = rs.Blocks[i] } return &ReferenceScope{ Tx: rs.Tx, - blocks: blocks, + Blocks: blocks, nodes: nil, cachedFilePath: rs.cachedFilePath, now: rs.now, @@ -246,7 +246,7 @@ func (rs *ReferenceScope) CreateNode() *ReferenceScope { node := &ReferenceScope{ Tx: rs.Tx, - blocks: rs.blocks, + Blocks: rs.Blocks, nodes: nodes, cachedFilePath: rs.cachedFilePath, now: rs.now, @@ -267,11 +267,11 @@ func (rs *ReferenceScope) CreateNode() *ReferenceScope { } func (rs *ReferenceScope) Global() BlockScope { - return rs.blocks[len(rs.blocks)-1] + return rs.Blocks[len(rs.Blocks)-1] } func (rs *ReferenceScope) CurrentBlock() BlockScope { - return rs.blocks[0] + return rs.Blocks[0] } func (rs *ReferenceScope) ClearCurrentBlock() { @@ -318,16 +318,16 @@ func (rs *ReferenceScope) Now() time.Time { } func (rs *ReferenceScope) DeclareVariable(ctx context.Context, expr parser.VariableDeclaration) error { - return rs.blocks[0].variables.Declare(ctx, rs, expr) + return rs.Blocks[0].Variables.Declare(ctx, rs, expr) } func (rs *ReferenceScope) DeclareVariableDirectly(variable parser.Variable, val value.Primary) error { - return rs.blocks[0].variables.Add(variable, val) + return rs.Blocks[0].Variables.Add(variable, val) } func (rs *ReferenceScope) GetVariable(expr parser.Variable) (val value.Primary, err error) { - for i := range rs.blocks { - if v, ok := rs.blocks[i].variables.Get(expr); ok { + for i := range rs.Blocks { + if v, ok := rs.Blocks[i].Variables.Get(expr); ok { return v, nil } } @@ -340,8 +340,8 @@ func (rs *ReferenceScope) SubstituteVariable(ctx context.Context, expr parser.Va return } - for i := range rs.blocks { - if rs.blocks[i].variables.Set(expr.Variable, val) { + for i := range rs.Blocks { + if rs.Blocks[i].Variables.Set(expr.Variable, val) { return } } @@ -350,8 +350,8 @@ func (rs *ReferenceScope) SubstituteVariable(ctx context.Context, expr parser.Va } func (rs *ReferenceScope) SubstituteVariableDirectly(variable parser.Variable, val value.Primary) (value.Primary, error) { - for i := range rs.blocks { - if rs.blocks[i].variables.Set(variable, val) { + for i := range rs.Blocks { + if rs.Blocks[i].Variables.Set(variable, val) { return val, nil } } @@ -359,8 +359,8 @@ func (rs *ReferenceScope) SubstituteVariableDirectly(variable parser.Variable, v } func (rs *ReferenceScope) DisposeVariable(expr parser.Variable) error { - for i := range rs.blocks { - if rs.blocks[i].variables.Dispose(expr) { + for i := range rs.Blocks { + if rs.Blocks[i].Variables.Dispose(expr) { return nil } } @@ -369,8 +369,8 @@ func (rs *ReferenceScope) DisposeVariable(expr parser.Variable) error { func (rs *ReferenceScope) AllVariables() VariableMap { all := NewVariableMap() - for i := range rs.blocks { - rs.blocks[i].variables.Range(func(key, val interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].Variables.Range(func(key, val interface{}) bool { if !all.Exists(key.(string)) { all.Store(key.(string), val.(value.Primary)) } @@ -381,8 +381,8 @@ func (rs *ReferenceScope) AllVariables() VariableMap { } func (rs *ReferenceScope) TemporaryTableExists(name string) bool { - for i := range rs.blocks { - if rs.blocks[i].temporaryTables.Exists(name) { + for i := range rs.Blocks { + if rs.Blocks[i].TemporaryTables.Exists(name) { return true } } @@ -390,8 +390,8 @@ func (rs *ReferenceScope) TemporaryTableExists(name string) bool { } func (rs *ReferenceScope) GetTemporaryTable(name parser.Identifier) (*View, error) { - for i := range rs.blocks { - if view, err := rs.blocks[i].temporaryTables.Get(name); err == nil { + for i := range rs.Blocks { + if view, err := rs.Blocks[i].TemporaryTables.Get(name); err == nil { return view, nil } } @@ -399,8 +399,8 @@ func (rs *ReferenceScope) GetTemporaryTable(name parser.Identifier) (*View, erro } func (rs *ReferenceScope) GetTemporaryTableWithInternalId(ctx context.Context, name parser.Identifier, flags *cmd.Flags) (view *View, err error) { - for i := range rs.blocks { - if view, err = rs.blocks[i].temporaryTables.GetWithInternalId(ctx, name, flags); err == nil { + for i := range rs.Blocks { + if view, err = rs.Blocks[i].TemporaryTables.GetWithInternalId(ctx, name, flags); err == nil { return } else if err != errTableNotLoaded { return nil, err @@ -410,21 +410,21 @@ func (rs *ReferenceScope) GetTemporaryTableWithInternalId(ctx context.Context, n } func (rs *ReferenceScope) SetTemporaryTable(view *View) { - rs.blocks[0].temporaryTables.Set(view) + rs.Blocks[0].TemporaryTables.Set(view) } func (rs *ReferenceScope) ReplaceTemporaryTable(view *View) { - for i := range rs.blocks { - if rs.blocks[i].temporaryTables.Exists(view.FileInfo.Path) { - rs.blocks[i].temporaryTables.Set(view) + for i := range rs.Blocks { + if rs.Blocks[i].TemporaryTables.Exists(view.FileInfo.Path) { + rs.Blocks[i].TemporaryTables.Set(view) return } } } func (rs *ReferenceScope) DisposeTemporaryTable(name parser.QueryExpression) error { - for i := range rs.blocks { - if rs.blocks[i].temporaryTables.DisposeTemporaryTable(name) { + for i := range rs.Blocks { + if rs.Blocks[i].TemporaryTables.DisposeTemporaryTable(name) { return nil } } @@ -433,8 +433,8 @@ func (rs *ReferenceScope) DisposeTemporaryTable(name parser.QueryExpression) err func (rs *ReferenceScope) StoreTemporaryTable(session *Session, uncomittedViews map[string]*FileInfo) []string { msglist := make([]string, 0, len(uncomittedViews)) - for i := range rs.blocks { - rs.blocks[i].temporaryTables.Range(func(key, value interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].TemporaryTables.Range(func(key, value interface{}) bool { if _, ok := uncomittedViews[key.(string)]; ok { view := value.(*View) @@ -453,13 +453,13 @@ func (rs *ReferenceScope) StoreTemporaryTable(session *Session, uncomittedViews func (rs *ReferenceScope) RestoreTemporaryTable(uncomittedViews map[string]*FileInfo) []string { msglist := make([]string, 0, len(uncomittedViews)) - for i := range rs.blocks { - rs.blocks[i].temporaryTables.Range(func(key, value interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].TemporaryTables.Range(func(key, value interface{}) bool { if _, ok := uncomittedViews[key.(string)]; ok { view := value.(*View) if view.FileInfo.IsStdin() { - rs.blocks[i].temporaryTables.Delete(view.FileInfo.Path) + rs.Blocks[i].TemporaryTables.Delete(view.FileInfo.Path) } else { view.Restore() } @@ -474,8 +474,8 @@ func (rs *ReferenceScope) RestoreTemporaryTable(uncomittedViews map[string]*File func (rs *ReferenceScope) AllTemporaryTables() ViewMap { all := NewViewMap() - for i := range rs.blocks { - rs.blocks[i].temporaryTables.Range(func(key, value interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].TemporaryTables.Range(func(key, value interface{}) bool { if !value.(*View).FileInfo.IsFile() { k := key.(string) if !all.Exists(k) { @@ -489,16 +489,16 @@ func (rs *ReferenceScope) AllTemporaryTables() ViewMap { } func (rs *ReferenceScope) DeclareCursor(expr parser.CursorDeclaration) error { - return rs.blocks[0].cursors.Declare(expr) + return rs.Blocks[0].Cursors.Declare(expr) } func (rs *ReferenceScope) AddPseudoCursor(name parser.Identifier, values []value.Primary) error { - return rs.blocks[0].cursors.AddPseudoCursor(name, values) + return rs.Blocks[0].Cursors.AddPseudoCursor(name, values) } func (rs *ReferenceScope) DisposeCursor(name parser.Identifier) error { - for i := range rs.blocks { - err := rs.blocks[i].cursors.Dispose(name) + for i := range rs.Blocks { + err := rs.Blocks[i].Cursors.Dispose(name) if err == nil { return nil } @@ -511,8 +511,8 @@ func (rs *ReferenceScope) DisposeCursor(name parser.Identifier) error { func (rs *ReferenceScope) OpenCursor(ctx context.Context, name parser.Identifier, values []parser.ReplaceValue) error { var err error - for i := range rs.blocks { - err = rs.blocks[i].cursors.Open(ctx, rs, name, values) + for i := range rs.Blocks { + err = rs.Blocks[i].Cursors.Open(ctx, rs, name, values) if err == nil { return nil } @@ -524,8 +524,8 @@ func (rs *ReferenceScope) OpenCursor(ctx context.Context, name parser.Identifier } func (rs *ReferenceScope) CloseCursor(name parser.Identifier) error { - for i := range rs.blocks { - err := rs.blocks[i].cursors.Close(name) + for i := range rs.Blocks { + err := rs.Blocks[i].Cursors.Close(name) if err == nil { return nil } @@ -540,8 +540,8 @@ func (rs *ReferenceScope) FetchCursor(name parser.Identifier, position int, numb var values []value.Primary var err error - for i := range rs.blocks { - values, err = rs.blocks[i].cursors.Fetch(name, position, number) + for i := range rs.Blocks { + values, err = rs.Blocks[i].Cursors.Fetch(name, position, number) if err == nil { return values, nil } @@ -553,8 +553,8 @@ func (rs *ReferenceScope) FetchCursor(name parser.Identifier, position int, numb } func (rs *ReferenceScope) CursorIsOpen(name parser.Identifier) (ternary.Value, error) { - for i := range rs.blocks { - if ok, err := rs.blocks[i].cursors.IsOpen(name); err == nil { + for i := range rs.Blocks { + if ok, err := rs.Blocks[i].Cursors.IsOpen(name); err == nil { return ok, nil } } @@ -565,8 +565,8 @@ func (rs *ReferenceScope) CursorIsInRange(name parser.Identifier) (ternary.Value var result ternary.Value var err error - for i := range rs.blocks { - result, err = rs.blocks[i].cursors.IsInRange(name) + for i := range rs.Blocks { + result, err = rs.Blocks[i].Cursors.IsInRange(name) if err == nil { return result, nil } @@ -581,8 +581,8 @@ func (rs *ReferenceScope) CursorCount(name parser.Identifier) (int, error) { var count int var err error - for i := range rs.blocks { - count, err = rs.blocks[i].cursors.Count(name) + for i := range rs.Blocks { + count, err = rs.Blocks[i].Cursors.Count(name) if err == nil { return count, nil } @@ -595,8 +595,8 @@ func (rs *ReferenceScope) CursorCount(name parser.Identifier) (int, error) { func (rs *ReferenceScope) AllCursors() CursorMap { all := NewCursorMap() - for i := range rs.blocks { - rs.blocks[i].cursors.Range(func(key, val interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].Cursors.Range(func(key, val interface{}) bool { cur := val.(*Cursor) if !cur.isPseudo { if !all.Exists(key.(string)) { @@ -610,16 +610,16 @@ func (rs *ReferenceScope) AllCursors() CursorMap { } func (rs *ReferenceScope) DeclareFunction(expr parser.FunctionDeclaration) error { - return rs.blocks[0].functions.Declare(expr) + return rs.Blocks[0].Functions.Declare(expr) } func (rs *ReferenceScope) DeclareAggregateFunction(expr parser.AggregateDeclaration) error { - return rs.blocks[0].functions.DeclareAggregate(expr) + return rs.Blocks[0].Functions.DeclareAggregate(expr) } func (rs *ReferenceScope) GetFunction(expr parser.QueryExpression, name string) (*UserDefinedFunction, error) { - for i := range rs.blocks { - if fn, ok := rs.blocks[i].functions.Get(expr, name); ok { + for i := range rs.Blocks { + if fn, ok := rs.Blocks[i].Functions.Get(expr, name); ok { return fn, nil } } @@ -627,8 +627,8 @@ func (rs *ReferenceScope) GetFunction(expr parser.QueryExpression, name string) } func (rs *ReferenceScope) DisposeFunction(name parser.Identifier) error { - for i := range rs.blocks { - if rs.blocks[i].functions.Dispose(name) { + for i := range rs.Blocks { + if rs.Blocks[i].Functions.Dispose(name) { return nil } } @@ -639,8 +639,8 @@ func (rs *ReferenceScope) AllFunctions() (UserDefinedFunctionMap, UserDefinedFun scalarAll := NewUserDefinedFunctionMap() aggregateAll := NewUserDefinedFunctionMap() - for i := range rs.blocks { - rs.blocks[i].functions.Range(func(key, val interface{}) bool { + for i := range rs.Blocks { + rs.Blocks[i].Functions.Range(func(key, val interface{}) bool { fn := val.(*UserDefinedFunction) if fn.IsAggregate { if !aggregateAll.Exists(key.(string)) { diff --git a/lib/query/reference_scope_test.go b/lib/query/reference_scope_test.go index 3ee68c5..4f4d3d9 100644 --- a/lib/query/reference_scope_test.go +++ b/lib/query/reference_scope_test.go @@ -246,8 +246,8 @@ func TestReferenceScope_SubstituteVariable(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(testVariablesReferenceScope.blocks, v.ResultScope.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.blocks, v.ResultScope.blocks) + if !BlockScopeListEqual(testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) } if !reflect.DeepEqual(result, v.Result) { t.Errorf("%s: result = %v, want %v", v.Name, result, v.Result) @@ -295,8 +295,8 @@ func TestReferenceScope_DisposeVariable(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(testVariablesReferenceScope.blocks, v.ResultScope.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.blocks, v.ResultScope.blocks) + if !BlockScopeListEqual(testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) } } } @@ -535,8 +535,8 @@ var referenceScopeSetTemporaryTableTests = []struct { func TestReferenceScope_SetTemporaryTable(t *testing.T) { for _, v := range referenceScopeSetTemporaryTableTests { testTemporaryTablesReferenceScope.SetTemporaryTable(v.SetView) - if !BlockScopeListEqual(testTemporaryTablesReferenceScope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.blocks, v.Result.blocks) + if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) } } } @@ -637,8 +637,8 @@ var referenceScopeReplaceTemporaryTableTests = []struct { func TestReferenceScope_ReplaceTemporaryTable(t *testing.T) { for _, v := range referenceScopeReplaceTemporaryTableTests { testTemporaryTablesReferenceScope.ReplaceTemporaryTable(v.SetView) - if !BlockScopeListEqual(testTemporaryTablesReferenceScope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.blocks, v.Result.blocks) + if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) } } } @@ -721,8 +721,8 @@ func TestReferenceScope_DisposeTemporaryTable(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(testTemporaryTablesReferenceScope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.blocks, v.Result.blocks) + if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) } } } @@ -843,8 +843,8 @@ func TestReferenceScope_StoreTemporaryTable(t *testing.T) { log := scope.StoreTemporaryTable(TestTx.Session, UncommittedViews) - if !BlockScopeListEqual(scope.blocks, expect.blocks) { - t.Errorf("Store: blocks = %v, want %v", scope.blocks, expect.blocks) + if !BlockScopeListEqual(scope.Blocks, expect.Blocks) { + t.Errorf("Store: blocks = %v, want %v", scope.Blocks, expect.Blocks) } if reflect.DeepEqual(log, expectOut) { @@ -976,8 +976,8 @@ func TestReferenceScope_RestoreTemporaryTable(t *testing.T) { log := scope.RestoreTemporaryTable(UncommittedViews) - if !BlockScopeListEqual(scope.blocks, expect.blocks) { - t.Errorf("Restore: blocks = %v, want %v", scope.blocks, expect.blocks) + if !BlockScopeListEqual(scope.Blocks, expect.Blocks) { + t.Errorf("Restore: blocks = %v, want %v", scope.Blocks, expect.Blocks) } if reflect.DeepEqual(log, expectOut) { @@ -1063,8 +1063,8 @@ func TestReferenceScope_DisposeCursor(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(scope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, scope.blocks, v.Result.blocks) + if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks) } } } @@ -1146,7 +1146,7 @@ var referenceScopeOpenCursorTests = []struct { func TestReferenceScope_OpenCursor(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -1176,7 +1176,7 @@ func TestReferenceScope_OpenCursor(t *testing.T) { }, nil, time.Time{}, nil) for _, v := range referenceScopeOpenCursorTests { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) err := scope.OpenCursor(context.Background(), v.CurName, v.CurValues) if err != nil { @@ -1191,8 +1191,8 @@ func TestReferenceScope_OpenCursor(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(scope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, scope.blocks, v.Result.blocks) + if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks) } } } @@ -1243,7 +1243,7 @@ var referenceScopeCloseCursorTests = []struct { func TestReferenceScope_CloseCursor(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() @@ -1311,8 +1311,8 @@ func TestReferenceScope_CloseCursor(t *testing.T) { t.Errorf("%s: no error, want error %q", v.Name, v.Error) continue } - if !BlockScopeListEqual(scope.blocks, v.Result.blocks) { - t.Errorf("%s: blocks = %v, want %v", v.Name, scope.blocks, v.Result.blocks) + if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) { + t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks) } } } diff --git a/lib/query/runtime_information.go b/lib/query/runtime_information.go index 026bbc4..24770b6 100644 --- a/lib/query/runtime_information.go +++ b/lib/query/runtime_information.go @@ -33,15 +33,15 @@ func GetRuntimeInformation(tx *Transaction, expr parser.RuntimeInformation) (val switch strings.ToUpper(expr.Name) { case UncommittedInformation: - p = value.NewBoolean(!tx.uncommittedViews.IsEmpty()) + p = value.NewBoolean(!tx.UncommittedViews.IsEmpty()) case CreatedInformation: - p = value.NewInteger(int64(tx.uncommittedViews.CountCreatedTables())) + p = value.NewInteger(int64(tx.UncommittedViews.CountCreatedTables())) case UpdatedInformation: - p = value.NewInteger(int64(tx.uncommittedViews.CountUpdatedTables())) + p = value.NewInteger(int64(tx.UncommittedViews.CountUpdatedTables())) case UpdatedViewsInformation: - p = value.NewInteger(int64(tx.uncommittedViews.CountUpdatedViews())) + p = value.NewInteger(int64(tx.UncommittedViews.CountUpdatedViews())) case LoadedTablesInformation: - p = value.NewInteger(int64(tx.cachedViews.Len())) + p = value.NewInteger(int64(tx.CachedViews.Len())) case WorkingDirectory: wd, err := os.Getwd() if err != nil { diff --git a/lib/query/runtime_information_test.go b/lib/query/runtime_information_test.go index a3d4e6b..11b0e46 100644 --- a/lib/query/runtime_information_test.go +++ b/lib/query/runtime_information_test.go @@ -50,18 +50,18 @@ var getRuntimeInformationTests = []struct { func TestGetRuntimeInformation(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) - TestTx.uncommittedViews.Clean() + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) + TestTx.UncommittedViews.Clean() initFlag(TestTx.Flags) }() - TestTx.cachedViews = GenerateViewMap([]*View{ + TestTx.CachedViews = GenerateViewMap([]*View{ {FileInfo: &FileInfo{Path: "table1"}}, {FileInfo: &FileInfo{Path: "table2"}}, {FileInfo: &FileInfo{Path: "table3"}}, {FileInfo: &FileInfo{Path: "table4"}}, }) - TestTx.uncommittedViews = UncommittedViews{ + TestTx.UncommittedViews = UncommittedViews{ mtx: &sync.RWMutex{}, Created: map[string]*FileInfo{ "TABLE1": {}, diff --git a/lib/query/transaction.go b/lib/query/transaction.go index 48560b3..0e90ecf 100644 --- a/lib/query/transaction.go +++ b/lib/query/transaction.go @@ -30,8 +30,8 @@ type Transaction struct { RetryDelay time.Duration FileContainer *file.Container - cachedViews ViewMap - uncommittedViews UncommittedViews + CachedViews ViewMap + UncommittedViews UncommittedViews operationMutex *sync.Mutex viewLoadingMutex *sync.Mutex @@ -73,8 +73,8 @@ func NewTransaction(ctx context.Context, defaultWaitTimeout time.Duration, retry WaitTimeout: file.DefaultWaitTimeout, RetryDelay: file.DefaultRetryDelay, FileContainer: file.NewContainer(), - cachedViews: NewViewMap(), - uncommittedViews: NewUncommittedViews(), + CachedViews: NewViewMap(), + UncommittedViews: NewUncommittedViews(), operationMutex: &sync.Mutex{}, viewLoadingMutex: &sync.Mutex{}, stdinIsLocked: false, @@ -110,14 +110,14 @@ func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr p tx.operationMutex.Lock() defer tx.operationMutex.Unlock() - createdFiles, updatedFiles := tx.uncommittedViews.UncommittedFiles() + createdFiles, updatedFiles := tx.UncommittedViews.UncommittedFiles() createFileInfo := make([]*FileInfo, 0, len(createdFiles)) updateFileInfo := make([]*FileInfo, 0, len(updatedFiles)) if 0 < len(createdFiles) { for _, fileinfo := range createdFiles { - view, _ := tx.cachedViews.Get(parser.Identifier{Literal: fileinfo.Path}) + view, _ := tx.CachedViews.Get(parser.Identifier{Literal: fileinfo.Path}) fp, _ := view.FileInfo.Handler.FileForUpdate() if err := fp.Truncate(0); err != nil { @@ -143,7 +143,7 @@ func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr p if 0 < len(updatedFiles) { for _, fileinfo := range updatedFiles { - view, _ := tx.cachedViews.Get(parser.Identifier{Literal: fileinfo.Path}) + view, _ := tx.CachedViews.Get(parser.Identifier{Literal: fileinfo.Path}) fp, _ := view.FileInfo.Handler.FileForUpdate() if err := fp.Truncate(0); err != nil { @@ -171,22 +171,22 @@ func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr p if err := tx.FileContainer.Commit(f.Handler); err != nil { return NewCommitError(expr, err.Error()) } - tx.uncommittedViews.Unset(f) + tx.UncommittedViews.Unset(f) tx.LogNotice(fmt.Sprintf("Commit: file %q is created.", f.Path), tx.Flags.Quiet) } for _, f := range updateFileInfo { if err := tx.FileContainer.Commit(f.Handler); err != nil { return NewCommitError(expr, err.Error()) } - tx.uncommittedViews.Unset(f) + tx.UncommittedViews.Unset(f) tx.LogNotice(fmt.Sprintf("Commit: file %q is updated.", f.Path), tx.Flags.Quiet) } - msglist := scope.StoreTemporaryTable(tx.Session, tx.uncommittedViews.UncommittedTempViews()) + msglist := scope.StoreTemporaryTable(tx.Session, tx.UncommittedViews.UncommittedTempViews()) if 0 < len(msglist) { tx.LogNotice(strings.Join(msglist, "\n"), tx.quietForTemporaryViews(expr)) } - tx.uncommittedViews.Clean() + tx.UncommittedViews.Clean() tx.UnlockStdin() if err := tx.ReleaseResources(); err != nil { return NewCommitError(expr, err.Error()) @@ -198,7 +198,7 @@ func (tx *Transaction) Rollback(scope *ReferenceScope, expr parser.Expression) e tx.operationMutex.Lock() defer tx.operationMutex.Unlock() - createdFiles, updatedFiles := tx.uncommittedViews.UncommittedFiles() + createdFiles, updatedFiles := tx.UncommittedViews.UncommittedFiles() if 0 < len(createdFiles) { for _, fileinfo := range createdFiles { @@ -213,12 +213,12 @@ func (tx *Transaction) Rollback(scope *ReferenceScope, expr parser.Expression) e } if scope != nil { - msglist := scope.RestoreTemporaryTable(tx.uncommittedViews.UncommittedTempViews()) + msglist := scope.RestoreTemporaryTable(tx.UncommittedViews.UncommittedTempViews()) if 0 < len(msglist) { tx.LogNotice(strings.Join(msglist, "\n"), tx.quietForTemporaryViews(expr)) } } - tx.uncommittedViews.Clean() + tx.UncommittedViews.Clean() tx.UnlockStdin() if err := tx.ReleaseResources(); err != nil { return NewRollbackError(expr, err.Error()) @@ -231,7 +231,7 @@ func (tx *Transaction) quietForTemporaryViews(expr parser.Expression) bool { } func (tx *Transaction) ReleaseResources() error { - if err := tx.cachedViews.Clean(tx.FileContainer); err != nil { + if err := tx.CachedViews.Clean(tx.FileContainer); err != nil { return err } if err := tx.FileContainer.CloseAll(); err != nil { @@ -243,7 +243,7 @@ func (tx *Transaction) ReleaseResources() error { func (tx *Transaction) ReleaseResourcesWithErrors() error { var errs []error - if err := tx.cachedViews.CleanWithErrors(tx.FileContainer); err != nil { + if err := tx.CachedViews.CleanWithErrors(tx.FileContainer); err != nil { errs = append(errs, err.(*file.ForcedUnlockError).Errors...) } if err := tx.FileContainer.CloseAllWithErrors(); err != nil { diff --git a/lib/query/transaction_test.go b/lib/query/transaction_test.go index d12c12e..608bb18 100644 --- a/lib/query/transaction_test.go +++ b/lib/query/transaction_test.go @@ -20,7 +20,7 @@ import ( func TestTransaction_Commit(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) TestTx.Session.SetStdout(NewDiscard()) initFlag(TestTx.Flags) }() @@ -30,7 +30,7 @@ func TestTransaction_Commit(t *testing.T) { ch, _ := file.NewHandlerForCreate(TestTx.FileContainer, GetTestFilePath("created_file.csv")) uh, _ := file.NewHandlerForUpdate(context.Background(), TestTx.FileContainer, GetTestFilePath("updated_file_1.csv"), TestTx.WaitTimeout, TestTx.RetryDelay) - TestTx.cachedViews = GenerateViewMap([]*View{ + TestTx.CachedViews = GenerateViewMap([]*View{ { Header: NewHeader("created_file", []string{"column1", "column2"}), RecordSet: RecordSet{}, @@ -70,7 +70,7 @@ func TestTransaction_Commit(t *testing.T) { }, }) - TestTx.uncommittedViews = UncommittedViews{ + TestTx.UncommittedViews = UncommittedViews{ mtx: &sync.RWMutex{}, Created: map[string]*FileInfo{ strings.ToUpper(GetTestFilePath("created_file.csv")): { @@ -136,7 +136,7 @@ func TestTransaction_Commit(t *testing.T) { TestTx.Flags.ExportOptions.StripEndingLineBreak = true ch, _ = file.NewHandlerForCreate(TestTx.FileContainer, GetTestFilePath("created_file_1.csv")) uh, _ = file.NewHandlerForUpdate(context.Background(), TestTx.FileContainer, GetTestFilePath("updated_file_1.csv"), TestTx.WaitTimeout, TestTx.RetryDelay) - TestTx.cachedViews = GenerateViewMap([]*View{ + TestTx.CachedViews = GenerateViewMap([]*View{ { Header: NewHeader("created_file_1", []string{"column1", "column2"}), RecordSet: RecordSet{}, @@ -176,7 +176,7 @@ func TestTransaction_Commit(t *testing.T) { }, }) - TestTx.uncommittedViews = UncommittedViews{ + TestTx.UncommittedViews = UncommittedViews{ mtx: &sync.RWMutex{}, Created: map[string]*FileInfo{ strings.ToUpper(GetTestFilePath("created_file_1.csv")): { @@ -229,14 +229,14 @@ func TestTransaction_Commit(t *testing.T) { func TestTransaction_Rollback(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) TestTx.Session.SetStdout(NewDiscard()) initFlag(TestTx.Flags) }() TestTx.Flags.SetQuiet(false) - TestTx.uncommittedViews = UncommittedViews{ + TestTx.UncommittedViews = UncommittedViews{ mtx: &sync.RWMutex{}, Created: map[string]*FileInfo{ strings.ToUpper(GetTestFilePath("created_file.csv")): { diff --git a/lib/query/user_defined_function.go b/lib/query/user_defined_function.go index 618bef9..4efb54a 100644 --- a/lib/query/user_defined_function.go +++ b/lib/query/user_defined_function.go @@ -206,7 +206,7 @@ func (fn *UserDefinedFunction) execute(ctx context.Context, scope *ReferenceScop for i, v := range fn.Parameters { if i < len(args) { - if err := scope.blocks[0].variables.Add(v, args[i]); err != nil { + if err := scope.Blocks[0].Variables.Add(v, args[i]); err != nil { return nil, err } } else { diff --git a/lib/query/view.go b/lib/query/view.go index f2384db..cf97dd1 100644 --- a/lib/query/view.go +++ b/lib/query/view.go @@ -532,7 +532,7 @@ func loadStdin(ctx context.Context, scope *ReferenceScope, fileInfo *FileInfo, s defer scope.Tx.viewLoadingMutex.Unlock() var err error - view, ok := scope.Global().temporaryTables.Load(stdin.String()) + view, ok := scope.Global().TemporaryTables.Load(stdin.String()) if !ok || (forUpdate && !view.FileInfo.ForUpdate) { if forUpdate { if err = scope.Tx.LockStdinContext(ctx); err != nil { @@ -548,19 +548,19 @@ func loadStdin(ctx context.Context, scope *ReferenceScope, fileInfo *FileInfo, s if err != nil { return nil, err } - scope.Global().temporaryTables.Set(view) + scope.Global().TemporaryTables.Set(view) } pathIdent := parser.Identifier{Literal: stdin.String()} if useInternalId { - if view, err = scope.Global().temporaryTables.GetWithInternalId(ctx, pathIdent, scope.Tx.Flags); err != nil { + if view, err = scope.Global().TemporaryTables.GetWithInternalId(ctx, pathIdent, scope.Tx.Flags); err != nil { if err == errTableNotLoaded { err = NewUndeclaredTemporaryTableError(pathIdent) } return nil, err } } else { - if view, err = scope.Global().temporaryTables.Get(pathIdent); err != nil { + if view, err = scope.Global().TemporaryTables.Get(pathIdent); err != nil { if err == errTableNotLoaded { err = NewUndeclaredTemporaryTableError(pathIdent) } @@ -689,14 +689,14 @@ func loadObject( var view *View pathIdent := parser.Identifier{BaseExpr: tablePath.GetBaseExpr(), Literal: filePath} if useInternalId { - if view, err = scope.Tx.cachedViews.GetWithInternalId(ctx, pathIdent, scope.Tx.Flags); err != nil { + if view, err = scope.Tx.CachedViews.GetWithInternalId(ctx, pathIdent, scope.Tx.Flags); err != nil { if err == errTableNotLoaded { err = NewTableNotLoadedError(pathIdent) } return nil, err } } else { - if view, err = scope.Tx.cachedViews.Get(pathIdent); err != nil { + if view, err = scope.Tx.CachedViews.Get(pathIdent); err != nil { return nil, NewTableNotLoadedError(pathIdent) } } @@ -757,7 +757,7 @@ func cacheViewFromFile( return filePath, err } - view, ok := scope.Tx.cachedViews.Load(filePath) + view, ok := scope.Tx.CachedViews.Load(filePath) if !ok || (forUpdate && !view.FileInfo.ForUpdate) { fileInfo, err := (func() (*FileInfo, error) { if isInlineObject && (isInlineObjectData(tablePath) || isInlineObjectURL(tablePath)) { @@ -777,7 +777,7 @@ func cacheViewFromFile( } filePath = fileInfo.Path - view, ok = scope.Tx.cachedViews.Load(filePath) + view, ok = scope.Tx.CachedViews.Load(filePath) if !ok || (forUpdate && !view.FileInfo.ForUpdate) { fileInfo.DelimiterPositions = options.DelimiterPositions fileInfo.SingleLine = options.SingleLine @@ -791,7 +791,7 @@ func cacheViewFromFile( fileInfo = view.FileInfo } - if err = scope.Tx.cachedViews.Dispose(scope.Tx.FileContainer, fileInfo.Path); err != nil { + if err = scope.Tx.CachedViews.Dispose(scope.Tx.FileContainer, fileInfo.Path); err != nil { return filePath, err } @@ -851,7 +851,7 @@ func cacheViewFromFile( return filePath, appendCompositeError(err, scope.Tx.FileContainer.Close(fileInfo.Handler)) } loadView.FileInfo.ForUpdate = forUpdate - scope.Tx.cachedViews.Set(loadView) + scope.Tx.CachedViews.Set(loadView) } } if 0 < len(filePathForCacheKey) { diff --git a/lib/query/view_test.go b/lib/query/view_test.go index e9b4934..6ee8305 100644 --- a/lib/query/view_test.go +++ b/lib/query/view_test.go @@ -3004,7 +3004,7 @@ var viewLoadTests = []struct { func TestView_Load(t *testing.T) { defer func() { _ = TestTx.ReleaseResources() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = TestTx.Session.SetStdin(os.Stdin) initFlag(TestTx.Flags) }() @@ -3014,7 +3014,7 @@ func TestView_Load(t *testing.T) { for _, v := range viewLoadTests { TestTx.UnlockStdin() - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) _ = TestTx.Session.SetStdin(os.Stdin) TestTx.Flags.ImportOptions.Format = v.ImportFormat @@ -3108,9 +3108,9 @@ func TestView_Load(t *testing.T) { if !NodeScopeListEqual(queryScope.nodes, v.ResultScope.nodes) { t.Errorf("%s: node list = %v, want %v", v.Name, queryScope.nodes, v.ResultScope.nodes) } - for i := range queryScope.blocks { - if !reflect.DeepEqual(queryScope.blocks[i].temporaryTables.Keys(), v.ResultScope.blocks[i].temporaryTables.Keys()) { - t.Errorf("%s: temp view list = %v, want %v", v.Name, queryScope.blocks[i].temporaryTables.Keys(), v.ResultScope.blocks[i].temporaryTables.Keys()) + for i := range queryScope.Blocks { + if !reflect.DeepEqual(queryScope.Blocks[i].TemporaryTables.Keys(), v.ResultScope.Blocks[i].TemporaryTables.Keys()) { + t.Errorf("%s: temp view list = %v, want %v", v.Name, queryScope.Blocks[i].TemporaryTables.Keys(), v.ResultScope.Blocks[i].TemporaryTables.Keys()) } } diff --git a/lib/query/virtual_terminal.go b/lib/query/virtual_terminal.go new file mode 100644 index 0000000..3a21b85 --- /dev/null +++ b/lib/query/virtual_terminal.go @@ -0,0 +1,18 @@ +package query + +import ( + "context" +) + +type VirtualTerminal interface { + ReadLine() (string, error) + Write(string) error + WriteError(string) error + SetPrompt(ctx context.Context) + SetContinuousPrompt(ctx context.Context) + SaveHistory(string) error + Teardown() error + GetSize() (int, int, error) + ReloadConfig() error + UpdateCompleter() +} diff --git a/lib/query/completer_readline.go b/lib/terminal/completer_readline.go similarity index 96% rename from lib/query/completer_readline.go rename to lib/terminal/completer_readline.go index 972bffd..450468d 100644 --- a/lib/query/completer_readline.go +++ b/lib/terminal/completer_readline.go @@ -1,6 +1,6 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -package query +package terminal import ( "io/ioutil" @@ -12,6 +12,7 @@ import ( "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/go-text" "github.com/mithrandie/readline-csvq" @@ -139,7 +140,7 @@ func (l ReadlineListener) OnChange(line []rune, pos int, key rune) ([]rune, int, type Completer struct { completer *readline.PrefixCompleter - scope *ReferenceScope + scope *query.ReferenceScope flagList []string runinfoList []string @@ -169,7 +170,7 @@ type Completer struct { isInAndAfterSelect bool } -func NewCompleter(scope *ReferenceScope) *Completer { +func NewCompleter(scope *query.ReferenceScope) *Completer { completer := &Completer{ completer: readline.NewPrefixCompleter(), scope: scope, @@ -180,31 +181,31 @@ func NewCompleter(scope *ReferenceScope) *Completer { for _, v := range cmd.FlagList { completer.flagList = append(completer.flagList, cmd.FlagSymbol(v)) } - completer.runinfoList = make([]string, 0, len(RuntimeInformatinList)) - for _, v := range RuntimeInformatinList { + completer.runinfoList = make([]string, 0, len(query.RuntimeInformatinList)) + for _, v := range query.RuntimeInformatinList { completer.runinfoList = append(completer.runinfoList, cmd.RuntimeInformationSymbol(v)) } sort.Strings(completer.flagList) sort.Strings(completer.runinfoList) - completer.funcs = make([]string, 0, len(Functions)+3) - for k := range Functions { + completer.funcs = make([]string, 0, len(query.Functions)+3) + for k := range query.Functions { completer.funcs = append(completer.funcs, k) } completer.funcs = append(completer.funcs, "CALL") completer.funcs = append(completer.funcs, "NOW") completer.funcs = append(completer.funcs, "JSON_OBJECT") - completer.aggFuncs = make([]string, 0, len(AggregateFunctions)+2) - completer.analyticFuncs = make([]string, 0, len(AnalyticFunctions)+len(AggregateFunctions)) - for k := range AggregateFunctions { + completer.aggFuncs = make([]string, 0, len(query.AggregateFunctions)+2) + completer.analyticFuncs = make([]string, 0, len(query.AnalyticFunctions)+len(query.AggregateFunctions)) + for k := range query.AggregateFunctions { completer.aggFuncs = append(completer.aggFuncs, k) completer.analyticFuncs = append(completer.analyticFuncs, k) } completer.aggFuncs = append(completer.aggFuncs, "LISTAGG") completer.aggFuncs = append(completer.aggFuncs, "JSON_AGG") - for k := range AnalyticFunctions { + for k := range query.AnalyticFunctions { completer.analyticFuncs = append(completer.analyticFuncs, k) } @@ -236,7 +237,7 @@ func (c *Completer) Update() { func (c *Completer) updateStatements() { c.statementList = make([]string, 0, 10) c.scope.Tx.PreparedStatements.Range(func(key, value interface{}) bool { - c.statementList = append(c.statementList, value.(*PreparedStatement).Name) + c.statementList = append(c.statementList, value.(*query.PreparedStatement).Name) return true }) sort.Strings(c.statementList) @@ -259,7 +260,7 @@ func (c *Completer) updateCursors() { c.cursorList = make([]string, 0, len(cursorKeys)) for _, key := range cursorKeys { if cur, ok := cursors.Load(key); ok { - c.cursorList = append(c.cursorList, cur.name) + c.cursorList = append(c.cursorList, cur.Name) } } } @@ -274,7 +275,7 @@ func (c *Completer) updateFunctions() { funcKeys = append(funcKeys, v+"()") } userfuncs.Range(func(key, value interface{}) bool { - f := value.(*UserDefinedFunction) + f := value.(*query.UserDefinedFunction) funcKeys = append(funcKeys, f.Name.String()+"()") c.userFuncs = append(c.userFuncs, f.Name.String()) return true @@ -287,7 +288,7 @@ func (c *Completer) updateFunctions() { aggFuncKeys = append(aggFuncKeys, v+"()") } userAggFuncs.Range(func(key, value interface{}) bool { - f := value.(*UserDefinedFunction) + f := value.(*query.UserDefinedFunction) aggFuncKeys = append(aggFuncKeys, f.Name.String()+"()") c.userAggFuncs = append(c.userAggFuncs, f.Name.String()) return true @@ -303,7 +304,7 @@ func (c *Completer) updateFunctions() { analyticFuncKeys = append(analyticFuncKeys, v+"() OVER ()") } userAggFuncs.Range(func(key, value interface{}) bool { - f := value.(*UserDefinedFunction) + f := value.(*query.UserDefinedFunction) analyticFuncKeys = append(analyticFuncKeys, f.Name.String()+"() OVER ()") return true }) @@ -659,8 +660,8 @@ func (c *Completer) functionArgs(line string, origLine string, index int) readli if funcName == "FIRST_VALUE" || funcName == "LAST_VALUE" || funcName == "NTH_VALUE" || - (funcName != "LISTAGG" && funcName != "JSON_AGG" && InStrSliceWithCaseInsensitive(funcName, c.aggFuncs)) || - InStrSliceWithCaseInsensitive(funcName, c.userAggFuncs) { + (funcName != "LISTAGG" && funcName != "JSON_AGG" && query.InStrSliceWithCaseInsensitive(funcName, c.aggFuncs)) || + query.InStrSliceWithCaseInsensitive(funcName, c.userAggFuncs) { customList = append(customList, c.candidate("ROWS", true)) } @@ -692,8 +693,8 @@ func (c *Completer) functionArgs(line string, origLine string, index int) readli default: if i == 0 { if 0 < len(line) && i == c.lastIdx-1 { - if InStrSliceWithCaseInsensitive(c.tokens[i].Literal, c.aggFuncs) || - InStrSliceWithCaseInsensitive(c.tokens[i].Literal, c.userAggFuncs) { + if query.InStrSliceWithCaseInsensitive(c.tokens[i].Literal, c.aggFuncs) || + query.InStrSliceWithCaseInsensitive(c.tokens[i].Literal, c.userAggFuncs) { keywords = append(keywords, "DISTINCT") } } @@ -1711,24 +1712,24 @@ func (c *Completer) AlterArgs(line string, origLine string, index int) readline. case parser.SET: switch i { case c.lastIdx: - return FileAttributeList, nil, true + return query.FileAttributeList, nil, true case c.lastIdx - 1: return []string{"TO"}, nil, true case c.lastIdx - 2: switch strings.ToUpper(c.tokens[c.lastIdx-1].Literal) { - case TableFormat: + case query.TableFormat: return nil, c.candidateList(c.tableFormatList(), false), true - case TableDelimiter: + case query.TableDelimiter: return nil, c.candidateList(delimiterCandidates, false), true - case TableDelimiterPositions: + case query.TableDelimiterPositions: return nil, c.candidateList(delimiterPositionsCandidates, false), true - case TableEncoding: + case query.TableEncoding: return nil, c.candidateList(exportEncodingsCandidates, false), true - case TableLineBreak: + case query.TableLineBreak: return nil, c.candidateList(c.lineBreakList(), false), true - case TableJsonEscape: + case query.TableJsonEscape: return nil, c.candidateList(c.jsonEscapeTypeList(), false), true - case TableHeader, TableEncloseAll, TablePrettyPrint: + case query.TableHeader, query.TableEncloseAll, query.TablePrettyPrint: return nil, c.candidateList([]string{ternary.TRUE.String(), ternary.FALSE.String()}, false), true } } @@ -2062,7 +2063,7 @@ func (c *Completer) DisposeArgs(line string, origLine string, index int) readlin func (c *Completer) ShowArgs(line string, origLine string, index int) readline.CandidateList { var showChild = func() readline.CandidateList { - cands := c.candidateList(ShowObjectList, false) + cands := c.candidateList(query.ShowObjectList, false) cands = append(cands, c.candidate("FIELDS", true)) cands.Sort() cands = append(cands, c.candidateList(c.flagList, false)...) @@ -2106,7 +2107,7 @@ func (c *Completer) SearchAllTablesWithSpace(line string, origLine string, index } func (c *Completer) SearchAllTables(line string, _ string, _ int) readline.CandidateList { - tableKeys := c.scope.Tx.cachedViews.SortedKeys() + tableKeys := c.scope.Tx.CachedViews.SortedKeys() files := c.ListFiles(line, []string{cmd.CsvExt, cmd.TsvExt, cmd.JsonExt, cmd.JsonlExt, cmd.LtsvExt, cmd.TextExt}, c.scope.Tx.Flags.Repository) defaultDir := c.scope.Tx.Flags.Repository @@ -2117,7 +2118,7 @@ func (c *Completer) SearchAllTables(line string, _ string, _ int) readline.Candi items := make([]string, 0, len(tableKeys)+len(files)+len(c.viewList)) tablePath := make(map[string]bool) for _, k := range tableKeys { - if view, ok := c.scope.Tx.cachedViews.Load(k); ok { + if view, ok := c.scope.Tx.CachedViews.Load(k); ok { lpath := view.FileInfo.Path tablePath[lpath] = true if filepath.Dir(lpath) == defaultDir { @@ -2407,7 +2408,7 @@ func (c *Completer) ListFiles(path string, includeExt []string, repository strin continue } - if !f.IsDir() && (len(includeExt) < 1 || !InStrSliceWithCaseInsensitive(filepath.Ext(f.Name()), includeExt)) { + if !f.IsDir() && (len(includeExt) < 1 || !query.InStrSliceWithCaseInsensitive(filepath.Ext(f.Name()), includeExt)) { continue } @@ -2433,8 +2434,8 @@ func (c *Completer) ListFiles(path string, includeExt []string, repository strin func (c *Completer) AllColumnList() []string { m := make(map[string]bool) - c.scope.blocks[0].temporaryTables.Range(func(key, value interface{}) bool { - col := c.columnList(value.(*View)) + c.scope.Blocks[0].TemporaryTables.Range(func(key, value interface{}) bool { + col := c.columnList(value.(*query.View)) for _, s := range col { if _, ok := m[s]; !ok { m[s] = true @@ -2443,8 +2444,8 @@ func (c *Completer) AllColumnList() []string { return true }) - c.scope.Tx.cachedViews.Range(func(key, value interface{}) bool { - col := c.columnList(value.(*View)) + c.scope.Tx.CachedViews.Range(func(key, value interface{}) bool { + col := c.columnList(value.(*query.View)) for _, s := range col { if _, ok := m[s]; !ok { m[s] = true @@ -2466,21 +2467,21 @@ func (c *Completer) ColumnList(tableName string, repository string) []string { return list } - if view, ok := c.scope.blocks[0].temporaryTables.Load(tableName); ok { + if view, ok := c.scope.Blocks[0].TemporaryTables.Load(tableName); ok { list := c.columnList(view) c.tableColumns[tableName] = list return list } - if fpath, err := CreateFilePath(parser.Identifier{Literal: tableName}, repository); err == nil { - if view, ok := c.scope.Tx.cachedViews.Load(fpath); ok { + if fpath, err := query.CreateFilePath(parser.Identifier{Literal: tableName}, repository); err == nil { + if view, ok := c.scope.Tx.CachedViews.Load(fpath); ok { list := c.columnList(view) c.tableColumns[tableName] = list return list } } - if fpath, err := SearchFilePathFromAllTypes(parser.Identifier{Literal: tableName}, repository); err == nil { - if view, ok := c.scope.Tx.cachedViews.Load(fpath); ok { + if fpath, err := query.SearchFilePathFromAllTypes(parser.Identifier{Literal: tableName}, repository); err == nil { + if view, ok := c.scope.Tx.CachedViews.Load(fpath); ok { list := c.columnList(view) c.tableColumns[tableName] = list return list @@ -2490,7 +2491,7 @@ func (c *Completer) ColumnList(tableName string, repository string) []string { return nil } -func (*Completer) columnList(view *View) []string { +func (*Completer) columnList(view *query.View) []string { var list []string for _, h := range view.Header { list = append(list, h.Column) @@ -2750,10 +2751,10 @@ func (c *Completer) isTableObject(token parser.Token) bool { func (c *Completer) isFunction(token parser.Token) bool { if token.Token == parser.IDENTIFIER { - if _, ok := Functions[strings.ToUpper(token.Literal)]; ok { + if _, ok := query.Functions[strings.ToUpper(token.Literal)]; ok { return true } - return InStrSliceWithCaseInsensitive(token.Literal, c.userFuncList) + return query.InStrSliceWithCaseInsensitive(token.Literal, c.userFuncList) } return token.Token == parser.SUBSTRING || @@ -2826,7 +2827,7 @@ func (c *Completer) aggregateFunctionCandidateList(line string) readline.Candida func (c *Completer) analyticFunctionCandidateList(line string) readline.CandidateList { var cands readline.CandidateList if 0 <= c.lastIdx && c.tokens[c.lastIdx].Token == parser.FUNCTION { - if InStrSliceWithCaseInsensitive(c.tokens[c.lastIdx].Literal, []string{ + if query.InStrSliceWithCaseInsensitive(c.tokens[c.lastIdx].Literal, []string{ "FIRST_VALUE", "LAST_VALUE", "NTH_VALUE", @@ -2836,7 +2837,7 @@ func (c *Completer) analyticFunctionCandidateList(line string) readline.Candidat cands = append(cands, c.candidate("IGNORE NULLS", true)) } - if InStrSliceWithCaseInsensitive(c.tokens[c.lastIdx].Literal, c.analyticFuncs) { + if query.InStrSliceWithCaseInsensitive(c.tokens[c.lastIdx].Literal, c.analyticFuncs) { cands = append(cands, c.candidate("OVER", true)) } } diff --git a/lib/query/completer_readline_test.go b/lib/terminal/completer_readline_test.go similarity index 97% rename from lib/query/completer_readline_test.go rename to lib/terminal/completer_readline_test.go index 18e71a4..2f03d04 100644 --- a/lib/query/completer_readline_test.go +++ b/lib/terminal/completer_readline_test.go @@ -1,6 +1,6 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -package query +package terminal import ( "context" @@ -12,6 +12,7 @@ import ( "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/readline-csvq" @@ -104,19 +105,19 @@ func TestReadlineListener_OnChange(t *testing.T) { func TestCompleter_Update(t *testing.T) { defer func() { - TestTx.PreparedStatements = NewPreparedStatementMap() + TestTx.PreparedStatements = query.NewPreparedStatementMap() }() - scope := NewReferenceScope(TestTx) + scope := query.NewReferenceScope(TestTx) ctx := context.Background() - scope.SetTemporaryTable(&View{ - FileInfo: &FileInfo{Path: "view1", ViewType: ViewTypeTemporaryTable}, - Header: NewHeader("view1", []string{"col1", "col2"}), + scope.SetTemporaryTable(&query.View{ + FileInfo: &query.FileInfo{Path: "view1", ViewType: query.ViewTypeTemporaryTable}, + Header: query.NewHeader("view1", []string{"col1", "col2"}), }) - scope.SetTemporaryTable(&View{ - FileInfo: &FileInfo{Path: "view2", ViewType: ViewTypeTemporaryTable}, - Header: NewHeader("view1", []string{"col3", "col4"}), + scope.SetTemporaryTable(&query.View{ + FileInfo: &query.FileInfo{Path: "view2", ViewType: query.ViewTypeTemporaryTable}, + Header: query.NewHeader("view1", []string{"col3", "col4"}), }) _ = scope.DeclareCursor(parser.CursorDeclaration{Cursor: parser.Identifier{Literal: "cur1"}}) _ = scope.DeclareFunction(parser.FunctionDeclaration{Name: parser.Identifier{Literal: "scalarfunc"}}) @@ -132,16 +133,16 @@ func TestCompleter_Update(t *testing.T) { if len(c.flagList) != len(cmd.FlagList) || !strings.HasPrefix(c.flagList[0], cmd.FlagSign) { t.Error("flags are not set correctly") } - if len(c.runinfoList) != len(RuntimeInformatinList) || !strings.HasPrefix(c.runinfoList[0], cmd.RuntimeInformationSign) { + if len(c.runinfoList) != len(query.RuntimeInformatinList) || !strings.HasPrefix(c.runinfoList[0], cmd.RuntimeInformationSign) { t.Error("runtime information are not set correctly") } - if len(c.funcs) != len(Functions)+3 { + if len(c.funcs) != len(query.Functions)+3 { t.Error("functions are not set correctly") } - if len(c.aggFuncs) != len(AggregateFunctions)+2 { + if len(c.aggFuncs) != len(query.AggregateFunctions)+2 { t.Error("aggregate functions are not set correctly") } - if len(c.analyticFuncs) != len(AnalyticFunctions)+len(AggregateFunctions) { + if len(c.analyticFuncs) != len(query.AnalyticFunctions)+len(query.AggregateFunctions) { t.Error("analytic functions are not set correctly") } @@ -158,13 +159,13 @@ func TestCompleter_Update(t *testing.T) { if len(c.statementList) != 1 { t.Error("statement list is not set correctly") } - if len(c.funcList) != len(Functions)+3+1 || !strings.HasSuffix(c.funcList[0], "()") { + if len(c.funcList) != len(query.Functions)+3+1 || !strings.HasSuffix(c.funcList[0], "()") { t.Error("function list is not set correctly") } - if len(c.aggFuncList) != len(AggregateFunctions)+2+1 || !strings.HasSuffix(c.aggFuncList[0], "()") { + if len(c.aggFuncList) != len(query.AggregateFunctions)+2+1 || !strings.HasSuffix(c.aggFuncList[0], "()") { t.Error("aggregate function list is not set correctly") } - if len(c.analyticFuncList) != len(AnalyticFunctions)+len(AggregateFunctions)+1 || !strings.HasSuffix(c.analyticFuncList[0], "() OVER ()") { + if len(c.analyticFuncList) != len(query.AnalyticFunctions)+len(query.AggregateFunctions)+1 || !strings.HasSuffix(c.analyticFuncList[0], "() OVER ()") { t.Error("analytic function list is not set correctly") } if !reflect.DeepEqual(c.varList, []string{"@var"}) { @@ -180,7 +181,7 @@ func TestCompleter_Update(t *testing.T) { } } -var completer = NewCompleter(NewReferenceScope(TestTx)) +var completer = NewCompleter(query.NewReferenceScope(TestTx)) type completerTest struct { Name string @@ -195,8 +196,8 @@ func testCompleter(t *testing.T, f func(line string, origLine string, index int) defer func() { _ = os.Chdir(wd) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) - TestTx.PreparedStatements = NewPreparedStatementMap() + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) + TestTx.PreparedStatements = query.NewPreparedStatementMap() initFlag(TestTx.Flags) }() @@ -216,14 +217,14 @@ func testCompleter(t *testing.T, f func(line string, origLine string, index int) completer.varList = []string{"@var1", "@var2"} completer.envList = []string{"@%ENV1", "@%ENV2"} completer.enclosedEnvList = []string{"@%`ENV1`", "@%`ENV2`"} - TestTx.cachedViews.Set(&View{ - FileInfo: &FileInfo{ + TestTx.CachedViews.Set(&query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "newtable.csv"), }, - Header: NewHeader("newtable", []string{"ncol1", "ncol2", "ncol3"}), + Header: query.NewHeader("newtable", []string{"ncol1", "ncol2", "ncol3"}), }) - TestTx.cachedViews.Set(&View{ - FileInfo: &FileInfo{ + TestTx.CachedViews.Set(&query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "sub", "table2.csv"), }, }) @@ -4043,7 +4044,7 @@ func TestCompleter_ListFiles(t *testing.T) { wd, _ := os.Getwd() _ = os.Chdir(CompletionTestDir) - completer := NewCompleter(NewReferenceScope(TestTx)) + completer := NewCompleter(query.NewReferenceScope(TestTx)) for _, v := range completerListFilesTests { result := completer.ListFiles(v.Line, v.IncludeExt, v.Repository) if !reflect.DeepEqual(result, v.Expect) { @@ -4056,29 +4057,29 @@ func TestCompleter_ListFiles(t *testing.T) { func TestCompleter_AllColumnList(t *testing.T) { defer func() { - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) }() - scope := NewReferenceScope(TestTx) - scope.SetTemporaryTable(&View{ - FileInfo: &FileInfo{Path: "view1", ViewType: ViewTypeTemporaryTable}, - Header: NewHeader("view1", []string{"v1col1", "v1col2", "v1col3"}), + scope := query.NewReferenceScope(TestTx) + scope.SetTemporaryTable(&query.View{ + FileInfo: &query.FileInfo{Path: "view1", ViewType: query.ViewTypeTemporaryTable}, + Header: query.NewHeader("view1", []string{"v1col1", "v1col2", "v1col3"}), }) - scope.SetTemporaryTable(&View{FileInfo: &FileInfo{Path: "view2", ViewType: ViewTypeTemporaryTable}}) - TestTx.cachedViews.Set( - &View{ - FileInfo: &FileInfo{ + scope.SetTemporaryTable(&query.View{FileInfo: &query.FileInfo{Path: "view2", ViewType: query.ViewTypeTemporaryTable}}) + TestTx.CachedViews.Set( + &query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "newtable.csv"), }, - Header: NewHeader("newtable", []string{"ncol1", "col2", "ncol3"}), + Header: query.NewHeader("newtable", []string{"ncol1", "col2", "ncol3"}), }, ) - TestTx.cachedViews.Set( - &View{ - FileInfo: &FileInfo{ + TestTx.CachedViews.Set( + &query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "table1.csv"), }, - Header: NewHeader("newtable", []string{"tcol1", "col2", "tcol3"}), + Header: query.NewHeader("newtable", []string{"tcol1", "col2", "tcol3"}), }, ) @@ -4122,30 +4123,30 @@ func TestCompleter_ColumnList(t *testing.T) { defer func() { _ = os.Chdir(wd) - _ = TestTx.cachedViews.Clean(TestTx.FileContainer) + _ = TestTx.CachedViews.Clean(TestTx.FileContainer) initFlag(TestTx.Flags) }() - scope := NewReferenceScope(TestTx) - scope.SetTemporaryTable(&View{ - FileInfo: &FileInfo{Path: "view1", ViewType: ViewTypeTemporaryTable}, - Header: NewHeader("view1", []string{"v1col1", "v1col2", "v1col3"}), + scope := query.NewReferenceScope(TestTx) + scope.SetTemporaryTable(&query.View{ + FileInfo: &query.FileInfo{Path: "view1", ViewType: query.ViewTypeTemporaryTable}, + Header: query.NewHeader("view1", []string{"v1col1", "v1col2", "v1col3"}), }) - scope.SetTemporaryTable(&View{FileInfo: &FileInfo{Path: "view2", ViewType: ViewTypeTemporaryTable}}) - TestTx.cachedViews.Set( - &View{ - FileInfo: &FileInfo{ + scope.SetTemporaryTable(&query.View{FileInfo: &query.FileInfo{Path: "view2", ViewType: query.ViewTypeTemporaryTable}}) + TestTx.CachedViews.Set( + &query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "newtable.csv"), }, - Header: NewHeader("newtable", []string{"ncol3", "ncol2", "ncol1"}), + Header: query.NewHeader("newtable", []string{"ncol3", "ncol2", "ncol1"}), }, ) - TestTx.cachedViews.Set( - &View{ - FileInfo: &FileInfo{ + TestTx.CachedViews.Set( + &query.View{ + FileInfo: &query.FileInfo{ Path: filepath.Join(CompletionTestDir, "table1.csv"), }, - Header: NewHeader("newtable", []string{"tcol1", "tcol2", "tcol3"}), + Header: query.NewHeader("newtable", []string{"tcol1", "tcol2", "tcol3"}), }, ) @@ -4367,7 +4368,7 @@ var completerUpdateTokensTests = []struct { } func TestCompleter_UpdateTokens(t *testing.T) { - c := NewCompleter(NewReferenceScope(TestTx)) + c := NewCompleter(query.NewReferenceScope(TestTx)) c.userFuncs = []string{"userfunc"} c.userAggFuncs = []string{"aggfunc"} c.userFuncList = []string{"userfunc", "aggfunc"} diff --git a/lib/terminal/main_test.go b/lib/terminal/main_test.go new file mode 100644 index 0000000..383c0cf --- /dev/null +++ b/lib/terminal/main_test.go @@ -0,0 +1,118 @@ +package terminal + +import ( + "context" + "io" + "os" + "path/filepath" + "runtime" + "testing" + + "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/query" + + "github.com/mitchellh/go-homedir" +) + +var tempdir, _ = filepath.Abs(os.TempDir()) +var TestDir = filepath.Join(tempdir, "csvq_terminal_test") +var CompletionTestDir = filepath.Join(TestDir, "completion") +var CompletionTestSubDir = filepath.Join(TestDir, "completion", "sub") +var TestLocation = "UTC" +var TestTx, _ = query.NewTransaction(context.Background(), file.DefaultWaitTimeout, file.DefaultRetryDelay, query.NewSession()) +var TestDataDir string +var HomeDir string + +func GetWD() string { + wdir, _ := os.Getwd() + return wdir +} + +func TestMain(m *testing.M) { + os.Exit(run(m)) +} + +func run(m *testing.M) int { + defer teardown() + + setup() + return m.Run() +} + +func initFlag(flags *cmd.Flags) { + cpu := runtime.NumCPU() / 2 + if cpu < 1 { + cpu = 1 + } + + flags.Repository = "." + flags.DatetimeFormat = []string{} + flags.AnsiQuotes = false + flags.StrictEqual = false + flags.WaitTimeout = 15 + flags.ImportOptions = cmd.NewImportOptions() + flags.ExportOptions = cmd.NewExportOptions() + flags.Quiet = false + flags.LimitRecursion = 5 + flags.CPU = cpu + flags.Stats = false + flags.SetColor(false) + _ = flags.SetLocation(TestLocation) +} + +func copyfile(dstfile string, srcfile string) error { + src, err := os.Open(srcfile) + if err != nil { + return err + } + defer func() { _ = src.Close() }() + + dst, err := os.Create(dstfile) + if err != nil { + return err + } + defer func() { _ = dst.Close() }() + + _, err = io.Copy(dst, src) + if err != nil { + return err + } + + return nil +} + +func setup() { + if _, err := os.Stat(TestDir); err == nil { + _ = os.RemoveAll(TestDir) + } + if _, err := os.Stat(TestDir); os.IsNotExist(err) { + _ = os.Mkdir(TestDir, 0755) + } + if _, err := os.Stat(CompletionTestDir); os.IsNotExist(err) { + _ = os.Mkdir(CompletionTestDir, 0755) + } + if _, err := os.Stat(CompletionTestSubDir); os.IsNotExist(err) { + _ = os.Mkdir(CompletionTestSubDir, 0755) + } + + HomeDir, _ = homedir.Dir() + TestDataDir = filepath.Join(GetWD(), "..", "..", "testdata", "csv") + + _ = copyfile(filepath.Join(CompletionTestDir, "table1.csv"), filepath.Join(TestDataDir, "table1.csv")) + _ = copyfile(filepath.Join(CompletionTestDir, ".table1.csv"), filepath.Join(TestDataDir, "table1.csv")) + _ = copyfile(filepath.Join(CompletionTestDir, "source.sql"), filepath.Join(filepath.Join(GetWD(), "..", "..", "testdata"), "source.sql")) + _ = copyfile(filepath.Join(CompletionTestSubDir, "table2.csv"), filepath.Join(TestDataDir, "table2.csv")) + + _ = os.Setenv("CSVQ_TEST_ENV", "foo") + query.Version = "v1.0.0" + TestTx.Session.SetStdout(query.NewDiscard()) + TestTx.Session.SetStderr(query.NewDiscard()) + initFlag(TestTx.Flags) +} + +func teardown() { + if _, err := os.Stat(TestDir); err == nil { + _ = os.RemoveAll(TestDir) + } +} diff --git a/lib/query/terminal.go b/lib/terminal/terminal.go similarity index 82% rename from lib/query/terminal.go rename to lib/terminal/terminal.go index 276d00d..61cb4f2 100644 --- a/lib/query/terminal.go +++ b/lib/terminal/terminal.go @@ -1,4 +1,4 @@ -package query +package terminal import ( "bytes" @@ -10,27 +10,15 @@ import ( "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/excmd" "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/value" ) const ( - TerminalPrompt string = "csvq > " - TerminalContinuousPrompt string = " > " + DefaultPrompt string = "csvq > " + DefaultContinuousPrompt string = " > " ) -type VirtualTerminal interface { - ReadLine() (string, error) - Write(string) error - WriteError(string) error - SetPrompt(ctx context.Context) - SetContinuousPrompt(ctx context.Context) - SaveHistory(string) error - Teardown() error - GetSize() (int, int, error) - ReloadConfig() error - UpdateCompleter() -} - type PromptEvaluationError struct { Message string } @@ -51,14 +39,14 @@ type PromptElement struct { } type Prompt struct { - scope *ReferenceScope + scope *query.ReferenceScope sequence []PromptElement continuousSequence []PromptElement buf bytes.Buffer } -func NewPrompt(scope *ReferenceScope) *Prompt { +func NewPrompt(scope *query.ReferenceScope) *Prompt { return &Prompt{ scope: scope, } @@ -101,7 +89,7 @@ func (p *Prompt) LoadConfig() error { func (p *Prompt) RenderPrompt(ctx context.Context) (string, error) { s, err := p.Render(ctx, p.sequence) if err != nil || len(s) < 1 { - s = TerminalPrompt + s = DefaultPrompt } if p.scope.Tx.Flags.ExportOptions.Color { if strings.IndexByte(s, 0x1b) < 0 { @@ -116,7 +104,7 @@ func (p *Prompt) RenderPrompt(ctx context.Context) (string, error) { func (p *Prompt) RenderContinuousPrompt(ctx context.Context) (string, error) { s, err := p.Render(ctx, p.continuousSequence) if err != nil || len(s) < 1 { - s = TerminalContinuousPrompt + s = DefaultContinuousPrompt } if p.scope.Tx.Flags.ExportOptions.Color { if strings.IndexByte(s, 0x1b) < 0 { @@ -161,13 +149,13 @@ func (p *Prompt) Render(ctx context.Context, sequence []PromptElement) (string, case 1: expr, ok := statements[0].(parser.QueryExpression) if !ok { - return "", NewPromptEvaluationError(fmt.Sprintf(ErrMsgInvalidValueExpression, command)) + return "", NewPromptEvaluationError(fmt.Sprintf(query.ErrMsgInvalidValueExpression, command)) } if err = p.evaluate(ctx, expr); err != nil { return "", err } default: - return "", NewPromptEvaluationError(fmt.Sprintf(ErrMsgInvalidValueExpression, command)) + return "", NewPromptEvaluationError(fmt.Sprintf(query.ErrMsgInvalidValueExpression, command)) } } } @@ -177,14 +165,14 @@ func (p *Prompt) Render(ctx context.Context, sequence []PromptElement) (string, } func (p *Prompt) evaluate(ctx context.Context, expr parser.QueryExpression) error { - val, err := Evaluate(ctx, p.scope, expr) + val, err := query.Evaluate(ctx, p.scope, expr) if err != nil { - if ae, ok := err.(Error); ok { + if ae, ok := err.(query.Error); ok { err = NewPromptEvaluationError(ae.Message()) } return err } - s, _ := NewStringFormatter().Format("%s", []value.Primary{val}) + s, _ := query.NewStringFormatter().Format("%s", []value.Primary{val}) _, err = p.buf.WriteString(s) if err != nil { err = NewPromptEvaluationError(err.Error()) diff --git a/lib/query/terminal_functions.go b/lib/terminal/terminal_functions.go similarity index 66% rename from lib/query/terminal_functions.go rename to lib/terminal/terminal_functions.go index 5f57120..0bb0e49 100644 --- a/lib/query/terminal_functions.go +++ b/lib/terminal/terminal_functions.go @@ -1,11 +1,12 @@ //go:build !windows -package query +package terminal import ( "io" + "os" ) func GetStdinForREPL() io.ReadCloser { - return stdin + return os.Stdin } diff --git a/lib/query/terminal_functions_windows.go b/lib/terminal/terminal_functions_windows.go similarity index 89% rename from lib/query/terminal_functions_windows.go rename to lib/terminal/terminal_functions_windows.go index bab0fa4..4339a8f 100644 --- a/lib/query/terminal_functions_windows.go +++ b/lib/terminal/terminal_functions_windows.go @@ -1,6 +1,6 @@ //go:build windows -package query +package terminal import ( "io" diff --git a/lib/query/terminal_general.go b/lib/terminal/terminal_general.go similarity index 86% rename from lib/query/terminal_general.go rename to lib/terminal/terminal_general.go index bca148e..1004e47 100644 --- a/lib/query/terminal_general.go +++ b/lib/terminal/terminal_general.go @@ -1,12 +1,13 @@ //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows -package query +package terminal import ( "context" "io" "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/query" "golang.org/x/crypto/ssh/terminal" ) @@ -17,10 +18,10 @@ type SSHTerminal struct { origState *terminal.State rawState *terminal.State prompt *Prompt - tx *Transaction + tx *query.Transaction } -func NewTerminal(ctx context.Context, scope *ReferenceScope) (VirtualTerminal, error) { +func NewTerminal(ctx context.Context, scope *query.ReferenceScope) (query.VirtualTerminal, error) { stdin := int(scope.Tx.Session.ScreenFd()) origState, err := terminal.MakeRaw(stdin) if err != nil { @@ -38,7 +39,7 @@ func NewTerminal(ctx context.Context, scope *ReferenceScope) (VirtualTerminal, e } t := SSHTerminal{ - terminal: terminal.NewTerminal(NewStdIO(scope.Tx.Session), scope.Tx.Palette.Render(cmd.PromptEffect, TerminalPrompt)), + terminal: terminal.NewTerminal(NewStdIO(scope.Tx.Session), scope.Tx.Palette.Render(cmd.PromptEffect, DefaultPrompt)), stdin: stdin, origState: origState, rawState: rawState, @@ -83,7 +84,7 @@ func (t SSHTerminal) Write(s string) error { } func (t SSHTerminal) WriteError(s string) error { - _, err := t.tx.Session.stderr.Write([]byte(s)) + _, err := t.tx.Session.Stderr().Write([]byte(s)) return err } @@ -132,9 +133,9 @@ func (sh *StdIO) Write(p []byte) (n int, err error) { return sh.writer.Write(p) } -func NewStdIO(sess *Session) *StdIO { +func NewStdIO(sess *query.Session) *StdIO { return &StdIO{ - reader: sess.stdin, - writer: sess.stdout, + reader: sess.Stdin(), + writer: sess.Stdout(), } } diff --git a/lib/query/terminal_readline.go b/lib/terminal/terminal_readline.go similarity index 95% rename from lib/query/terminal_readline.go rename to lib/terminal/terminal_readline.go index 72fa81d..7d923bd 100644 --- a/lib/query/terminal_readline.go +++ b/lib/terminal/terminal_readline.go @@ -1,6 +1,6 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -package query +package terminal import ( "context" @@ -9,6 +9,7 @@ import ( "path/filepath" "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/query" "github.com/mitchellh/go-homedir" "github.com/mithrandie/readline-csvq" @@ -20,10 +21,10 @@ type ReadLineTerminal struct { prompt *Prompt env *cmd.Environment completer *Completer - tx *Transaction + tx *query.Transaction } -func NewTerminal(ctx context.Context, scope *ReferenceScope) (VirtualTerminal, error) { +func NewTerminal(ctx context.Context, scope *query.ReferenceScope) (query.VirtualTerminal, error) { fd := int(scope.Tx.Session.ScreenFd()) limit := *scope.Tx.Environment.InteractiveShell.HistoryLimit diff --git a/lib/query/terminal_readline_test.go b/lib/terminal/terminal_readline_test.go similarity index 98% rename from lib/query/terminal_readline_test.go rename to lib/terminal/terminal_readline_test.go index fe2584c..a1ca2ac 100644 --- a/lib/query/terminal_readline_test.go +++ b/lib/terminal/terminal_readline_test.go @@ -1,6 +1,6 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -package query +package terminal import ( "path/filepath" diff --git a/lib/query/terminal_test.go b/lib/terminal/terminal_test.go similarity index 95% rename from lib/query/terminal_test.go rename to lib/terminal/terminal_test.go index eee1e90..cd7a17d 100644 --- a/lib/query/terminal_test.go +++ b/lib/terminal/terminal_test.go @@ -1,4 +1,4 @@ -package query +package terminal import ( "context" @@ -7,6 +7,7 @@ import ( "github.com/mithrandie/csvq/lib/excmd" "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/value" ) @@ -40,7 +41,7 @@ var promptLoadConfigTests = []struct { } func TestPrompt_LoadConfig(t *testing.T) { - prompt := NewPrompt(NewReferenceScope(TestTx)) + prompt := NewPrompt(query.NewReferenceScope(TestTx)) for _, v := range promptLoadConfigTests { TestTx.Environment.InteractiveShell.Prompt = v.Prompt @@ -75,7 +76,7 @@ var promptRenderPromptTests = []struct { { Sequence: nil, UseColor: false, - Expect: TerminalPrompt, + Expect: DefaultPrompt, }, { Sequence: []PromptElement{ @@ -106,7 +107,7 @@ func TestPrompt_RenderPrompt(t *testing.T) { initFlag(TestTx.Flags) }() - prompt := NewPrompt(NewReferenceScope(TestTx)) + prompt := NewPrompt(query.NewReferenceScope(TestTx)) for _, v := range promptRenderPromptTests { TestTx.UseColor(v.UseColor) @@ -141,7 +142,7 @@ var promptRenderContinuousPromptTests = []struct { { Sequence: nil, UseColor: false, - Expect: TerminalContinuousPrompt, + Expect: DefaultContinuousPrompt, }, { Sequence: []PromptElement{ @@ -172,7 +173,7 @@ func TestPrompt_RenderContinuousPrompt(t *testing.T) { initFlag(TestTx.Flags) }() - prompt := NewPrompt(NewReferenceScope(TestTx)) + prompt := NewPrompt(query.NewReferenceScope(TestTx)) for _, v := range promptRenderContinuousPromptTests { TestTx.UseColor(v.UseColor) @@ -262,7 +263,7 @@ var promptRenderTests = []struct { } func TestPrompt_Render(t *testing.T) { - scope := NewReferenceScope(TestTx) + scope := query.NewReferenceScope(TestTx) _ = scope.DeclareVariableDirectly(parser.Variable{Name: "var"}, value.NewString("abc")) prompt := NewPrompt(scope) @@ -299,7 +300,7 @@ var promptStripEscapeSequenceTests = []struct { } func TestPrompt_StripEscapeSequence(t *testing.T) { - prompt := NewPrompt(NewReferenceScope(TestTx)) + prompt := NewPrompt(query.NewReferenceScope(TestTx)) for _, v := range promptStripEscapeSequenceTests { result := prompt.StripEscapeSequence(v.Input) From b5015ba6741fa2b8ea2a210a0d040cd8eb3cb0cb Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 20:51:12 +0900 Subject: [PATCH 05/17] Refactor: Move processes in main.go to package cli. --- lib/cli/app.go | 560 +++++++++++++++++++++++++++++++++++++ help.go => lib/cli/help.go | 7 +- main.go | 555 +----------------------------------- 3 files changed, 566 insertions(+), 556 deletions(-) create mode 100644 lib/cli/app.go rename help.go => lib/cli/help.go (97%) diff --git a/lib/cli/app.go b/lib/cli/app.go new file mode 100644 index 0000000..a17d0b0 --- /dev/null +++ b/lib/cli/app.go @@ -0,0 +1,560 @@ +package cli + +import ( + "context" + "log" + "os" + "os/signal" + + "github.com/mithrandie/csvq/lib/action" + "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/query" + + "github.com/urfave/cli/v2" +) + +func Run() { + action.CurrentVersion, _ = action.ParseVersion(query.Version) + if !action.CurrentVersion.IsEmpty() { + query.Version = action.CurrentVersion.String() + } + + cli.AppHelpTemplate = appHHelpTemplate + cli.CommandHelpTemplate = commandHelpTemplate + + app := cli.NewApp() + + app.Name = "csvq" + app.Usage = "SQL-like query language for csv" + app.ArgsUsage = "[query|argument]" + app.Version = query.Version + app.OnUsageError = onUsageError + app.Flags = []cli.Flag{ + &cli.StringFlag{ + Name: "repository", + Aliases: []string{"r"}, + Usage: "directory `PATH` where files are located", + }, + &cli.StringFlag{ + Name: "timezone", + Aliases: []string{"z"}, + Value: "Local", + Usage: "default timezone", + }, + &cli.StringFlag{ + Name: "datetime-format", + Aliases: []string{"t"}, + Usage: "datetime format to parse strings", + }, + &cli.BoolFlag{ + Name: "ansi-quotes", + Aliases: []string{"k"}, + Usage: "use double quotation mark as identifier enclosure", + }, + &cli.BoolFlag{ + Name: "strict-equal", + Aliases: []string{"g"}, + Usage: "compare strictly that two values are equal for DISTINCT, GROUP BY and ORDER BY", + }, + &cli.Float64Flag{ + Name: "wait-timeout", + Aliases: []string{"w"}, + Value: 10, + Usage: "limit of the waiting time in seconds to wait for locked files to be released", + }, + &cli.StringFlag{ + Name: "source", + Aliases: []string{"s"}, + Usage: "load query or statements from `FILE`", + }, + &cli.StringFlag{ + Name: "import-format", + Aliases: []string{"i"}, + Value: "CSV", + Usage: "default format to load files", + }, + &cli.StringFlag{ + Name: "delimiter", + Aliases: []string{"d"}, + Value: ",", + Usage: "field delimiter for CSV", + }, + &cli.BoolFlag{ + Name: "allow-uneven-fields", + Usage: "allow loading CSV files with uneven field length", + }, + &cli.StringFlag{ + Name: "delimiter-positions", + Aliases: []string{"m"}, + Usage: "delimiter positions for FIXED", + }, + &cli.StringFlag{ + Name: "json-query", + Aliases: []string{"j"}, + Usage: "`QUERY` for JSON", + }, + &cli.StringFlag{ + Name: "encoding", + Aliases: []string{"e"}, + Value: "AUTO", + Usage: "file encoding", + }, + &cli.BoolFlag{ + Name: "no-header", + Aliases: []string{"n"}, + Usage: "import the first line as a record", + }, + &cli.BoolFlag{ + Name: "without-null", + Aliases: []string{"a"}, + Usage: "parse empty fields as empty strings", + }, + &cli.StringFlag{ + Name: "out", + Aliases: []string{"o"}, + Usage: "export result sets of select queries to `FILE`", + }, + &cli.BoolFlag{ + Name: "strip-ending-line-break", + Aliases: []string{"T"}, + Usage: "strip line break from the end of files and query results", + }, + &cli.StringFlag{ + Name: "format", + Aliases: []string{"f"}, + Usage: "format of query results. (default: \"CSV\" for output to pipe, \"TEXT\" otherwise)", + }, + &cli.StringFlag{ + Name: "write-encoding", + Aliases: []string{"E"}, + Value: "UTF8", + Usage: "character encoding of query results", + }, + &cli.StringFlag{ + Name: "write-delimiter", + Aliases: []string{"D"}, + Value: ",", + Usage: "field delimiter for CSV in query results", + }, + &cli.StringFlag{ + Name: "write-delimiter-positions", + Aliases: []string{"M"}, + Usage: "delimiter positions for FIXED in query results", + }, + &cli.BoolFlag{ + Name: "without-header", + Aliases: []string{"N"}, + Usage: "export result sets of select queries without the header line", + }, + &cli.StringFlag{ + Name: "line-break", + Aliases: []string{"l"}, + Value: "LF", + Usage: "line break in query results", + }, + &cli.BoolFlag{ + Name: "enclose-all", + Aliases: []string{"Q"}, + Usage: "enclose all string values in CSV and TSV", + }, + &cli.StringFlag{ + Name: "json-escape", + Aliases: []string{"J"}, + Value: "BACKSLASH", + Usage: "JSON escape type", + }, + &cli.BoolFlag{ + Name: "pretty-print", + Aliases: []string{"P"}, + Usage: "make JSON output easier to read in query results", + }, + &cli.BoolFlag{ + Name: "east-asian-encoding", + Aliases: []string{"W"}, + Usage: "count ambiguous characters as fullwidth", + }, + &cli.BoolFlag{ + Name: "count-diacritical-sign", + Aliases: []string{"S"}, + Usage: "count diacritical signs as halfwidth", + }, + &cli.BoolFlag{ + Name: "count-format-code", + Aliases: []string{"A"}, + Usage: "count format characters and zero-width spaces as halfwidth", + }, + &cli.BoolFlag{ + Name: "color", + Aliases: []string{"c"}, + Usage: "use ANSI color escape sequences", + }, + &cli.BoolFlag{ + Name: "quiet", + Aliases: []string{"q"}, + Usage: "suppress operation log output", + }, + &cli.IntFlag{ + Name: "limit-recursion", + Value: 1000, + Usage: "maximum number of iterations for recursive queries", + }, + &cli.IntFlag{ + Name: "cpu", + Aliases: []string{"p"}, + Value: cmd.GetDefaultNumberOfCPU(), + Usage: "hint for the number of cpu cores to be used", + }, + &cli.BoolFlag{ + Name: "stats", + Aliases: []string{"x"}, + Usage: "show execution time and memory statistics", + }, + } + + app.Commands = []*cli.Command{ + { + Name: "fields", + Usage: "Show fields in a file", + ArgsUsage: "DATA_FILE_PATH", + Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { + if 1 != c.NArg() { + return query.NewIncorrectCommandUsageError("fields subcommand takes exactly 1 argument") + } + table := c.Args().First() + return action.ShowFields(ctx, proc, table) + }), + }, + { + Name: "calc", + Usage: "Calculate a value from stdin", + ArgsUsage: "expression", + Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { + if !proc.Tx.Session.CanReadStdin { + return query.NewIncorrectCommandUsageError(query.ErrMsgStdinEmpty) + } + if 1 != c.NArg() { + return query.NewIncorrectCommandUsageError("calc subcommand takes exactly 1 argument") + } + expr := c.Args().First() + return action.Calc(ctx, proc, expr) + }), + }, + { + Name: "syntax", + Usage: "Print syntax", + ArgsUsage: "[search_word ...]", + Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { + words := append([]string{c.Args().First()}, c.Args().Tail()...) + return action.Syntax(ctx, proc, words) + }), + }, + { + Name: "check-update", + Usage: "Check for updates", + ArgsUsage: " ", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "include-pre-release", + Usage: "check including pre-release version", + }, + }, + Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { + if 0 < c.NArg() { + return query.NewIncorrectCommandUsageError("check-update subcommand takes no argument") + } + + includePreRelease := false + if c.IsSet("include-pre-release") { + includePreRelease = c.Bool("include-pre-release") + } + return action.CheckUpdate(includePreRelease) + }), + }, + } + + for i := range app.Commands { + app.Commands[i].OnUsageError = onUsageError + } + + app.Action = commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { + queryString, path, err := readQuery(ctx, c, proc.Tx) + if err != nil { + return err + } + + if len(queryString) < 1 { + err = action.LaunchInteractiveShell(ctx, proc) + } else { + err = action.Run(ctx, proc, queryString, path, c.String("out")) + } + + return err + }) + + if err := app.Run(os.Args); err != nil { + log.Fatalln(err.Error()) + } +} + +func onUsageError(c *cli.Context, err error, isSubcommand bool) error { + if isSubcommand { + if e := cli.ShowCommandHelp(c, c.Command.Name); e != nil { + println(e.Error()) + } + } + if _, ok := err.(*query.IncorrectCommandUsageError); !ok { + err = query.NewIncorrectCommandUsageError(err.Error()) + } + return Exit(err, nil) +} + +func commandAction(fn func(ctx context.Context, c *cli.Context, proc *query.Processor) error) func(c *cli.Context) error { + return func(c *cli.Context) (err error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + session := query.NewSession() + tx, e := query.NewTransaction(ctx, file.DefaultWaitTimeout, file.DefaultRetryDelay, session) + if e != nil { + return Exit(e, nil) + } + + proc := query.NewProcessor(tx) + defer func() { + if e := proc.AutoRollback(); e != nil { + proc.LogError(e.Error()) + } + if e := proc.ReleaseResourcesWithErrors(); e != nil { + proc.LogError(e.Error()) + } + + if err != nil { + if _, ok := err.(*query.IncorrectCommandUsageError); ok { + err = onUsageError(c, err, 0 < len(c.Command.Name)) + } else { + err = Exit(err, proc.Tx) + } + } + }() + + // Handle signals + ch := make(chan os.Signal, 1) + signal.Notify(ch, action.Signals...) + var signalReceived error + + go func() { + sig := <-ch + signalReceived = query.NewSignalReceived(sig) + cancel() + }() + + // Run pre-load commands + if err = runPreloadCommands(ctx, proc); err != nil { + return + } + + // Overwrite Flags with Command Options + if err = overwriteFlags(c, proc.Tx); err != nil { + return + } + + err = fn(ctx, c, proc) + if signalReceived != nil { + err = signalReceived + } + return + } +} + +func overwriteFlags(c *cli.Context, tx *query.Transaction) error { + if c.IsSet("repository") { + if err := tx.SetFlag(cmd.RepositoryFlag, c.String("repository")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("timezone") { + if err := tx.SetFlag(cmd.TimezoneFlag, c.String("timezone")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("datetime-format") { + _ = tx.SetFlag(cmd.DatetimeFormatFlag, c.String("datetime-format")) + } + if c.IsSet("ansi-quotes") { + _ = tx.SetFlag(cmd.AnsiQuotesFlag, c.Bool("ansi-quotes")) + } + if c.IsSet("strict-equal") { + _ = tx.SetFlag(cmd.StrictEqualFlag, c.Bool("strict-equal")) + } + + if c.IsSet("wait-timeout") { + _ = tx.SetFlag(cmd.WaitTimeoutFlag, c.Float64("wait-timeout")) + } + if c.IsSet("color") { + _ = tx.SetFlag(cmd.ColorFlag, c.Bool("color")) + } + + if c.IsSet("import-format") { + if err := tx.SetFlag(cmd.ImportFormatFlag, c.String("import-format")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("delimiter") { + if err := tx.SetFlag(cmd.DelimiterFlag, c.String("delimiter")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("allow-uneven-fields") { + _ = tx.SetFlag(cmd.AllowUnevenFieldsFlag, c.Bool("allow-uneven-fields")) + } + if c.IsSet("delimiter-positions") { + if err := tx.SetFlag(cmd.DelimiterPositionsFlag, c.String("delimiter-positions")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("json-query") { + _ = tx.SetFlag(cmd.JsonQueryFlag, c.String("json-query")) + } + if c.IsSet("encoding") { + if err := tx.SetFlag(cmd.EncodingFlag, c.String("encoding")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("no-header") { + _ = tx.SetFlag(cmd.NoHeaderFlag, c.Bool("no-header")) + } + if c.IsSet("without-null") { + _ = tx.SetFlag(cmd.WithoutNullFlag, c.Bool("without-null")) + } + + if c.IsSet("strip-ending-line-break") { + _ = tx.SetFlag(cmd.StripEndingLineBreakFlag, c.Bool("strip-ending-line-break")) + } + + if err := tx.SetFormatFlag(c.String("format"), c.String("out")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + + if c.IsSet("write-encoding") { + if err := tx.SetFlag(cmd.ExportEncodingFlag, c.String("write-encoding")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("write-delimiter") { + if err := tx.SetFlag(cmd.ExportDelimiterFlag, c.String("write-delimiter")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("write-delimiter-positions") { + if err := tx.SetFlag(cmd.ExportDelimiterPositionsFlag, c.String("write-delimiter-positions")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("without-header") { + _ = tx.SetFlag(cmd.WithoutHeaderFlag, c.Bool("without-header")) + } + if c.IsSet("line-break") { + if err := tx.SetFlag(cmd.LineBreakFlag, c.String("line-break")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("enclose-all") { + _ = tx.SetFlag(cmd.EncloseAllFlag, c.Bool("enclose-all")) + } + if c.IsSet("json-escape") { + if err := tx.SetFlag(cmd.JsonEscapeFlag, c.String("json-escape")); err != nil { + return query.NewIncorrectCommandUsageError(err.Error()) + } + } + if c.IsSet("pretty-print") { + _ = tx.SetFlag(cmd.PrettyPrintFlag, c.Bool("pretty-print")) + } + + if c.IsSet("east-asian-encoding") { + _ = tx.SetFlag(cmd.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) + } + if c.IsSet("count-diacritical-sign") { + _ = tx.SetFlag(cmd.CountDiacriticalSignFlag, c.Bool("count-diacritical-sign")) + } + if c.IsSet("count-format-code") { + _ = tx.SetFlag(cmd.CountFormatCodeFlag, c.Bool("count-format-code")) + } + + if c.IsSet("quiet") { + _ = tx.SetFlag(cmd.QuietFlag, c.Bool("quiet")) + } + if c.IsSet("limit-recursion") { + _ = tx.SetFlag(cmd.LimitRecursion, c.Int64("limit-recursion")) + } + if c.IsSet("cpu") { + _ = tx.SetFlag(cmd.CPUFlag, c.Int64("cpu")) + } + if c.IsSet("stats") { + _ = tx.SetFlag(cmd.StatsFlag, c.Bool("stats")) + } + + return nil +} + +func runPreloadCommands(ctx context.Context, proc *query.Processor) (err error) { + files := cmd.GetSpecialFilePath(cmd.PreloadCommandFileName) + for _, fpath := range files { + if !file.Exists(fpath) { + continue + } + + statements, err := query.LoadStatementsFromFile(ctx, proc.Tx, parser.Identifier{Literal: fpath}) + if err != nil { + return err + } + + if _, err := proc.Execute(ctx, statements); err != nil { + return err + } + } + return nil +} + +func readQuery(ctx context.Context, c *cli.Context, tx *query.Transaction) (queryString string, path string, err error) { + if c.IsSet("source") && 0 < len(c.String("source")) { + if 0 < c.NArg() { + err = query.NewIncorrectCommandUsageError("no argument can be passed when \"--source\" option is specified") + } else { + path = c.String("source") + queryString, err = query.LoadContentsFromFile(ctx, tx, parser.Identifier{Literal: path}) + } + } else { + switch c.NArg() { + case 0: + // Launch interactive shell + case 1: + queryString = c.Args().First() + default: + err = query.NewIncorrectCommandUsageError("csvq command takes exactly 1 argument") + } + } + return +} + +func Exit(err error, tx *query.Transaction) error { + if err == nil { + return nil + } + if exit, ok := err.(*query.ForcedExit); ok && exit.Code() == 0 { + return nil + } + + code := query.ReturnCodeApplicationError + message := err.Error() + if tx != nil { + message = tx.Error(message) + } + + if apperr, ok := err.(query.Error); ok { + code = apperr.Code() + } + + return cli.Exit(message, code) +} diff --git a/help.go b/lib/cli/help.go similarity index 97% rename from help.go rename to lib/cli/help.go index 12e373f..665d9a0 100644 --- a/help.go +++ b/lib/cli/help.go @@ -1,4 +1,4 @@ -package main +package cli var appHHelpTemplate = `NAME: {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} @@ -51,13 +51,14 @@ var commandHelpTemplate = `NAME: {{.HelpName}} - {{.Usage}} USAGE: - csvq [options] {{.Name}}{{if .VisibleFlags}} [subcommand options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} -{{if .Category}} + csvq [options] {{.Name}}{{if .VisibleFlags}} [subcommand options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}} + CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: {{.Description}}{{end}}{{if .VisibleFlags}} + OPTIONS: {{range .VisibleFlags}}{{.}} {{end}}{{end}} diff --git a/main.go b/main.go index 62f44f4..71251fd 100644 --- a/main.go +++ b/main.go @@ -1,560 +1,9 @@ package main import ( - "context" - "log" - "os" - "os/signal" - - "github.com/mithrandie/csvq/lib/action" - "github.com/mithrandie/csvq/lib/cmd" - "github.com/mithrandie/csvq/lib/file" - "github.com/mithrandie/csvq/lib/parser" - "github.com/mithrandie/csvq/lib/query" - - "github.com/urfave/cli/v2" + "github.com/mithrandie/csvq/lib/cli" ) func main() { - action.CurrentVersion, _ = action.ParseVersion(query.Version) - if !action.CurrentVersion.IsEmpty() { - query.Version = action.CurrentVersion.String() - } - - cli.AppHelpTemplate = appHHelpTemplate - cli.CommandHelpTemplate = commandHelpTemplate - - app := cli.NewApp() - - app.Name = "csvq" - app.Usage = "SQL-like query language for csv" - app.ArgsUsage = "[query|argument]" - app.Version = query.Version - app.OnUsageError = onUsageError - app.Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "repository", - Aliases: []string{"r"}, - Usage: "directory `PATH` where files are located", - }, - &cli.StringFlag{ - Name: "timezone", - Aliases: []string{"z"}, - Value: "Local", - Usage: "default timezone", - }, - &cli.StringFlag{ - Name: "datetime-format", - Aliases: []string{"t"}, - Usage: "datetime format to parse strings", - }, - &cli.BoolFlag{ - Name: "ansi-quotes", - Aliases: []string{"k"}, - Usage: "use double quotation mark as identifier enclosure", - }, - &cli.BoolFlag{ - Name: "strict-equal", - Aliases: []string{"g"}, - Usage: "compare strictly that two values are equal for DISTINCT, GROUP BY and ORDER BY", - }, - &cli.Float64Flag{ - Name: "wait-timeout", - Aliases: []string{"w"}, - Value: 10, - Usage: "limit of the waiting time in seconds to wait for locked files to be released", - }, - &cli.StringFlag{ - Name: "source", - Aliases: []string{"s"}, - Usage: "load query or statements from `FILE`", - }, - &cli.StringFlag{ - Name: "import-format", - Aliases: []string{"i"}, - Value: "CSV", - Usage: "default format to load files", - }, - &cli.StringFlag{ - Name: "delimiter", - Aliases: []string{"d"}, - Value: ",", - Usage: "field delimiter for CSV", - }, - &cli.BoolFlag{ - Name: "allow-uneven-fields", - Usage: "allow loading CSV files with uneven field length", - }, - &cli.StringFlag{ - Name: "delimiter-positions", - Aliases: []string{"m"}, - Usage: "delimiter positions for FIXED", - }, - &cli.StringFlag{ - Name: "json-query", - Aliases: []string{"j"}, - Usage: "`QUERY` for JSON", - }, - &cli.StringFlag{ - Name: "encoding", - Aliases: []string{"e"}, - Value: "AUTO", - Usage: "file encoding", - }, - &cli.BoolFlag{ - Name: "no-header", - Aliases: []string{"n"}, - Usage: "import the first line as a record", - }, - &cli.BoolFlag{ - Name: "without-null", - Aliases: []string{"a"}, - Usage: "parse empty fields as empty strings", - }, - &cli.StringFlag{ - Name: "out", - Aliases: []string{"o"}, - Usage: "export result sets of select queries to `FILE`", - }, - &cli.BoolFlag{ - Name: "strip-ending-line-break", - Aliases: []string{"T"}, - Usage: "strip line break from the end of files and query results", - }, - &cli.StringFlag{ - Name: "format", - Aliases: []string{"f"}, - Usage: "format of query results. (default: \"CSV\" for output to pipe, \"TEXT\" otherwise)", - }, - &cli.StringFlag{ - Name: "write-encoding", - Aliases: []string{"E"}, - Value: "UTF8", - Usage: "character encoding of query results", - }, - &cli.StringFlag{ - Name: "write-delimiter", - Aliases: []string{"D"}, - Value: ",", - Usage: "field delimiter for CSV in query results", - }, - &cli.StringFlag{ - Name: "write-delimiter-positions", - Aliases: []string{"M"}, - Usage: "delimiter positions for FIXED in query results", - }, - &cli.BoolFlag{ - Name: "without-header", - Aliases: []string{"N"}, - Usage: "export result sets of select queries without the header line", - }, - &cli.StringFlag{ - Name: "line-break", - Aliases: []string{"l"}, - Value: "LF", - Usage: "line break in query results", - }, - &cli.BoolFlag{ - Name: "enclose-all", - Aliases: []string{"Q"}, - Usage: "enclose all string values in CSV and TSV", - }, - &cli.StringFlag{ - Name: "json-escape", - Aliases: []string{"J"}, - Value: "BACKSLASH", - Usage: "JSON escape type", - }, - &cli.BoolFlag{ - Name: "pretty-print", - Aliases: []string{"P"}, - Usage: "make JSON output easier to read in query results", - }, - &cli.BoolFlag{ - Name: "east-asian-encoding", - Aliases: []string{"W"}, - Usage: "count ambiguous characters as fullwidth", - }, - &cli.BoolFlag{ - Name: "count-diacritical-sign", - Aliases: []string{"S"}, - Usage: "count diacritical signs as halfwidth", - }, - &cli.BoolFlag{ - Name: "count-format-code", - Aliases: []string{"A"}, - Usage: "count format characters and zero-width spaces as halfwidth", - }, - &cli.BoolFlag{ - Name: "color", - Aliases: []string{"c"}, - Usage: "use ANSI color escape sequences", - }, - &cli.BoolFlag{ - Name: "quiet", - Aliases: []string{"q"}, - Usage: "suppress operation log output", - }, - &cli.IntFlag{ - Name: "limit-recursion", - Value: 1000, - Usage: "maximum number of iterations for recursive queries", - }, - &cli.IntFlag{ - Name: "cpu", - Aliases: []string{"p"}, - Value: cmd.GetDefaultNumberOfCPU(), - Usage: "hint for the number of cpu cores to be used", - }, - &cli.BoolFlag{ - Name: "stats", - Aliases: []string{"x"}, - Usage: "show execution time and memory statistics", - }, - } - - app.Commands = []*cli.Command{ - { - Name: "fields", - Usage: "Show fields in a file", - ArgsUsage: "DATA_FILE_PATH", - Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { - if 1 != c.NArg() { - return query.NewIncorrectCommandUsageError("fields subcommand takes exactly 1 argument") - } - table := c.Args().First() - return action.ShowFields(ctx, proc, table) - }), - }, - { - Name: "calc", - Usage: "Calculate a value from stdin", - ArgsUsage: "expression", - Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { - if !proc.Tx.Session.CanReadStdin { - return query.NewIncorrectCommandUsageError(query.ErrMsgStdinEmpty) - } - if 1 != c.NArg() { - return query.NewIncorrectCommandUsageError("calc subcommand takes exactly 1 argument") - } - expr := c.Args().First() - return action.Calc(ctx, proc, expr) - }), - }, - { - Name: "syntax", - Usage: "Print syntax", - ArgsUsage: "[search_word ...]", - Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { - words := append([]string{c.Args().First()}, c.Args().Tail()...) - return action.Syntax(ctx, proc, words) - }), - }, - { - Name: "check-update", - Usage: "Check for updates", - ArgsUsage: " ", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "include-pre-release", - Usage: "check including pre-release version", - }, - }, - Action: commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { - if 0 < c.NArg() { - return query.NewIncorrectCommandUsageError("check-update subcommand takes no argument") - } - - includePreRelease := false - if c.IsSet("include-pre-release") { - includePreRelease = c.Bool("include-pre-release") - } - return action.CheckUpdate(includePreRelease) - }), - }, - } - - for i := range app.Commands { - app.Commands[i].OnUsageError = onUsageError - } - - app.Action = commandAction(func(ctx context.Context, c *cli.Context, proc *query.Processor) error { - queryString, path, err := readQuery(ctx, c, proc.Tx) - if err != nil { - return err - } - - if len(queryString) < 1 { - err = action.LaunchInteractiveShell(ctx, proc) - } else { - err = action.Run(ctx, proc, queryString, path, c.String("out")) - } - - return err - }) - - if err := app.Run(os.Args); err != nil { - log.Fatalln(err.Error()) - } -} - -func onUsageError(c *cli.Context, err error, isSubcommand bool) error { - if isSubcommand { - if e := cli.ShowCommandHelp(c, c.Command.Name); e != nil { - println(e.Error()) - } - } - if _, ok := err.(*query.IncorrectCommandUsageError); !ok { - err = query.NewIncorrectCommandUsageError(err.Error()) - } - return Exit(err, nil) -} - -func commandAction(fn func(ctx context.Context, c *cli.Context, proc *query.Processor) error) func(c *cli.Context) error { - return func(c *cli.Context) (err error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - session := query.NewSession() - tx, e := query.NewTransaction(ctx, file.DefaultWaitTimeout, file.DefaultRetryDelay, session) - if e != nil { - return Exit(e, nil) - } - - proc := query.NewProcessor(tx) - defer func() { - if e := proc.AutoRollback(); e != nil { - proc.LogError(e.Error()) - } - if e := proc.ReleaseResourcesWithErrors(); e != nil { - proc.LogError(e.Error()) - } - - if err != nil { - if _, ok := err.(*query.IncorrectCommandUsageError); ok { - err = onUsageError(c, err, 0 < len(c.Command.Name)) - } else { - err = Exit(err, proc.Tx) - } - } - }() - - // Handle signals - ch := make(chan os.Signal, 1) - signal.Notify(ch, action.Signals...) - var signalReceived error - - go func() { - sig := <-ch - signalReceived = query.NewSignalReceived(sig) - cancel() - }() - - // Run pre-load commands - if err = runPreloadCommands(ctx, proc); err != nil { - return - } - - // Overwrite Flags with Command Options - if err = overwriteFlags(c, proc.Tx); err != nil { - return - } - - err = fn(ctx, c, proc) - if signalReceived != nil { - err = signalReceived - } - return - } -} - -func overwriteFlags(c *cli.Context, tx *query.Transaction) error { - if c.IsSet("repository") { - if err := tx.SetFlag(cmd.RepositoryFlag, c.String("repository")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("timezone") { - if err := tx.SetFlag(cmd.TimezoneFlag, c.String("timezone")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("datetime-format") { - _ = tx.SetFlag(cmd.DatetimeFormatFlag, c.String("datetime-format")) - } - if c.IsSet("ansi-quotes") { - _ = tx.SetFlag(cmd.AnsiQuotesFlag, c.Bool("ansi-quotes")) - } - if c.IsSet("strict-equal") { - _ = tx.SetFlag(cmd.StrictEqualFlag, c.Bool("strict-equal")) - } - - if c.IsSet("wait-timeout") { - _ = tx.SetFlag(cmd.WaitTimeoutFlag, c.Float64("wait-timeout")) - } - if c.IsSet("color") { - _ = tx.SetFlag(cmd.ColorFlag, c.Bool("color")) - } - - if c.IsSet("import-format") { - if err := tx.SetFlag(cmd.ImportFormatFlag, c.String("import-format")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("delimiter") { - if err := tx.SetFlag(cmd.DelimiterFlag, c.String("delimiter")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("allow-uneven-fields") { - _ = tx.SetFlag(cmd.AllowUnevenFieldsFlag, c.Bool("allow-uneven-fields")) - } - if c.IsSet("delimiter-positions") { - if err := tx.SetFlag(cmd.DelimiterPositionsFlag, c.String("delimiter-positions")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("json-query") { - _ = tx.SetFlag(cmd.JsonQueryFlag, c.String("json-query")) - } - if c.IsSet("encoding") { - if err := tx.SetFlag(cmd.EncodingFlag, c.String("encoding")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("no-header") { - _ = tx.SetFlag(cmd.NoHeaderFlag, c.Bool("no-header")) - } - if c.IsSet("without-null") { - _ = tx.SetFlag(cmd.WithoutNullFlag, c.Bool("without-null")) - } - - if c.IsSet("strip-ending-line-break") { - _ = tx.SetFlag(cmd.StripEndingLineBreakFlag, c.Bool("strip-ending-line-break")) - } - - if err := tx.SetFormatFlag(c.String("format"), c.String("out")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - - if c.IsSet("write-encoding") { - if err := tx.SetFlag(cmd.ExportEncodingFlag, c.String("write-encoding")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("write-delimiter") { - if err := tx.SetFlag(cmd.ExportDelimiterFlag, c.String("write-delimiter")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("write-delimiter-positions") { - if err := tx.SetFlag(cmd.ExportDelimiterPositionsFlag, c.String("write-delimiter-positions")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("without-header") { - _ = tx.SetFlag(cmd.WithoutHeaderFlag, c.Bool("without-header")) - } - if c.IsSet("line-break") { - if err := tx.SetFlag(cmd.LineBreakFlag, c.String("line-break")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("enclose-all") { - _ = tx.SetFlag(cmd.EncloseAllFlag, c.Bool("enclose-all")) - } - if c.IsSet("json-escape") { - if err := tx.SetFlag(cmd.JsonEscapeFlag, c.String("json-escape")); err != nil { - return query.NewIncorrectCommandUsageError(err.Error()) - } - } - if c.IsSet("pretty-print") { - _ = tx.SetFlag(cmd.PrettyPrintFlag, c.Bool("pretty-print")) - } - - if c.IsSet("east-asian-encoding") { - _ = tx.SetFlag(cmd.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) - } - if c.IsSet("count-diacritical-sign") { - _ = tx.SetFlag(cmd.CountDiacriticalSignFlag, c.Bool("count-diacritical-sign")) - } - if c.IsSet("count-format-code") { - _ = tx.SetFlag(cmd.CountFormatCodeFlag, c.Bool("count-format-code")) - } - - if c.IsSet("quiet") { - _ = tx.SetFlag(cmd.QuietFlag, c.Bool("quiet")) - } - if c.IsSet("limit-recursion") { - _ = tx.SetFlag(cmd.LimitRecursion, c.Int64("limit-recursion")) - } - if c.IsSet("cpu") { - _ = tx.SetFlag(cmd.CPUFlag, c.Int64("cpu")) - } - if c.IsSet("stats") { - _ = tx.SetFlag(cmd.StatsFlag, c.Bool("stats")) - } - - return nil -} - -func runPreloadCommands(ctx context.Context, proc *query.Processor) (err error) { - files := cmd.GetSpecialFilePath(cmd.PreloadCommandFileName) - for _, fpath := range files { - if !file.Exists(fpath) { - continue - } - - statements, err := query.LoadStatementsFromFile(ctx, proc.Tx, parser.Identifier{Literal: fpath}) - if err != nil { - return err - } - - if _, err := proc.Execute(ctx, statements); err != nil { - return err - } - } - return nil -} - -func readQuery(ctx context.Context, c *cli.Context, tx *query.Transaction) (queryString string, path string, err error) { - if c.IsSet("source") && 0 < len(c.String("source")) { - if 0 < c.NArg() { - err = query.NewIncorrectCommandUsageError("no argument can be passed when \"--source\" option is specified") - } else { - path = c.String("source") - queryString, err = query.LoadContentsFromFile(ctx, tx, parser.Identifier{Literal: path}) - } - } else { - switch c.NArg() { - case 0: - // Launch interactive shell - case 1: - queryString = c.Args().First() - default: - err = query.NewIncorrectCommandUsageError("csvq command takes exactly 1 argument") - } - } - return -} - -func Exit(err error, tx *query.Transaction) error { - if err == nil { - return nil - } - if exit, ok := err.(*query.ForcedExit); ok && exit.Code() == 0 { - return nil - } - - code := query.ReturnCodeApplicationError - message := err.Error() - if tx != nil { - message = tx.Error(message) - } - - if apperr, ok := err.(query.Error); ok { - code = apperr.Code() - } - - return cli.Exit(message, code) + cli.Run() } From 5c932218a1d004563649c780d4ed60896a4e69c6 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 21:04:12 +0900 Subject: [PATCH 06/17] Update the version for Release 1.17.6-pr.1 --- lib/query/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query/version.go b/lib/query/version.go index 4584519..f234a02 100644 --- a/lib/query/version.go +++ b/lib/query/version.go @@ -1,3 +1,3 @@ package query -var Version = "v1.17.5" +var Version = "v1.17.6-pr.1" From d1199ea0d1f1f9a63f8b0fbb2c02eacbc5f9af08 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Tue, 28 Jun 2022 22:14:55 +0900 Subject: [PATCH 07/17] Update help text. --- lib/cli/app.go | 5 +++-- lib/cli/help.go | 44 ++++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/lib/cli/app.go b/lib/cli/app.go index a17d0b0..1bef32c 100644 --- a/lib/cli/app.go +++ b/lib/cli/app.go @@ -30,6 +30,7 @@ func Run() { app.Usage = "SQL-like query language for csv" app.ArgsUsage = "[query|argument]" app.Version = query.Version + app.Authors = []*cli.Author{{Name: "Yuki et al."}} app.OnUsageError = onUsageError app.Flags = []cli.Flag{ &cli.StringFlag{ @@ -56,13 +57,13 @@ func Run() { &cli.BoolFlag{ Name: "strict-equal", Aliases: []string{"g"}, - Usage: "compare strictly that two values are equal for DISTINCT, GROUP BY and ORDER BY", + Usage: "compare strictly equal or not in DISTINCT, GROUP BY and ORDER BY", }, &cli.Float64Flag{ Name: "wait-timeout", Aliases: []string{"w"}, Value: 10, - Usage: "limit of the waiting time in seconds to wait for locked files to be released", + Usage: "maximum time in seconds to wait for locked files to be released", }, &cli.StringFlag{ Name: "source", diff --git a/lib/cli/help.go b/lib/cli/help.go index 665d9a0..a7bd472 100644 --- a/lib/cli/help.go +++ b/lib/cli/help.go @@ -1,65 +1,65 @@ package cli -var appHHelpTemplate = `NAME: +var appHHelpTemplate = `Name: {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} https://mithrandie.github.io/csvq -USAGE: +Usage: {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[options]{{end}}{{if .Commands}} [subcommand]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} -VERSION: +Version: Version {{.Version}}{{end}}{{end}}{{if .Description}} -DESCRIPTION: +Description: {{.Description}}{{end}}{{if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: +Author{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: {{range $index, $author := .Authors}}{{if $index}} {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} -SUBCOMMANDS:{{range .VisibleCategories}}{{if .Name}} +Subcommands:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} -OPTIONS: +Options: {{range $index, $option := .VisibleFlags}}{{if $index}} {{end}}{{$option}}{{end}} -PARAMETERS: +Parameters: Timezone - Local | UTC + Local | UTC Import Format - CSV | TSV | FIXED | JSON | JSONL | LTSV + CSV | TSV | FIXED | JSON | JSONL | LTSV Export Format - CSV | TSV | FIXED | JSON | JSONL | LTSV | GFM | ORG | BOX | TEXT + CSV | TSV | FIXED | JSON | JSONL | LTSV | GFM | ORG | BOX | TEXT Import Character Encodings - AUTO | UTF8 | UTF8M | UTF16 | UTF16BE | UTF16LE | UTF16BEM | UTF16LEM | SJIS + AUTO | UTF8 | UTF8M | UTF16 | UTF16BE | UTF16LE | UTF16BEM | UTF16LEM | SJIS Export Character Encodings - UTF8 | UTF8M | UTF16 | UTF16BE | UTF16LE | UTF16BEM | UTF16LEM | SJIS + UTF8 | UTF8M | UTF16 | UTF16BE | UTF16LE | UTF16BEM | UTF16LEM | SJIS Line Break - CRLF | CR | LF + CRLF | CR | LF JSON Escape Type - BACKSLASH | HEX | HEXALL{{end}}{{if .Copyright}} + BACKSLASH | HEX | HEXALL{{end}}{{if .Copyright}} -COPYRIGHT: +Copyright: {{.Copyright}}{{end}} ` -var commandHelpTemplate = `NAME: +var commandHelpTemplate = `Name: {{.HelpName}} - {{.Usage}} -USAGE: +Usage: csvq [options] {{.Name}}{{if .VisibleFlags}} [subcommand options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}} -CATEGORY: +Category: {{.Category}}{{end}}{{if .Description}} -DESCRIPTION: +Description: {{.Description}}{{end}}{{if .VisibleFlags}} -OPTIONS: +Options: {{range .VisibleFlags}}{{.}} {{end}}{{end}} ` From 7acbe23f2d982ef74ffb70c1cdd3c9e6383f1f12 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Fri, 1 Jul 2022 13:35:54 +0900 Subject: [PATCH 08/17] Add system defined constants. --- docs/_includes/side_menu.html | 1 + docs/_posts/2006-01-02-runtime-information.md | 2 +- docs/_posts/2006-01-02-statement.md | 4 + .../2006-01-02-system-defined-constant.md | 31 + docs/_posts/2006-01-02-value.md | 6 + docs/reference.md | 1 + docs/sitemap.xml | 4 + lib/constant/definition.go | 29 + lib/constant/main.go | 42 + lib/constant/main_test.go | 114 + lib/excmd/const.go | 12 +- lib/json/path_parser.go | 18 +- lib/parser/ast.go | 10 + lib/parser/ast_test.go | 11 + lib/parser/parser.go | 4174 +++++++++-------- lib/parser/parser.y | 24 +- lib/parser/parser_test.go | 19 + lib/parser/scanner.go | 33 +- lib/parser/scanner_test.go | 20 + lib/query/error.go | 11 + lib/query/error_code.go | 1 + lib/query/eval.go | 6 + lib/query/eval_test.go | 17 + lib/query/field_analyzer.go | 4 +- lib/syntax/syntax.go | 49 +- lib/terminal/completer_readline.go | 12 + lib/terminal/completer_readline_test.go | 12 + 27 files changed, 2569 insertions(+), 2098 deletions(-) create mode 100644 docs/_posts/2006-01-02-system-defined-constant.md create mode 100644 lib/constant/definition.go create mode 100644 lib/constant/main.go create mode 100644 lib/constant/main_test.go diff --git a/docs/_includes/side_menu.html b/docs/_includes/side_menu.html index a312ec2..e4a19aa 100644 --- a/docs/_includes/side_menu.html +++ b/docs/_includes/side_menu.html @@ -35,6 +35,7 @@
  • Flag
  • Environment Variable
  • Runtime Information
  • +
  • System Defined Constant
  • JSON
  • diff --git a/docs/_posts/2006-01-02-runtime-information.md b/docs/_posts/2006-01-02-runtime-information.md index cd616e7..3ea196a 100644 --- a/docs/_posts/2006-01-02-runtime-information.md +++ b/docs/_posts/2006-01-02-runtime-information.md @@ -6,7 +6,7 @@ category: reference # Runtime Information -Following values can be referred as a runtime information. +Following values can be referred as runtime information. | name | type | description | | :- | :- | :- | diff --git a/docs/_posts/2006-01-02-statement.md b/docs/_posts/2006-01-02-statement.md index 76b6790..916eb89 100644 --- a/docs/_posts/2006-01-02-statement.md +++ b/docs/_posts/2006-01-02-statement.md @@ -126,6 +126,9 @@ Environment Variable Runtime Information : A [runtime information]({{ '/reference/runtime-information.html' | relative_url }}) is a word starting with "@#" and followed by a character string that contains any unicode letters, any digits or Low Lines(U+005F `_`). Character case is ignored. +System Defined Constant +: A [system defined constant]({{ '/reference/system-defined-constant.html' | relative_url }}) is a group of words represented by two words separated by "::". Character case is ignored. + ``` abcde -- identifier 識別子 -- identifier @@ -142,6 +145,7 @@ null -- null @%ENV_VAR -- environment variable @%`ENV_VAR` -- environment variable @#INFO -- runtime information +CATEGORY::NAME -- system defined constant /* if --ansi-quotes is specified */ "abcd\"e" -- identifier diff --git a/docs/_posts/2006-01-02-system-defined-constant.md b/docs/_posts/2006-01-02-system-defined-constant.md new file mode 100644 index 0000000..40f7a6d --- /dev/null +++ b/docs/_posts/2006-01-02-system-defined-constant.md @@ -0,0 +1,31 @@ +--- +layout: default +title: System Defined Constant - Reference Manual - csvq +category: reference +--- + +# System Defined Constant + +A system-defined constant is specified by two words: the category and the constant name. +The two words are separated by "::". + +e.g. `MATH::PI` + +| Category | Name | Type | Value | +|:---------|:-----------------|:--------|:------------------------------------------------------------------| +| MATH | E | float | 2.71828182845904523536028747135266249775724709369995957496696763 | +| | PI | float | 3.14159265358979323846264338327950288419716939937510582097494459 | +| | PHI | float | 1.61803398874989484820458683436563811772030917980576286213544862 | +| | SQRT2 | float | 1.41421356237309504880168872420969807856967187537694807317667974 | +| | SQRTE | float | 1.64872127070012814684865078781416357165377610071014801157507931 | +| | SQRTPI | float | 1.77245385090551602729816748334114518279754945612238712821380779 | +| | SQRTPHI | float | 1.27201964951406896425242246173749149171560804184009624861664038 | +| | LN2 | float | 0.693147180559945309417232121458176568075500134360255254120680009 | +| | LOG2E | float | 1 / Ln2 | +| | LN10 | float | 2.30258509299404568401799145468436420760110148862877297603332790 | +| | LOG10E | float | 1 / Ln10 | +| FLOAT | MAX | float | 0x1p1023 * (1 + (1 - 0x1p-52)) | +| | SMALLEST_NONZERO | float | 0x1p-1022 * 0x1p-52 | +| INTEGER | MAX | integer | 1<<63 - 1 | +| | MIN | integer | -1 << 63 | + diff --git a/docs/_posts/2006-01-02-value.md b/docs/_posts/2006-01-02-value.md index 28d09fb..d9e5b9b 100644 --- a/docs/_posts/2006-01-02-value.md +++ b/docs/_posts/2006-01-02-value.md @@ -65,6 +65,7 @@ Representations of missing values. * [Variable Substitution](#variable_substitution) * [Environment Variable](#environment-variable) * [Runtime Information](#runtime-information) +* [System Defined Constant](#system-defined-constant) * [Flag](#flag) * [Parentheses](#parentheses) * [Case Expressions](#case) @@ -150,6 +151,11 @@ If the result set has no record, that subquery returns null. [Runtime Information]({{ '/reference/runtime-information.html' | relative_url }}) +### System Defined Constant +{: #system-defined-constant} + +[System Defined Constant]({{ '/reference/system-defined-constant.html' | relative_url }}) + ### Flag {: #flag} diff --git a/docs/reference.md b/docs/reference.md index 9390d34..41e784c 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -31,6 +31,7 @@ title: Reference Manual - csvq * [Flag]({{ '/reference/flag.html' | relative_url }}) * [Environment Variable]({{ '/reference/environment-variable.html' | relative_url }}) * [Runtime Information]({{ '/reference/runtime-information.html' | relative_url }}) + * [System Defined Constant]({{ '/reference/system-defined-constant.html' | relative_url }}) * [JSON]({{ '/reference/json.html' | relative_url }}) * Operators * [Operator Precedence]({{ '/reference/operator-precedence.html' | relative_url }}) diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 770eb06..e360485 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -112,6 +112,10 @@ https://mithrandie.github.io/csvq/reference/runtime-information.html 2018-11-24T06:47:39+00:00 + + https://mithrandie.github.io/csvq/reference/system-defined-constant.html + 2022-07-01T04:44:12+00:00 + https://mithrandie.github.io/csvq/reference/json.html 2018-11-17T22:33:20+00:00 diff --git a/lib/constant/definition.go b/lib/constant/definition.go new file mode 100644 index 0000000..2b5789c --- /dev/null +++ b/lib/constant/definition.go @@ -0,0 +1,29 @@ +package constant + +import ( + "math" +) + +var Definition = map[string]map[string]interface{}{ + "MATH": { + "E": math.E, + "PI": math.Pi, + "PHI": math.Phi, + "SQRT2": math.Sqrt2, + "SQRTE": math.SqrtE, + "SQRTPI": math.SqrtPi, + "SQRTPHI": math.SqrtPhi, + "LN2": math.Ln2, + "LOG2E": math.Log2E, + "LN10": math.Ln10, + "LOG10E": math.Log10E, + }, + "FLOAT": { + "MAX": math.MaxFloat64, + "SMALLEST_NONZERO": math.SmallestNonzeroFloat64, + }, + "INTEGER": { + "MAX": int64(math.MaxInt64), + "MIN": int64(math.MinInt64), + }, +} diff --git a/lib/constant/main.go b/lib/constant/main.go new file mode 100644 index 0000000..9f6a352 --- /dev/null +++ b/lib/constant/main.go @@ -0,0 +1,42 @@ +package constant + +import ( + "errors" + "strings" + + "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/value" +) + +var ErrInvalidType = errors.New("invalid constant type") +var ErrUndefined = errors.New("constant is not defined") + +func Get(expr parser.Constant) (value.Primary, error) { + if m, ok := Definition[strings.ToUpper(expr.Space)]; ok { + if c, ok := m[strings.ToUpper(expr.Name)]; ok { + return ConvertConstantToPrivamryValue(c) + } + } + return nil, ErrUndefined +} + +func ConvertConstantToPrivamryValue(c interface{}) (value.Primary, error) { + switch v := c.(type) { + case int64: + return value.NewInteger(v), nil + case float64: + return value.NewFloat(v), nil + default: + return nil, ErrInvalidType + } +} + +func Count() int { + count := 0 + + for _, v := range Definition { + count = count + len(v) + } + + return count +} diff --git a/lib/constant/main_test.go b/lib/constant/main_test.go new file mode 100644 index 0000000..f070013 --- /dev/null +++ b/lib/constant/main_test.go @@ -0,0 +1,114 @@ +package constant + +import ( + "errors" + "math" + "reflect" + "testing" + + "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/value" +) + +func TestGet(t *testing.T) { + Definition["TEST"] = map[string]interface{}{ + "INVALID_TYPE": uint8(3), + } + + defer func() { + delete(Definition, "Unused") + }() + + expr := parser.Constant{ + Space: "integer", + Name: "max", + } + var expect value.Primary = value.NewInteger(math.MaxInt64) + + ret, err := Get(expr) + if err != nil { + t.Errorf("unexpected error %q", err) + } + + if !reflect.DeepEqual(ret, expect) { + t.Errorf("result = %s, want %s", ret.String(), expect.String()) + } + + expr = parser.Constant{ + Space: "math", + Name: "pi", + } + expect = value.NewFloat(math.Pi) + + ret, err = Get(expr) + if err != nil { + t.Errorf("unexpected error %q", err) + } + + if !reflect.DeepEqual(ret, expect) { + t.Errorf("result = %s, want %s", ret.String(), expect.String()) + } + + expr = parser.Constant{ + Space: "NotDefined", + Name: "pi", + } + expectError := ErrUndefined + + _, err = Get(expr) + if err == nil { + t.Errorf("no error, want error %q", expectError.Error()) + } + if !errors.Is(err, expectError) { + t.Errorf("error %q, want error %q", err.Error(), expectError.Error()) + } + + expr = parser.Constant{ + Space: "math", + Name: "NotDefined", + } + + _, err = Get(expr) + if err == nil { + t.Errorf("no error, want error %q", expectError.Error()) + } + if !errors.Is(err, expectError) { + t.Errorf("error %q, want error %q", err.Error(), expectError.Error()) + } + + expr = parser.Constant{ + Space: "test", + Name: "invalid_type", + } + expectError = ErrInvalidType + + _, err = Get(expr) + if err == nil { + t.Errorf("no error, want error %q", expectError.Error()) + } + if !errors.Is(err, expectError) { + t.Errorf("error %q, want error %q", err.Error(), expectError.Error()) + } +} + +func TestCount(t *testing.T) { + oldDef := Definition + + Definition = map[string]map[string]interface{}{} + Definition["CAT1"] = map[string]interface{}{ + "VAL1": 1, + } + Definition["CAT2"] = map[string]interface{}{ + "VAL2": 2, + "VAL3": 3, + } + + defer func() { + Definition = oldDef + }() + + ret := Count() + if ret != 3 { + t.Errorf("result = %d, want %d", ret, 3) + } +} diff --git a/lib/excmd/const.go b/lib/excmd/const.go index 2e0cf3b..3dff785 100644 --- a/lib/excmd/const.go +++ b/lib/excmd/const.go @@ -1,13 +1,13 @@ package excmd -const EOF = -(iota + 1) +const EOF = -1 type ElementType int const ( - FixedString ElementType = 1 - Variable ElementType = 2 - EnvironmentVariable ElementType = 3 - RuntimeInformation ElementType = 4 - CsvqExpression ElementType = 5 + FixedString ElementType = iota + Variable + EnvironmentVariable + RuntimeInformation + CsvqExpression ) diff --git a/lib/json/path_parser.go b/lib/json/path_parser.go index c0bc422..d38310f 100644 --- a/lib/json/path_parser.go +++ b/lib/json/path_parser.go @@ -1,13 +1,13 @@ -// Code generated by goyacc -p jp -o path_parser.go -v path_parser.output path_parser.y. DO NOT EDIT. +// Code generated by goyacc -p jp -o lib/json/path_parser.go -v lib/json/path_parser.output lib/json/path_parser.y. DO NOT EDIT. -//line path_parser.y:2 +//line lib/json/path_parser.y:2 package json import __yyfmt__ "fmt" -//line path_parser.y:2 +//line lib/json/path_parser.y:2 -//line path_parser.y:5 +//line lib/json/path_parser.y:5 type jpSymType struct { yys int expression PathExpression @@ -31,7 +31,7 @@ const jpEofCode = 1 const jpErrCode = 2 const jpInitialStackSize = 16 -//line path_parser.y:40 +//line lib/json/path_parser.y:40 func ParsePath(src string) (PathExpression, error) { l := new(PathLexer) @@ -434,27 +434,27 @@ jpdefault: case 1: jpDollar = jpS[jppt-0 : jppt+1] -//line path_parser.y:20 +//line lib/json/path_parser.y:20 { jpVAL.expression = ObjectPath{} jplex.(*PathLexer).path = jpVAL.expression } case 2: jpDollar = jpS[jppt-1 : jppt+1] -//line path_parser.y:25 +//line lib/json/path_parser.y:25 { jpVAL.expression = jpDollar[1].member jplex.(*PathLexer).path = jpVAL.expression } case 3: jpDollar = jpS[jppt-1 : jppt+1] -//line path_parser.y:32 +//line lib/json/path_parser.y:32 { jpVAL.member = ObjectPath{Name: jpDollar[1].token.Literal} } case 4: jpDollar = jpS[jppt-3 : jppt+1] -//line path_parser.y:36 +//line lib/json/path_parser.y:36 { jpVAL.member = ObjectPath{Name: jpDollar[1].token.Literal, Child: jpDollar[3].member} } diff --git a/lib/parser/ast.go b/lib/parser/ast.go index 31dc9d6..2b49b4e 100644 --- a/lib/parser/ast.go +++ b/lib/parser/ast.go @@ -185,6 +185,16 @@ func (i Identifier) String() string { return i.Literal } +type Constant struct { + *BaseExpr + Space string + Name string +} + +func (e Constant) String() string { + return strings.ToUpper(e.Space) + ConstantDelimiter + strings.ToUpper(e.Name) +} + type FieldReference struct { *BaseExpr View Identifier diff --git a/lib/parser/ast_test.go b/lib/parser/ast_test.go index 7522516..3618fa2 100644 --- a/lib/parser/ast_test.go +++ b/lib/parser/ast_test.go @@ -144,6 +144,17 @@ func TestIdentifier_String(t *testing.T) { } } +func TestConstant_String(t *testing.T) { + e := Constant{ + Space: "math", + Name: "pi", + } + expect := "MATH::PI" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } +} + func TestFieldReference_String(t *testing.T) { e := FieldReference{ View: Identifier{Literal: "table1"}, diff --git a/lib/parser/parser.go b/lib/parser/parser.go index 39bbfc0..2818b7b 100644 --- a/lib/parser/parser.go +++ b/lib/parser/parser.go @@ -1,19 +1,20 @@ -// Code generated by goyacc -o parser.go -v parser.output parser.y. DO NOT EDIT. +// Code generated by goyacc -o lib/parser/parser.go -v lib/parser/parser.output lib/parser/parser.y. DO NOT EDIT. -//line parser.y:2 +//line lib/parser/parser.y:2 package parser import __yyfmt__ "fmt" -//line parser.y:2 +//line lib/parser/parser.y:2 import ( "strconv" + "strings" "github.com/mithrandie/csvq/lib/value" ) -//line parser.y:11 +//line lib/parser/parser.y:12 type yySymType struct { yys int program []Statement @@ -58,150 +59,151 @@ const ENVIRONMENT_VARIABLE = 57355 const RUNTIME_INFORMATION = 57356 const EXTERNAL_COMMAND = 57357 const PLACEHOLDER = 57358 -const SELECT = 57359 -const FROM = 57360 -const UPDATE = 57361 -const SET = 57362 -const UNSET = 57363 -const DELETE = 57364 -const WHERE = 57365 -const INSERT = 57366 -const INTO = 57367 -const VALUES = 57368 -const REPLACE = 57369 -const AS = 57370 -const DUAL = 57371 -const STDIN = 57372 -const RECURSIVE = 57373 -const CREATE = 57374 -const ADD = 57375 -const DROP = 57376 -const ALTER = 57377 -const TABLE = 57378 -const FIRST = 57379 -const LAST = 57380 -const AFTER = 57381 -const BEFORE = 57382 -const DEFAULT = 57383 -const RENAME = 57384 -const TO = 57385 -const VIEW = 57386 -const ORDER = 57387 -const GROUP = 57388 -const HAVING = 57389 -const BY = 57390 -const ASC = 57391 -const DESC = 57392 -const LIMIT = 57393 -const OFFSET = 57394 -const PERCENT = 57395 -const JOIN = 57396 -const INNER = 57397 -const OUTER = 57398 -const LEFT = 57399 -const RIGHT = 57400 -const FULL = 57401 -const CROSS = 57402 -const ON = 57403 -const USING = 57404 -const NATURAL = 57405 -const LATERAL = 57406 -const UNION = 57407 -const INTERSECT = 57408 -const EXCEPT = 57409 -const ALL = 57410 -const ANY = 57411 -const EXISTS = 57412 -const IN = 57413 -const AND = 57414 -const OR = 57415 -const NOT = 57416 -const BETWEEN = 57417 -const LIKE = 57418 -const IS = 57419 -const NULL = 57420 -const DISTINCT = 57421 -const WITH = 57422 -const RANGE = 57423 -const UNBOUNDED = 57424 -const PRECEDING = 57425 -const FOLLOWING = 57426 -const CURRENT = 57427 -const ROW = 57428 -const CASE = 57429 -const IF = 57430 -const ELSEIF = 57431 -const WHILE = 57432 -const WHEN = 57433 -const THEN = 57434 -const ELSE = 57435 -const DO = 57436 -const END = 57437 -const DECLARE = 57438 -const CURSOR = 57439 -const FOR = 57440 -const FETCH = 57441 -const OPEN = 57442 -const CLOSE = 57443 -const DISPOSE = 57444 -const PREPARE = 57445 -const NEXT = 57446 -const PRIOR = 57447 -const ABSOLUTE = 57448 -const RELATIVE = 57449 -const SEPARATOR = 57450 -const PARTITION = 57451 -const OVER = 57452 -const COMMIT = 57453 -const ROLLBACK = 57454 -const CONTINUE = 57455 -const BREAK = 57456 -const EXIT = 57457 -const ECHO = 57458 -const PRINT = 57459 -const PRINTF = 57460 -const SOURCE = 57461 -const EXECUTE = 57462 -const CHDIR = 57463 -const PWD = 57464 -const RELOAD = 57465 -const REMOVE = 57466 -const SYNTAX = 57467 -const TRIGGER = 57468 -const FUNCTION = 57469 -const AGGREGATE = 57470 -const BEGIN = 57471 -const RETURN = 57472 -const IGNORE = 57473 -const WITHIN = 57474 -const VAR = 57475 -const SHOW = 57476 -const TIES = 57477 -const NULLS = 57478 -const ROWS = 57479 -const ONLY = 57480 -const CSV = 57481 -const JSON = 57482 -const JSONL = 57483 -const FIXED = 57484 -const LTSV = 57485 -const CSV_INLINE = 57486 -const JSON_INLINE = 57487 -const JSON_TABLE = 57488 -const JSON_ROW = 57489 -const SUBSTRING = 57490 -const COUNT = 57491 -const JSON_OBJECT = 57492 -const AGGREGATE_FUNCTION = 57493 -const LIST_FUNCTION = 57494 -const ANALYTIC_FUNCTION = 57495 -const FUNCTION_NTH = 57496 -const FUNCTION_WITH_INS = 57497 -const COMPARISON_OP = 57498 -const STRING_OP = 57499 -const SUBSTITUTION_OP = 57500 -const UMINUS = 57501 -const UPLUS = 57502 +const CONSTANT = 57359 +const SELECT = 57360 +const FROM = 57361 +const UPDATE = 57362 +const SET = 57363 +const UNSET = 57364 +const DELETE = 57365 +const WHERE = 57366 +const INSERT = 57367 +const INTO = 57368 +const VALUES = 57369 +const REPLACE = 57370 +const AS = 57371 +const DUAL = 57372 +const STDIN = 57373 +const RECURSIVE = 57374 +const CREATE = 57375 +const ADD = 57376 +const DROP = 57377 +const ALTER = 57378 +const TABLE = 57379 +const FIRST = 57380 +const LAST = 57381 +const AFTER = 57382 +const BEFORE = 57383 +const DEFAULT = 57384 +const RENAME = 57385 +const TO = 57386 +const VIEW = 57387 +const ORDER = 57388 +const GROUP = 57389 +const HAVING = 57390 +const BY = 57391 +const ASC = 57392 +const DESC = 57393 +const LIMIT = 57394 +const OFFSET = 57395 +const PERCENT = 57396 +const JOIN = 57397 +const INNER = 57398 +const OUTER = 57399 +const LEFT = 57400 +const RIGHT = 57401 +const FULL = 57402 +const CROSS = 57403 +const ON = 57404 +const USING = 57405 +const NATURAL = 57406 +const LATERAL = 57407 +const UNION = 57408 +const INTERSECT = 57409 +const EXCEPT = 57410 +const ALL = 57411 +const ANY = 57412 +const EXISTS = 57413 +const IN = 57414 +const AND = 57415 +const OR = 57416 +const NOT = 57417 +const BETWEEN = 57418 +const LIKE = 57419 +const IS = 57420 +const NULL = 57421 +const DISTINCT = 57422 +const WITH = 57423 +const RANGE = 57424 +const UNBOUNDED = 57425 +const PRECEDING = 57426 +const FOLLOWING = 57427 +const CURRENT = 57428 +const ROW = 57429 +const CASE = 57430 +const IF = 57431 +const ELSEIF = 57432 +const WHILE = 57433 +const WHEN = 57434 +const THEN = 57435 +const ELSE = 57436 +const DO = 57437 +const END = 57438 +const DECLARE = 57439 +const CURSOR = 57440 +const FOR = 57441 +const FETCH = 57442 +const OPEN = 57443 +const CLOSE = 57444 +const DISPOSE = 57445 +const PREPARE = 57446 +const NEXT = 57447 +const PRIOR = 57448 +const ABSOLUTE = 57449 +const RELATIVE = 57450 +const SEPARATOR = 57451 +const PARTITION = 57452 +const OVER = 57453 +const COMMIT = 57454 +const ROLLBACK = 57455 +const CONTINUE = 57456 +const BREAK = 57457 +const EXIT = 57458 +const ECHO = 57459 +const PRINT = 57460 +const PRINTF = 57461 +const SOURCE = 57462 +const EXECUTE = 57463 +const CHDIR = 57464 +const PWD = 57465 +const RELOAD = 57466 +const REMOVE = 57467 +const SYNTAX = 57468 +const TRIGGER = 57469 +const FUNCTION = 57470 +const AGGREGATE = 57471 +const BEGIN = 57472 +const RETURN = 57473 +const IGNORE = 57474 +const WITHIN = 57475 +const VAR = 57476 +const SHOW = 57477 +const TIES = 57478 +const NULLS = 57479 +const ROWS = 57480 +const ONLY = 57481 +const CSV = 57482 +const JSON = 57483 +const JSONL = 57484 +const FIXED = 57485 +const LTSV = 57486 +const CSV_INLINE = 57487 +const JSON_INLINE = 57488 +const JSON_TABLE = 57489 +const JSON_ROW = 57490 +const SUBSTRING = 57491 +const COUNT = 57492 +const JSON_OBJECT = 57493 +const AGGREGATE_FUNCTION = 57494 +const LIST_FUNCTION = 57495 +const ANALYTIC_FUNCTION = 57496 +const FUNCTION_NTH = 57497 +const FUNCTION_WITH_INS = 57498 +const COMPARISON_OP = 57499 +const STRING_OP = 57500 +const SUBSTITUTION_OP = 57501 +const UMINUS = 57502 +const UPLUS = 57503 var yyToknames = [...]string{ "$end", @@ -220,6 +222,7 @@ var yyToknames = [...]string{ "RUNTIME_INFORMATION", "EXTERNAL_COMMAND", "PLACEHOLDER", + "CONSTANT", "SELECT", "FROM", "UPDATE", @@ -384,7 +387,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line parser.y:2802 +//line lib/parser/parser.y:2824 func SetDebugLevel(level int, verbose bool) { yyDebug = level @@ -408,1037 +411,1040 @@ var yyExca = [...]int{ -2, 0, -1, 21, 1, 26, - 89, 26, - 91, 26, - 93, 26, - 95, 26, - 161, 26, + 90, 26, + 92, 26, + 94, 26, + 96, 26, + 162, 26, -2, 239, -1, 27, - 65, 188, 66, 188, 67, 188, + 68, 188, -2, 200, -1, 35, 1, 78, - 89, 78, - 91, 78, - 93, 78, - 95, 78, - 161, 78, + 90, 78, + 92, 78, + 94, 78, + 96, 78, + 162, 78, -2, 252, -1, 61, - 65, 189, 66, 189, 67, 189, + 68, 189, -2, 244, - -1, 121, - 19, 220, - 22, 220, - 24, 220, + -1, 123, + 20, 220, + 23, 220, + 25, 220, -2, 1, - -1, 135, - 65, 188, + -1, 137, 66, 188, 67, 188, + 68, 188, -2, 200, - -1, 175, + -1, 177, 1, 122, - 89, 122, - 91, 122, - 93, 122, - 95, 122, - 161, 122, + 90, 122, + 92, 122, + 94, 122, + 96, 122, + 162, 122, -2, 233, - -1, 176, + -1, 178, 1, 163, - 89, 163, - 91, 163, - 93, 163, - 95, 163, - 161, 163, + 90, 163, + 92, 163, + 94, 163, + 96, 163, + 162, 163, -2, 239, - -1, 181, + -1, 183, 1, 156, - 89, 156, - 91, 156, - 93, 156, - 95, 156, - 161, 156, + 90, 156, + 92, 156, + 94, 156, + 96, 156, + 162, 156, -2, 239, - -1, 182, + -1, 184, 1, 157, - 89, 157, - 91, 157, - 93, 157, - 95, 157, - 161, 157, + 90, 157, + 92, 157, + 94, 157, + 96, 157, + 162, 157, -2, 239, - -1, 183, + -1, 185, 1, 158, - 89, 158, - 91, 158, - 93, 158, - 95, 158, - 161, 158, + 90, 158, + 92, 158, + 94, 158, + 96, 158, + 162, 158, -2, 239, - -1, 184, + -1, 186, 1, 161, - 89, 161, - 91, 161, - 93, 161, - 95, 161, - 161, 161, + 90, 161, + 92, 161, + 94, 161, + 96, 161, + 162, 161, -2, 233, - -1, 185, + -1, 187, 1, 162, - 89, 162, - 91, 162, - 93, 162, - 95, 162, - 161, 162, + 90, 162, + 92, 162, + 94, 162, + 96, 162, + 162, 162, -2, 239, - -1, 188, + -1, 190, 1, 169, - 89, 169, - 91, 169, - 93, 169, - 95, 169, - 161, 169, + 90, 169, + 92, 169, + 94, 169, + 96, 169, + 162, 169, -2, 233, - -1, 189, + -1, 191, 1, 170, - 89, 170, - 91, 170, - 93, 170, - 95, 170, - 161, 170, + 90, 170, + 92, 170, + 94, 170, + 96, 170, + 162, 170, -2, 239, - -1, 255, - 89, 1, - 93, 1, - 95, 1, + -1, 257, + 90, 1, + 94, 1, + 96, 1, -2, 220, - -1, 278, - 169, 358, - -2, 485, - -1, 279, - 169, 359, - -2, 486, -1, 280, - 169, 360, - -2, 487, + 170, 359, + -2, 486, -1, 281, - 169, 361, - -2, 488, + 170, 360, + -2, 487, -1, 282, - 169, 362, + 170, 361, + -2, 488, + -1, 283, + 170, 362, -2, 489, - -1, 293, - 54, 505, - -2, 421, - -1, 329, + -1, 284, + 170, 363, + -2, 490, + -1, 295, + 55, 507, + -2, 422, + -1, 331, 4, 144, - 135, 144, 136, 144, 137, 144, - 139, 144, + 138, 144, 140, 144, 141, 144, 142, 144, 143, 144, + 144, 144, -2, 239, - -1, 330, + -1, 332, 4, 145, - 135, 145, 136, 145, 137, 145, - 139, 145, + 138, 145, 140, 145, 141, 145, 142, 145, 143, 145, + 144, 145, -2, 239, - -1, 340, + -1, 342, 1, 174, - 89, 174, - 91, 174, - 93, 174, - 95, 174, - 161, 174, + 90, 174, + 92, 174, + 94, 174, + 96, 174, + 162, 174, -2, 239, - -1, 347, - 95, 4, + -1, 349, + 96, 4, -2, 220, - -1, 366, - 71, 0, - 75, 0, + -1, 368, + 72, 0, 76, 0, 77, 0, - 156, 0, - 162, 0, - -2, 279, - -1, 367, - 71, 0, - 75, 0, + 78, 0, + 157, 0, + 163, 0, + -2, 280, + -1, 369, + 72, 0, 76, 0, 77, 0, - 156, 0, - 162, 0, - -2, 281, - -1, 376, - 71, 0, - 75, 0, + 78, 0, + 157, 0, + 163, 0, + -2, 282, + -1, 378, + 72, 0, 76, 0, 77, 0, - 156, 0, - 162, 0, - -2, 291, - -1, 415, - 95, 1, + 78, 0, + 157, 0, + 163, 0, + -2, 292, + -1, 417, + 96, 1, -2, 220, - -1, 422, + -1, 424, 1, 210, - 52, 210, - 80, 210, - 89, 210, - 91, 210, - 93, 210, - 95, 210, - 98, 210, - 138, 210, - 161, 210, - 170, 210, + 53, 210, + 81, 210, + 90, 210, + 92, 210, + 94, 210, + 96, 210, + 99, 210, + 139, 210, + 162, 210, + 171, 210, -2, 239, - -1, 423, + -1, 425, 1, 215, - 89, 215, - 91, 215, - 93, 215, - 95, 215, - 98, 215, + 90, 215, + 92, 215, + 94, 215, + 96, 215, 99, 215, - 161, 215, - 170, 215, + 100, 215, + 162, 215, + 171, 215, -2, 239, - -1, 453, - 65, 189, + -1, 455, 66, 189, 67, 189, - -2, 378, - -1, 474, + 68, 189, + -2, 379, + -1, 476, 1, 80, - 89, 80, - 91, 80, - 93, 80, - 95, 80, - 161, 80, + 90, 80, + 92, 80, + 94, 80, + 96, 80, + 162, 80, -2, 239, - -1, 475, + -1, 477, 1, 81, - 89, 81, - 91, 81, - 93, 81, - 95, 81, - 161, 81, + 90, 81, + 92, 81, + 94, 81, + 96, 81, + 162, 81, -2, 233, - -1, 476, + -1, 478, 1, 82, - 89, 82, - 91, 82, - 93, 82, - 95, 82, - 161, 82, + 90, 82, + 92, 82, + 94, 82, + 96, 82, + 162, 82, -2, 239, - -1, 477, + -1, 479, 1, 83, - 89, 83, - 91, 83, - 93, 83, - 95, 83, - 161, 83, + 90, 83, + 92, 83, + 94, 83, + 96, 83, + 162, 83, -2, 233, - -1, 478, + -1, 480, 1, 149, - 89, 149, - 91, 149, - 93, 149, - 95, 149, - 161, 149, + 90, 149, + 92, 149, + 94, 149, + 96, 149, + 162, 149, -2, 233, - -1, 479, + -1, 481, 1, 150, - 89, 150, - 91, 150, - 93, 150, - 95, 150, - 161, 150, + 90, 150, + 92, 150, + 94, 150, + 96, 150, + 162, 150, -2, 239, - -1, 480, + -1, 482, 1, 151, - 89, 151, - 91, 151, - 93, 151, - 95, 151, - 161, 151, + 90, 151, + 92, 151, + 94, 151, + 96, 151, + 162, 151, -2, 233, - -1, 481, + -1, 483, 1, 152, - 89, 152, - 91, 152, - 93, 152, - 95, 152, - 161, 152, + 90, 152, + 92, 152, + 94, 152, + 96, 152, + 162, 152, -2, 239, - -1, 484, + -1, 486, 1, 117, - 89, 117, - 91, 117, - 93, 117, - 95, 117, - 161, 117, - 171, 117, + 90, 117, + 92, 117, + 94, 117, + 96, 117, + 162, 117, + 172, 117, -2, 239, - -1, 489, - 1, 419, - 89, 419, - 91, 419, - 93, 419, - 95, 419, - 161, 419, + -1, 491, + 1, 420, + 90, 420, + 92, 420, + 94, 420, + 96, 420, + 162, 420, -2, 239, - -1, 496, + -1, 498, 1, 175, - 89, 175, - 91, 175, - 93, 175, - 95, 175, - 161, 175, + 90, 175, + 92, 175, + 94, 175, + 96, 175, + 162, 175, -2, 239, - -1, 528, - 71, 0, - 75, 0, + -1, 530, + 72, 0, 76, 0, 77, 0, - 156, 0, - 162, 0, - -2, 292, - -1, 554, - 95, 1, + 78, 0, + 157, 0, + 163, 0, + -2, 293, + -1, 556, + 96, 1, -2, 220, - -1, 561, - 91, 1, - 93, 1, - 95, 1, + -1, 563, + 92, 1, + 94, 1, + 96, 1, -2, 220, - -1, 590, - 170, 356, - 171, 356, + -1, 592, + 171, 357, + 172, 357, -2, 233, - -1, 608, - 54, 505, - -2, 381, - -1, 648, - 19, 220, - 22, 220, - 24, 220, + -1, 610, + 55, 507, + -2, 382, + -1, 650, + 20, 220, + 23, 220, + 25, 220, -2, 4, - -1, 651, - 95, 4, + -1, 653, + 96, 4, -2, 220, - -1, 652, - 95, 4, + -1, 654, + 96, 4, -2, 220, - -1, 677, - 170, 261, - 171, 261, + -1, 679, + 171, 262, + 172, 262, -2, 189, - -1, 752, - 89, 4, - 93, 4, - 95, 4, + -1, 754, + 90, 4, + 94, 4, + 96, 4, -2, 220, - -1, 757, - 95, 4, + -1, 759, + 96, 4, -2, 220, - -1, 758, - 95, 4, + -1, 760, + 96, 4, -2, 220, - -1, 784, - 89, 1, - 93, 1, - 95, 1, + -1, 786, + 90, 1, + 94, 1, + 96, 1, -2, 220, - -1, 821, - 17, 516, - 80, 516, - 169, 516, + -1, 823, + 18, 518, + 81, 518, + 170, 518, -2, 87, - -1, 829, + -1, 831, 1, 95, - 89, 95, - 91, 95, - 93, 95, - 95, 95, - 161, 95, + 90, 95, + 92, 95, + 94, 95, + 96, 95, + 162, 95, -2, 233, - -1, 830, + -1, 832, 1, 96, - 89, 96, - 91, 96, - 93, 96, - 95, 96, - 161, 96, + 90, 96, + 92, 96, + 94, 96, + 96, 96, + 162, 96, -2, 239, - -1, 834, - 95, 6, + -1, 836, + 96, 6, -2, 220, - -1, 840, - 170, 128, + -1, 842, 171, 128, + 172, 128, -2, 239, - -1, 845, - 95, 4, + -1, 847, + 96, 4, -2, 220, - -1, 915, - 95, 6, + -1, 917, + 96, 6, -2, 220, - -1, 916, - 95, 6, + -1, 918, + 96, 6, -2, 220, - -1, 920, - 95, 4, + -1, 922, + 96, 4, -2, 220, - -1, 924, - 91, 4, - 93, 4, - 95, 4, + -1, 926, + 92, 4, + 94, 4, + 96, 4, -2, 220, - -1, 965, - 19, 220, - 22, 220, - 24, 220, + -1, 967, + 20, 220, + 23, 220, + 25, 220, -2, 6, - -1, 972, - 161, 62, + -1, 974, + 162, 62, -2, 239, - -1, 1006, - 89, 6, - 93, 6, - 95, 6, + -1, 1008, + 90, 6, + 94, 6, + 96, 6, -2, 220, - -1, 1009, - 95, 8, + -1, 1011, + 96, 8, -2, 220, - -1, 1016, - 95, 6, + -1, 1018, + 96, 6, -2, 220, - -1, 1019, - 89, 4, - 93, 4, - 95, 4, + -1, 1021, + 90, 4, + 94, 4, + 96, 4, -2, 220, - -1, 1033, - 95, 6, + -1, 1035, + 96, 6, -2, 220, - -1, 1058, - 95, 6, - -2, 220, - -1, 1062, - 91, 6, - 93, 6, - 95, 6, + -1, 1060, + 96, 6, -2, 220, -1, 1064, - 19, 220, - 22, 220, - 24, 220, + 92, 6, + 94, 6, + 96, 6, + -2, 220, + -1, 1066, + 20, 220, + 23, 220, + 25, 220, -2, 8, - -1, 1067, - 95, 8, + -1, 1069, + 96, 8, -2, 220, - -1, 1068, - 95, 8, + -1, 1070, + 96, 8, -2, 220, - -1, 1087, - 89, 8, - 93, 8, - 95, 8, + -1, 1089, + 90, 8, + 94, 8, + 96, 8, -2, 220, - -1, 1092, - 95, 8, + -1, 1094, + 96, 8, -2, 220, - -1, 1093, - 95, 8, + -1, 1095, + 96, 8, -2, 220, - -1, 1104, - 89, 6, - 93, 6, - 95, 6, + -1, 1106, + 90, 6, + 94, 6, + 96, 6, -2, 220, - -1, 1109, - 95, 8, + -1, 1111, + 96, 8, -2, 220, - -1, 1124, - 95, 8, + -1, 1126, + 96, 8, -2, 220, - -1, 1128, - 91, 8, - 93, 8, - 95, 8, + -1, 1130, + 92, 8, + 94, 8, + 96, 8, -2, 220, - -1, 1148, - 89, 8, - 93, 8, - 95, 8, + -1, 1150, + 90, 8, + 94, 8, + 96, 8, -2, 220, } const yyPrivate = 57344 -const yyLast = 4001 +const yyLast = 4038 var yyAct = [...]int{ - 124, 61, 1122, 130, 1123, 1057, 1096, 675, 1088, 1056, - 424, 1007, 201, 919, 918, 905, 753, 855, 505, 616, - 263, 931, 202, 854, 307, 632, 553, 731, 690, 141, - 98, 638, 726, 639, 607, 636, 583, 264, 805, 619, - 288, 567, 488, 260, 504, 26, 261, 297, 853, 133, - 598, 482, 503, 25, 603, 552, 362, 438, 732, 359, - 443, 293, 285, 273, 245, 442, 144, 1, 292, 497, - 271, 544, 84, 83, 61, 27, 209, 71, 186, 151, - 1010, 299, 213, 257, 353, 499, 3, 1035, 348, 332, - 253, 77, 234, 893, 894, 233, 234, 1046, 195, 233, - 248, 79, 233, 446, 135, 447, 448, 449, 441, 234, - 1053, 444, 522, 825, 155, 163, 895, 896, 879, 880, - 745, 746, 61, 814, 61, 1042, 179, 702, 703, 511, - 110, 338, 446, 259, 447, 448, 449, 441, 79, 79, - 444, 138, 68, 141, 140, 79, 137, 301, 256, 139, - 79, 79, 778, 79, 1029, 296, 276, 268, 290, 951, - 897, 743, 876, 215, 78, 742, 26, 192, 739, 225, - 224, 226, 227, 228, 25, 192, 154, 154, 723, 157, - 349, 720, 719, 704, 700, 79, 79, 646, 349, 254, - 609, 643, 1041, 574, 520, 580, 234, 349, 141, 233, - 102, 78, 349, 436, 286, 431, 357, 3, 78, 313, - 287, 119, 1028, 78, 78, 352, 78, 1026, 200, 445, - 272, 1025, 375, 320, 225, 224, 226, 227, 228, 349, - 308, 306, 311, 374, 79, 312, 1024, 1022, 1004, 592, - 337, 1003, 1002, 1001, 375, 375, 997, 612, 78, 78, - 992, 990, 373, 142, 620, 989, 61, 988, 987, 963, - 944, 111, 112, 113, 942, 278, 279, 280, 281, 282, - 303, 304, 305, 135, 400, 401, 941, 930, 917, 881, - 878, 851, 827, 368, 824, 301, 821, 818, 291, 427, - 142, 142, 355, 356, 802, 298, 393, 142, 518, 453, - 26, 795, 142, 142, 142, 142, 148, 777, 25, 760, - 741, 738, 722, 668, 667, 119, 666, 389, 388, 390, - 394, 395, 396, 411, 397, 398, 399, 665, 437, 221, - 230, 229, 220, 219, 222, 218, 428, 374, 581, 547, - 663, 3, 629, 542, 541, 351, 593, 471, 61, 540, - 535, 533, 429, 434, 141, 531, 141, 141, 457, 635, - 452, 545, 509, 412, 495, 433, 345, 346, 344, 102, - 953, 945, 375, 943, 458, 61, 939, 929, 375, 375, - 493, 494, 899, 885, 487, 863, 142, 125, 35, 861, - 860, 859, 857, 467, 831, 618, 466, 774, 110, 195, - 772, 771, 527, 375, 546, 546, 546, 762, 529, 530, - 705, 79, 490, 491, 216, 215, 61, 678, 492, 655, - 217, 225, 224, 226, 227, 228, 615, 701, 995, 514, - 141, 514, 514, 543, 517, 473, 301, 472, 456, 519, - 432, 524, 523, 152, 147, 513, 301, 515, 516, 258, - 147, 252, 538, 226, 227, 228, 154, 1064, 221, 230, - 26, 220, 219, 222, 218, 28, 242, 241, 25, 579, - 141, 550, 141, 532, 78, 594, 548, 549, 536, 537, - 539, 459, 240, 557, 239, 238, 237, 236, 470, 235, - 965, 648, 291, 610, 121, 597, 588, 326, 645, 596, - 286, 3, 587, 314, 595, 606, 650, 608, 247, 35, - 605, 324, 192, 272, 406, 572, 692, 132, 21, 1052, - 775, 622, 143, 869, 773, 694, 790, 152, 1016, 111, - 112, 113, 916, 114, 115, 116, 117, 118, 672, 197, - 915, 122, 568, 216, 215, 656, 677, 110, 834, 217, - 225, 224, 226, 227, 228, 61, 770, 867, 768, 673, - 79, 176, 61, 142, 177, 178, 573, 181, 182, 183, - 185, 670, 189, 120, 691, 569, 676, 767, 769, 659, - 657, 375, 141, 766, 763, 693, 407, 737, 697, 197, - 243, 194, 671, 199, 669, 662, 244, 856, 564, 26, - 421, 698, 301, 301, 170, 171, 26, 25, 197, 683, - 301, 676, 223, 706, 25, 641, 325, 316, 996, 954, - 141, 578, 684, 78, 469, 710, 570, 420, 291, 688, - 323, 680, 1147, 1137, 1132, 721, 707, 696, 1093, 21, - 3, 194, 1131, 35, 724, 1126, 734, 3, 708, 61, - 699, 1112, 61, 61, 1111, 1124, 141, 718, 1103, 269, - 679, 717, 1092, 711, 713, 565, 1079, 1071, 1068, 110, - 315, 168, 169, 172, 173, 375, 1063, 102, 111, 112, - 113, 1060, 114, 115, 116, 117, 118, 1018, 1015, 749, - 329, 330, 1014, 976, 964, 747, 928, 927, 922, 848, - 317, 318, 847, 783, 682, 776, 647, 558, 556, 340, - 159, 246, 142, 301, 1067, 301, 301, 301, 751, 1125, - 301, 755, 756, 1124, 1109, 801, 1009, 758, 789, 109, - 803, 788, 786, 757, 785, 35, 652, 797, 1059, 651, - 796, 921, 1058, 820, 555, 920, 1058, 794, 554, 1148, - 347, 1033, 920, 61, 815, 845, 554, 417, 61, 61, - 804, 415, 808, 158, 197, 833, 1128, 610, 800, 160, - 1104, 1087, 1062, 21, 837, 838, 836, 809, 811, 375, - 419, 608, 842, 422, 423, 61, 870, 799, 1019, 865, - 1006, 924, 865, 161, 784, 864, 141, 752, 868, 561, - 111, 112, 113, 35, 114, 115, 116, 117, 118, 676, - 255, 301, 1150, 301, 301, 301, 875, 874, 1106, 141, - 1089, 866, 843, 1021, 883, 1008, 787, 849, 850, 26, - 754, 413, 262, 141, 623, 61, 1144, 25, 1143, 1130, - 197, 474, 476, 479, 481, 484, 61, 886, 887, 892, - 484, 489, 873, 902, 1129, 489, 489, 901, 888, 496, - 889, 900, 610, 1085, 983, 21, 982, 926, 925, 5, - 3, 750, 1125, 1059, 921, 890, 608, 375, 555, 1151, - 903, 865, 141, 1146, 949, 641, 839, 940, 1120, 641, - 1102, 1049, 301, 1017, 872, 197, 948, 782, 375, 310, - 947, 141, 1141, 1083, 980, 960, 934, 676, 936, 937, - 938, 955, 1097, 686, 967, 923, 61, 61, 1119, 961, - 907, 61, 1101, 1145, 1097, 61, 970, 956, 676, 1116, - 141, 973, 974, 21, 977, 197, 971, 197, 1100, 957, - 1117, 1118, 35, 196, 1099, 1076, 780, 107, 214, 35, - 589, 371, 375, 403, 1047, 370, 372, 402, 986, 998, - 912, 991, 247, 865, 950, 461, 61, 1115, 674, 994, - 1011, 512, 350, 999, 614, 621, 405, 404, 958, 354, - 959, 1005, 676, 813, 1013, 378, 377, 207, 1134, 882, - 978, 1098, 993, 196, 981, 819, 1023, 333, 1020, 327, - 1095, 907, 907, 1098, 604, 141, 716, 61, 806, 807, - 61, 197, 196, 715, 1074, 602, 108, 61, 601, 649, - 61, 1075, 1031, 446, 1077, 447, 448, 911, 1043, 141, - 375, 266, 1048, 985, 61, 933, 35, 1055, 600, 35, - 35, 912, 912, 267, 1066, 265, 266, 197, 599, 1061, - 862, 907, 439, 134, 375, 744, 969, 932, 736, 61, - 676, 1078, 735, 61, 1072, 61, 334, 1080, 61, 61, - 733, 150, 21, 685, 1081, 206, 207, 208, 1084, 21, - 149, 689, 212, 1043, 676, 197, 1043, 1043, 61, 1050, - 975, 912, 907, 61, 61, 1037, 1105, 446, 620, 447, - 448, 449, 907, 792, 793, 61, 1043, 852, 911, 911, - 61, 1043, 1043, 841, 1012, 727, 728, 729, 730, 907, - 1121, 197, 1135, 835, 69, 61, 1138, 1136, 1043, 61, - 832, 446, 912, 447, 448, 449, 441, 806, 807, 444, - 35, 740, 912, 1043, 907, 35, 35, 1043, 907, 61, - 1037, 1149, 1086, 1037, 1037, 1090, 1091, 1153, 911, 912, - 585, 484, 162, 164, 489, 644, 21, 1043, 196, 21, - 21, 485, 35, 1037, 283, 1107, 270, 289, 1037, 1037, - 1113, 1114, 430, 110, 912, 387, 1027, 1000, 912, 617, - 907, 695, 562, 625, 627, 1037, 146, 1127, 446, 911, - 447, 448, 449, 441, 146, 465, 444, 435, 336, 911, - 1037, 145, 1139, 335, 1037, 331, 1142, 103, 462, 463, - 105, 103, 35, 105, 102, 205, 911, 464, 486, 309, - 912, 211, 534, 35, 1037, 70, 1152, 153, 817, 1108, - 1032, 844, 221, 414, 196, 220, 219, 222, 218, 10, - 9, 911, 584, 8, 830, 911, 7, 416, 65, 360, - 295, 197, 840, 294, 300, 302, 274, 277, 1133, 1094, - 21, 1073, 846, 1051, 64, 21, 21, 93, 63, 62, - 67, 110, 59, 66, 197, 221, 230, 229, 220, 219, - 222, 218, 60, 791, 575, 284, 425, 911, 197, 582, - 58, 210, 21, 35, 35, 419, 571, 276, 35, 566, - 563, 617, 35, 6, 111, 112, 113, 20, 114, 115, - 116, 117, 118, 617, 19, 72, 167, 216, 215, 17, - 640, 637, 16, 217, 225, 224, 226, 227, 228, 630, - 483, 634, 15, 14, 364, 617, 11, 197, 18, 13, - 12, 1038, 21, 35, 908, 1036, 617, 906, 500, 498, - 4, 2, 0, 21, 0, 0, 197, 0, 0, 0, - 216, 215, 0, 0, 0, 0, 217, 225, 224, 226, - 227, 228, 0, 0, 0, 339, 0, 0, 0, 0, - 0, 0, 0, 0, 35, 197, 0, 35, 0, 0, - 0, 0, 0, 0, 35, 0, 0, 35, 0, 0, - 0, 0, 111, 112, 113, 196, 114, 115, 116, 117, - 118, 35, 0, 0, 0, 0, 0, 966, 0, 0, - 585, 968, 972, 21, 21, 617, 0, 0, 21, 979, - 0, 0, 21, 0, 85, 0, 35, 0, 0, 0, - 35, 196, 35, 617, 0, 35, 35, 0, 0, 822, - 823, 0, 0, 0, 0, 0, 0, 0, 0, 131, - 197, 0, 0, 0, 0, 35, 0, 0, 0, 0, - 35, 35, 0, 21, 0, 0, 0, 0, 0, 725, - 0, 0, 35, 0, 197, 0, 0, 35, 187, 0, - 0, 0, 221, 230, 229, 220, 219, 222, 218, 0, - 0, 0, 35, 0, 0, 0, 35, 0, 193, 0, - 0, 0, 0, 0, 21, 759, 1034, 21, 0, 0, - 0, 231, 232, 0, 21, 0, 35, 21, 0, 846, - 0, 0, 0, 0, 0, 249, 250, 0, 0, 0, - 0, 21, 0, 0, 0, 0, 0, 1065, 0, 221, - 230, 229, 220, 219, 222, 218, 0, 0, 193, 0, - 0, 0, 0, 0, 131, 0, 21, 1082, 110, 0, - 21, 0, 21, 0, 0, 21, 21, 216, 215, 0, - 0, 110, 187, 217, 225, 224, 226, 227, 228, 0, - 0, 343, 339, 296, 276, 21, 0, 1110, 0, 0, - 21, 21, 0, 0, 0, 0, 296, 276, 0, 0, - 0, 0, 21, 0, 1034, 0, 0, 21, 0, 617, - 0, 0, 0, 0, 0, 0, 0, 342, 891, 0, - 110, 0, 21, 1140, 216, 215, 21, 0, 105, 0, - 217, 225, 224, 226, 227, 228, 0, 0, 361, 871, - 365, 366, 367, 0, 369, 877, 21, 376, 1110, 379, - 380, 381, 382, 383, 384, 385, 0, 0, 0, 187, - 391, 361, 0, 617, 0, 187, 187, 187, 898, 0, - 0, 0, 29, 0, 0, 0, 0, 408, 0, 0, - 0, 0, 904, 187, 0, 88, 0, 418, 0, 111, - 112, 113, 426, 278, 279, 280, 281, 282, 303, 304, - 305, 136, 111, 112, 113, 0, 278, 279, 280, 281, - 282, 303, 304, 305, 440, 0, 0, 0, 0, 0, - 156, 0, 0, 298, 0, 165, 166, 0, 174, 175, - 0, 952, 0, 0, 180, 0, 298, 187, 184, 468, - 188, 0, 190, 191, 0, 0, 198, 0, 0, 0, - 962, 111, 112, 113, 0, 114, 115, 116, 117, 118, - 0, 0, 0, 0, 187, 0, 221, 230, 229, 220, - 219, 222, 218, 0, 110, 0, 0, 0, 0, 984, - 0, 221, 230, 229, 220, 219, 222, 218, 0, 0, - 0, 0, 251, 765, 0, 526, 198, 528, 455, 187, - 221, 230, 229, 220, 219, 222, 218, 0, 0, 0, - 0, 0, 0, 0, 187, 198, 0, 0, 0, 187, - 187, 187, 0, 0, 275, 0, 275, 0, 0, 110, - 0, 0, 275, 0, 275, 0, 275, 0, 418, 0, - 0, 0, 559, 0, 319, 275, 321, 322, 0, 0, - 0, 216, 215, 328, 1030, 120, 0, 217, 225, 224, - 226, 227, 228, 0, 0, 764, 216, 215, 0, 0, - 198, 0, 217, 225, 224, 226, 227, 228, 1054, 0, - 0, 551, 110, 0, 0, 216, 215, 0, 0, 0, - 0, 217, 225, 224, 226, 227, 228, 358, 0, 363, - 339, 0, 0, 0, 0, 111, 112, 113, 120, 114, - 115, 116, 117, 118, 0, 0, 0, 0, 0, 386, - 0, 0, 363, 110, 80, 81, 82, 131, 107, 0, - 102, 105, 103, 104, 0, 74, 0, 0, 0, 409, - 0, 0, 0, 0, 0, 361, 127, 0, 0, 120, - 660, 0, 0, 0, 0, 0, 275, 0, 0, 664, - 111, 112, 113, 0, 114, 115, 116, 117, 118, 275, - 275, 198, 0, 0, 0, 0, 681, 0, 0, 0, - 450, 0, 0, 0, 275, 687, 0, 454, 0, 99, - 0, 0, 0, 100, 626, 460, 0, 108, 0, 426, - 0, 0, 0, 0, 0, 0, 129, 126, 0, 475, - 477, 478, 480, 111, 112, 113, 106, 114, 115, 116, - 117, 118, 275, 0, 709, 187, 198, 0, 198, 198, - 0, 0, 0, 0, 508, 0, 510, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, - 0, 0, 128, 0, 111, 112, 113, 0, 114, 115, - 116, 117, 118, 0, 0, 0, 119, 89, 92, 90, - 91, 94, 95, 96, 97, 221, 230, 229, 220, 219, - 222, 218, 86, 87, 364, 0, 761, 101, 73, 392, - 221, 230, 229, 220, 219, 222, 218, 0, 0, 0, - 0, 0, 198, 779, 0, 0, 0, 0, 221, 230, - 229, 220, 219, 222, 218, 0, 586, 275, 590, 0, - 0, 275, 275, 0, 0, 0, 798, 0, 187, 560, - 0, 275, 0, 0, 0, 0, 0, 611, 110, 454, - 0, 613, 198, 0, 198, 586, 0, 0, 624, 586, - 586, 628, 0, 0, 0, 631, 633, 0, 826, 642, - 216, 215, 0, 0, 276, 0, 217, 225, 224, 226, - 227, 228, 0, 0, 935, 216, 215, 0, 0, 418, - 0, 217, 225, 224, 226, 227, 228, 0, 0, 781, - 858, 0, 0, 216, 215, 0, 0, 653, 654, 217, - 225, 224, 226, 227, 228, 633, 363, 658, 386, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, - 0, 0, 0, 0, 0, 576, 577, 0, 0, 0, - 0, 884, 0, 110, 80, 81, 82, 0, 107, 0, - 102, 105, 103, 104, 0, 74, 0, 221, 230, 229, - 220, 219, 222, 218, 198, 0, 127, 0, 0, 120, - 221, 230, 229, 220, 219, 222, 218, 586, 0, 111, - 112, 113, 0, 114, 115, 116, 117, 118, 0, 586, - 413, 0, 0, 0, 0, 0, 0, 275, 275, 0, - 0, 0, 198, 0, 0, 0, 946, 0, 0, 99, - 0, 586, 0, 100, 633, 187, 0, 108, 0, 624, - 0, 110, 586, 0, 0, 0, 129, 126, 0, 187, - 0, 187, 0, 110, 79, 204, 106, 0, 198, 0, - 748, 0, 216, 215, 0, 131, 296, 276, 217, 225, - 224, 226, 227, 228, 0, 216, 215, 0, 110, 276, - 0, 217, 225, 224, 226, 227, 228, 0, 187, 0, - 0, 0, 203, 0, 111, 112, 113, 0, 114, 115, - 116, 117, 118, 296, 276, 0, 119, 89, 92, 90, - 91, 94, 95, 96, 97, 0, 586, 78, 0, 0, - 275, 586, 86, 87, 0, 0, 0, 101, 73, 0, - 0, 275, 275, 0, 0, 275, 816, 0, 812, 586, - 426, 0, 0, 0, 0, 586, 586, 0, 0, 0, - 0, 828, 829, 0, 0, 633, 0, 0, 0, 0, - 0, 0, 0, 418, 221, 230, 229, 220, 219, 222, - 218, 0, 111, 112, 113, 110, 278, 279, 280, 281, - 282, 303, 304, 305, 111, 112, 113, 110, 278, 279, - 280, 281, 282, 0, 102, 131, 0, 0, 198, 451, - 0, 0, 0, 0, 0, 0, 298, 0, 0, 111, - 112, 113, 0, 278, 279, 280, 281, 282, 303, 304, - 305, 198, 0, 0, 0, 0, 0, 0, 0, 275, - 275, 0, 0, 0, 0, 198, 0, 0, 0, 0, - 0, 624, 0, 298, 418, 0, 0, 0, 0, 216, - 215, 0, 0, 0, 0, 217, 225, 224, 226, 227, - 228, 0, 0, 0, 0, 110, 80, 81, 82, 0, - 107, 0, 102, 105, 103, 104, 22, 74, 79, 0, - 0, 37, 38, 0, 198, 0, 0, 0, 30, 0, - 0, 120, 0, 31, 46, 0, 32, 0, 0, 0, - 0, 633, 0, 198, 0, 0, 111, 112, 113, 0, - 114, 115, 116, 117, 118, 586, 0, 0, 111, 112, - 113, 0, 114, 115, 116, 117, 118, 0, 0, 0, - 0, 99, 198, 0, 0, 100, 0, 0, 0, 108, - 0, 78, 0, 0, 0, 110, 0, 0, 1040, 1039, - 0, 913, 0, 0, 0, 0, 0, 34, 106, 110, - 41, 39, 40, 36, 42, 0, 0, 0, 0, 586, - 296, 276, 44, 45, 506, 507, 0, 49, 50, 51, - 52, 43, 54, 55, 56, 47, 53, 57, 0, 0, - 0, 914, 0, 0, 33, 48, 111, 112, 113, 0, - 114, 115, 116, 117, 118, 810, 0, 198, 119, 89, - 92, 90, 91, 94, 95, 96, 97, 0, 0, 0, - 0, 0, 0, 0, 86, 87, 1044, 1045, 0, 101, - 73, 198, 0, 0, 0, 0, 0, 0, 110, 80, - 81, 82, 0, 107, 0, 102, 105, 103, 104, 22, - 74, 79, 0, 0, 37, 38, 0, 0, 0, 0, - 0, 30, 1069, 1070, 120, 0, 31, 46, 0, 32, - 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, - 278, 279, 280, 281, 282, 303, 304, 305, 0, 0, - 111, 112, 113, 0, 114, 115, 116, 117, 118, 0, - 0, 0, 0, 0, 99, 110, 0, 410, 100, 0, - 298, 0, 108, 0, 78, 0, 0, 0, 110, 0, - 0, 502, 501, 0, 75, 0, 0, 0, 0, 0, - 34, 106, 0, 41, 39, 40, 36, 42, 0, 0, - 0, 0, 0, 296, 276, 44, 45, 506, 507, 76, - 49, 50, 51, 52, 43, 54, 55, 56, 47, 53, - 57, 0, 0, 0, 0, 0, 0, 33, 48, 111, - 112, 113, 0, 114, 115, 116, 117, 118, 714, 0, - 0, 119, 89, 92, 90, 91, 94, 95, 96, 97, - 0, 0, 0, 0, 0, 0, 0, 86, 87, 0, - 0, 0, 101, 73, 110, 80, 81, 82, 0, 107, - 0, 102, 105, 103, 104, 22, 74, 79, 0, 0, + 126, 61, 1059, 1125, 1090, 1098, 1124, 1009, 132, 507, + 921, 426, 1058, 677, 755, 203, 634, 204, 920, 807, + 265, 1037, 309, 733, 640, 857, 555, 68, 728, 143, + 621, 856, 299, 638, 641, 933, 506, 26, 585, 266, + 600, 609, 505, 25, 569, 692, 99, 263, 490, 484, + 146, 499, 275, 262, 618, 554, 605, 1, 361, 440, + 364, 156, 156, 135, 159, 734, 287, 445, 294, 444, + 546, 85, 84, 290, 1044, 61, 188, 273, 27, 211, + 153, 247, 334, 215, 301, 355, 1048, 255, 78, 80, + 1012, 140, 111, 72, 142, 236, 139, 197, 235, 141, + 855, 250, 236, 235, 202, 524, 448, 137, 449, 450, + 451, 443, 350, 80, 446, 157, 513, 112, 236, 895, + 896, 235, 1055, 827, 61, 448, 61, 449, 450, 451, + 443, 165, 816, 446, 780, 127, 35, 745, 80, 744, + 261, 741, 181, 340, 122, 143, 80, 1031, 258, 303, + 897, 898, 881, 882, 80, 953, 747, 748, 704, 705, + 26, 725, 722, 292, 721, 80, 25, 80, 706, 702, + 648, 112, 645, 270, 899, 293, 79, 194, 576, 80, + 103, 256, 522, 351, 438, 80, 351, 295, 878, 236, + 351, 121, 235, 433, 359, 288, 289, 298, 278, 194, + 143, 79, 227, 226, 228, 229, 230, 315, 1030, 79, + 501, 3, 351, 376, 322, 144, 351, 79, 1028, 1027, + 354, 622, 447, 1026, 377, 274, 1024, 1006, 79, 1005, + 79, 1004, 353, 1003, 999, 310, 994, 313, 314, 992, + 614, 144, 79, 991, 990, 989, 377, 377, 79, 113, + 114, 115, 339, 116, 117, 118, 119, 120, 61, 35, + 965, 946, 944, 80, 943, 144, 28, 932, 919, 883, + 375, 880, 582, 907, 853, 829, 826, 823, 137, 820, + 804, 797, 779, 628, 121, 762, 743, 303, 740, 724, + 144, 429, 402, 403, 26, 357, 358, 395, 144, 520, + 25, 455, 370, 113, 114, 115, 376, 280, 281, 282, + 283, 284, 305, 306, 307, 413, 1043, 144, 594, 144, + 391, 670, 430, 396, 397, 398, 79, 669, 668, 667, + 665, 144, 549, 631, 3, 544, 543, 300, 217, 542, + 637, 199, 537, 156, 227, 226, 228, 229, 230, 535, + 61, 473, 533, 459, 547, 436, 143, 431, 143, 143, + 80, 414, 620, 439, 497, 347, 460, 511, 348, 346, + 435, 955, 947, 150, 377, 945, 941, 61, 103, 293, + 377, 377, 931, 901, 489, 887, 865, 863, 495, 496, + 862, 861, 199, 35, 859, 112, 469, 833, 776, 197, + 774, 773, 764, 707, 680, 377, 548, 548, 548, 657, + 617, 199, 228, 229, 230, 583, 703, 475, 61, 474, + 529, 458, 434, 494, 154, 595, 531, 532, 149, 260, + 492, 493, 143, 254, 516, 244, 516, 516, 303, 519, + 521, 243, 526, 525, 515, 242, 517, 518, 303, 241, + 240, 545, 239, 238, 26, 237, 328, 249, 540, 326, + 25, 1066, 967, 650, 123, 316, 194, 570, 3, 145, + 408, 574, 143, 461, 143, 559, 1054, 550, 551, 792, + 612, 777, 694, 775, 1018, 35, 696, 590, 454, 918, + 552, 288, 472, 318, 917, 836, 871, 772, 869, 599, + 571, 770, 643, 647, 581, 598, 597, 769, 768, 765, + 596, 589, 144, 652, 608, 293, 607, 149, 274, 771, + 674, 739, 575, 566, 858, 587, 682, 113, 114, 115, + 624, 116, 117, 118, 119, 120, 671, 154, 658, 245, + 693, 675, 409, 664, 672, 246, 317, 423, 679, 172, + 173, 572, 103, 35, 619, 681, 998, 61, 627, 629, + 956, 625, 580, 225, 61, 673, 471, 199, 422, 1149, + 1139, 1134, 1133, 1128, 1114, 327, 319, 320, 325, 1113, + 1105, 659, 1081, 377, 143, 661, 161, 1073, 695, 1065, + 567, 1062, 1020, 26, 678, 1017, 699, 1016, 978, 25, + 26, 966, 930, 929, 303, 303, 25, 1095, 271, 134, + 21, 685, 303, 924, 686, 850, 170, 171, 174, 175, + 849, 690, 143, 785, 684, 712, 649, 560, 3, 678, + 558, 1094, 1070, 124, 1069, 610, 701, 726, 700, 160, + 710, 698, 1127, 199, 720, 162, 1126, 1126, 1061, 1011, + 708, 61, 1060, 178, 61, 61, 179, 180, 143, 183, + 184, 185, 187, 248, 191, 719, 923, 760, 759, 163, + 922, 709, 723, 654, 653, 557, 619, 377, 349, 556, + 1111, 1060, 1035, 736, 196, 922, 201, 847, 619, 556, + 419, 417, 35, 1150, 1130, 749, 1106, 751, 199, 35, + 1089, 1064, 753, 1021, 1008, 757, 758, 926, 786, 754, + 619, 563, 257, 1152, 1108, 303, 1091, 303, 303, 303, + 1023, 619, 303, 778, 1010, 789, 756, 415, 264, 1146, + 1145, 1132, 791, 21, 1131, 196, 790, 787, 199, 796, + 199, 799, 1087, 985, 788, 984, 805, 806, 928, 810, + 927, 752, 1127, 1061, 612, 61, 923, 557, 835, 802, + 61, 61, 803, 817, 1153, 1148, 1122, 3, 1104, 839, + 840, 1051, 643, 841, 3, 798, 643, 1019, 874, 838, + 822, 377, 844, 1078, 331, 332, 35, 61, 784, 35, + 35, 713, 715, 312, 872, 587, 1143, 1085, 143, 867, + 619, 982, 867, 342, 688, 866, 845, 1121, 870, 1099, + 1103, 851, 852, 303, 199, 303, 303, 303, 619, 1119, + 1120, 143, 1147, 26, 824, 825, 885, 678, 1118, 25, + 888, 889, 877, 1102, 1101, 143, 876, 61, 782, 216, + 1099, 249, 109, 463, 875, 890, 1117, 891, 61, 612, + 199, 904, 373, 1076, 902, 903, 372, 374, 894, 676, + 1077, 405, 1049, 1079, 1013, 404, 514, 21, 352, 623, + 407, 406, 209, 356, 421, 868, 884, 424, 425, 377, + 380, 379, 808, 809, 143, 821, 1136, 335, 199, 1100, + 35, 867, 951, 329, 303, 35, 35, 942, 950, 925, + 377, 112, 949, 143, 957, 811, 813, 606, 815, 610, + 958, 914, 110, 962, 718, 717, 286, 1097, 61, 61, + 1100, 969, 35, 61, 199, 678, 959, 61, 278, 604, + 603, 972, 143, 973, 905, 476, 478, 481, 483, 486, + 979, 267, 268, 971, 486, 491, 678, 268, 987, 491, + 491, 935, 601, 498, 377, 602, 963, 269, 988, 21, + 936, 864, 938, 939, 940, 441, 136, 1000, 61, 208, + 209, 210, 35, 867, 980, 934, 738, 993, 983, 996, + 737, 336, 448, 35, 449, 450, 451, 443, 746, 1015, + 446, 735, 914, 914, 619, 794, 795, 3, 1022, 1025, + 678, 1014, 152, 892, 610, 151, 214, 143, 977, 61, + 1001, 448, 61, 449, 450, 451, 622, 854, 843, 61, + 837, 1045, 61, 448, 834, 449, 450, 21, 742, 646, + 487, 143, 377, 113, 114, 115, 61, 116, 117, 118, + 119, 120, 914, 69, 591, 1057, 995, 909, 619, 285, + 112, 1068, 389, 35, 35, 272, 377, 291, 35, 148, + 432, 61, 35, 1074, 199, 61, 147, 61, 616, 1080, + 61, 61, 1082, 1052, 1029, 1002, 1045, 112, 678, 1045, + 1045, 164, 166, 914, 467, 107, 697, 199, 1088, 564, + 61, 1092, 1093, 914, 1107, 61, 61, 464, 465, 1045, + 148, 199, 678, 35, 1045, 1045, 466, 61, 437, 338, + 914, 1109, 61, 651, 337, 333, 1115, 1116, 107, 104, + 104, 1045, 107, 1137, 103, 207, 1138, 61, 909, 909, + 488, 61, 1140, 1129, 311, 914, 1045, 213, 71, 914, + 1045, 70, 155, 1110, 35, 1034, 846, 35, 1141, 1151, + 199, 61, 1144, 913, 35, 416, 10, 35, 1155, 9, + 1045, 729, 730, 731, 732, 586, 21, 687, 8, 199, + 7, 35, 1154, 21, 418, 691, 65, 362, 909, 297, + 296, 914, 113, 114, 115, 302, 116, 117, 118, 119, + 120, 975, 976, 304, 276, 279, 35, 1135, 199, 1096, + 35, 1075, 35, 1053, 64, 35, 35, 94, 63, 113, + 114, 115, 366, 116, 117, 118, 119, 120, 62, 909, + 67, 59, 1039, 66, 60, 35, 793, 577, 427, 909, + 35, 35, 58, 212, 913, 913, 573, 568, 565, 6, + 20, 1007, 35, 19, 73, 169, 909, 35, 17, 642, + 639, 16, 5, 485, 15, 486, 14, 11, 491, 18, + 21, 13, 35, 21, 21, 12, 35, 1040, 910, 86, + 1038, 909, 112, 199, 908, 909, 502, 1039, 500, 4, + 1039, 1039, 1033, 2, 913, 0, 35, 0, 0, 0, + 0, 0, 1050, 0, 133, 0, 0, 199, 298, 278, + 1039, 0, 0, 112, 0, 1039, 1039, 0, 448, 1063, + 449, 450, 451, 443, 808, 809, 446, 909, 0, 0, + 0, 0, 1039, 189, 0, 913, 0, 198, 0, 536, + 122, 0, 819, 611, 1083, 913, 0, 1039, 1086, 0, + 0, 1039, 0, 0, 195, 0, 0, 0, 832, 0, + 0, 0, 913, 0, 259, 0, 842, 233, 234, 0, + 0, 1039, 0, 0, 21, 0, 848, 0, 0, 21, + 21, 251, 252, 0, 0, 0, 0, 913, 198, 0, + 1123, 913, 223, 232, 231, 222, 221, 224, 220, 0, + 0, 0, 0, 0, 0, 195, 21, 198, 0, 421, + 0, 133, 0, 0, 113, 114, 115, 0, 280, 281, + 282, 283, 284, 305, 306, 307, 0, 0, 0, 189, + 0, 0, 0, 913, 223, 232, 231, 222, 221, 224, + 220, 0, 0, 0, 0, 113, 114, 115, 300, 116, + 117, 118, 119, 120, 0, 0, 21, 0, 0, 0, + 0, 767, 0, 0, 0, 223, 232, 21, 222, 221, + 224, 220, 0, 29, 344, 0, 0, 218, 217, 0, + 0, 0, 0, 219, 227, 226, 228, 229, 230, 0, + 0, 0, 341, 0, 0, 363, 0, 367, 368, 369, + 0, 371, 138, 0, 378, 0, 381, 382, 383, 384, + 385, 386, 387, 0, 308, 0, 189, 393, 363, 218, + 217, 0, 189, 189, 189, 219, 227, 226, 228, 229, + 230, 968, 0, 766, 410, 970, 974, 21, 21, 0, + 189, 0, 21, 981, 420, 0, 21, 0, 200, 428, + 218, 217, 0, 0, 0, 0, 219, 227, 226, 228, + 229, 230, 0, 198, 0, 0, 0, 0, 0, 0, + 0, 442, 223, 232, 231, 222, 221, 224, 220, 0, + 0, 0, 0, 0, 0, 112, 0, 21, 0, 0, + 0, 0, 0, 0, 189, 0, 470, 0, 0, 200, + 0, 390, 392, 0, 0, 112, 0, 399, 400, 401, + 457, 223, 232, 231, 222, 221, 224, 220, 200, 80, + 0, 189, 0, 0, 0, 0, 0, 0, 21, 0, + 1036, 21, 122, 0, 0, 0, 0, 0, 21, 198, + 0, 21, 0, 848, 0, 0, 0, 0, 0, 0, + 0, 0, 528, 0, 530, 21, 189, 218, 217, 0, + 0, 1067, 0, 219, 227, 226, 228, 229, 230, 0, + 0, 189, 873, 200, 0, 0, 189, 189, 189, 468, + 21, 1084, 79, 0, 21, 0, 21, 112, 0, 21, + 21, 0, 0, 0, 584, 420, 218, 217, 0, 561, + 0, 80, 219, 227, 226, 228, 229, 230, 0, 21, + 997, 1112, 0, 0, 21, 21, 0, 113, 114, 115, + 0, 116, 117, 118, 119, 120, 21, 0, 1036, 0, + 0, 21, 0, 0, 632, 0, 636, 113, 114, 115, + 0, 116, 117, 118, 119, 120, 21, 1142, 0, 0, + 21, 89, 0, 0, 0, 0, 534, 0, 0, 0, + 0, 538, 539, 541, 79, 0, 0, 0, 0, 0, + 21, 144, 1112, 0, 200, 0, 223, 232, 231, 222, + 221, 224, 220, 0, 133, 0, 158, 0, 0, 0, + 112, 167, 168, 0, 176, 177, 0, 0, 0, 0, + 182, 0, 363, 0, 186, 0, 190, 662, 192, 193, + 198, 0, 0, 0, 0, 0, 666, 278, 112, 113, + 114, 115, 0, 116, 117, 118, 119, 120, 0, 200, + 0, 200, 200, 683, 0, 0, 0, 0, 0, 0, + 0, 0, 689, 0, 0, 278, 198, 0, 0, 0, + 200, 0, 0, 144, 0, 0, 428, 0, 0, 0, + 253, 218, 217, 0, 0, 0, 0, 219, 227, 226, + 228, 229, 230, 0, 0, 345, 341, 0, 0, 0, + 0, 711, 189, 0, 727, 0, 0, 0, 0, 0, + 0, 0, 277, 0, 277, 0, 0, 0, 0, 0, + 277, 0, 277, 223, 277, 200, 222, 221, 224, 220, + 0, 0, 321, 277, 323, 324, 0, 0, 0, 0, + 761, 330, 113, 114, 115, 0, 116, 117, 118, 119, + 120, 0, 0, 0, 223, 232, 231, 222, 221, 224, + 220, 0, 0, 763, 0, 200, 0, 200, 0, 0, + 113, 114, 115, 0, 280, 281, 282, 283, 284, 0, + 781, 0, 0, 0, 0, 360, 0, 365, 0, 0, + 0, 0, 0, 223, 232, 231, 222, 221, 224, 220, + 0, 0, 112, 800, 0, 189, 0, 388, 218, 217, + 365, 0, 0, 0, 219, 227, 226, 228, 229, 230, + 0, 0, 0, 0, 0, 0, 0, 411, 298, 278, + 0, 0, 0, 0, 0, 828, 0, 0, 112, 218, + 217, 200, 0, 0, 277, 219, 227, 226, 228, 229, + 230, 0, 0, 0, 553, 0, 420, 277, 277, 0, + 0, 0, 0, 893, 0, 0, 0, 860, 452, 0, + 0, 0, 277, 0, 0, 456, 0, 200, 218, 217, + 879, 0, 0, 462, 219, 227, 226, 228, 229, 230, + 801, 0, 0, 341, 0, 0, 0, 477, 479, 480, + 482, 0, 0, 900, 0, 0, 0, 0, 886, 0, + 277, 0, 0, 0, 0, 200, 0, 906, 0, 0, + 0, 0, 510, 0, 512, 0, 0, 0, 0, 0, + 0, 0, 112, 0, 113, 114, 115, 0, 280, 281, + 282, 283, 284, 305, 306, 307, 0, 0, 0, 0, + 0, 200, 0, 0, 0, 0, 0, 0, 298, 278, + 0, 0, 0, 0, 0, 0, 954, 0, 300, 0, + 113, 114, 115, 948, 116, 117, 118, 119, 120, 0, + 0, 0, 189, 0, 0, 964, 0, 0, 0, 0, + 0, 0, 0, 814, 0, 0, 189, 0, 189, 0, + 0, 0, 0, 0, 588, 277, 592, 0, 0, 277, + 277, 0, 133, 0, 986, 0, 0, 0, 0, 277, + 112, 0, 0, 0, 0, 613, 0, 456, 0, 615, + 0, 0, 0, 588, 0, 189, 626, 588, 588, 630, + 0, 0, 0, 633, 635, 453, 0, 644, 0, 0, + 0, 0, 223, 232, 231, 222, 221, 224, 220, 0, + 0, 0, 0, 0, 113, 114, 115, 952, 280, 281, + 282, 283, 284, 305, 306, 307, 0, 0, 0, 0, + 0, 960, 0, 961, 0, 655, 656, 428, 0, 1032, + 0, 200, 0, 635, 365, 660, 388, 0, 300, 112, + 81, 82, 83, 0, 109, 0, 103, 107, 104, 105, + 420, 75, 106, 1056, 200, 0, 223, 232, 231, 222, + 221, 224, 220, 129, 0, 0, 122, 0, 200, 0, + 0, 0, 0, 0, 0, 0, 0, 218, 217, 0, + 0, 0, 133, 219, 227, 226, 228, 229, 230, 0, + 0, 937, 113, 114, 115, 588, 116, 117, 118, 119, + 120, 0, 0, 0, 0, 0, 100, 588, 0, 0, + 101, 0, 0, 0, 110, 277, 277, 200, 0, 0, + 0, 0, 0, 131, 128, 0, 0, 0, 0, 588, + 0, 420, 635, 108, 0, 0, 200, 626, 0, 0, + 588, 218, 217, 0, 0, 0, 0, 219, 227, 226, + 228, 229, 230, 0, 0, 783, 0, 0, 750, 0, + 0, 0, 0, 0, 0, 200, 112, 0, 0, 130, + 0, 113, 114, 115, 0, 116, 117, 118, 119, 120, + 0, 112, 0, 121, 90, 93, 91, 92, 95, 96, + 97, 98, 298, 278, 0, 0, 0, 0, 0, 87, + 88, 366, 0, 0, 102, 74, 394, 298, 278, 0, + 0, 0, 0, 0, 588, 0, 0, 0, 277, 588, + 0, 0, 0, 0, 0, 0, 0, 812, 0, 277, + 277, 0, 0, 277, 818, 0, 0, 588, 0, 0, + 200, 0, 716, 588, 588, 0, 0, 0, 0, 830, + 831, 0, 0, 635, 0, 0, 0, 0, 112, 81, + 82, 83, 0, 109, 200, 103, 107, 104, 105, 22, + 75, 106, 80, 0, 0, 37, 38, 0, 0, 0, + 0, 0, 30, 0, 0, 122, 0, 31, 46, 0, + 32, 0, 0, 0, 0, 0, 0, 0, 113, 114, + 115, 0, 280, 281, 282, 283, 284, 305, 306, 307, + 0, 0, 0, 113, 114, 115, 0, 280, 281, 282, + 283, 284, 305, 306, 307, 100, 0, 277, 277, 101, + 0, 0, 300, 110, 0, 79, 112, 0, 0, 626, + 0, 0, 1042, 1041, 0, 915, 0, 300, 112, 0, + 412, 34, 108, 0, 41, 39, 40, 36, 42, 112, + 0, 389, 298, 278, 0, 0, 44, 45, 508, 509, + 0, 49, 50, 51, 52, 43, 54, 55, 56, 47, + 53, 57, 0, 0, 0, 916, 0, 0, 33, 48, + 113, 114, 115, 0, 116, 117, 118, 119, 120, 635, + 0, 0, 121, 90, 93, 91, 92, 95, 96, 97, + 98, 0, 0, 588, 0, 0, 0, 0, 87, 88, + 0, 0, 0, 102, 74, 0, 0, 0, 0, 0, + 0, 0, 0, 112, 81, 82, 83, 0, 109, 0, + 103, 107, 104, 105, 22, 75, 106, 80, 0, 0, 37, 38, 0, 0, 0, 0, 0, 30, 0, 0, - 120, 0, 31, 46, 0, 32, 111, 112, 113, 0, - 114, 115, 116, 117, 118, 0, 0, 0, 0, 111, - 112, 113, 0, 278, 279, 280, 281, 282, 303, 304, - 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 110, 0, 387, 100, 0, 0, 0, 108, 0, - 78, 0, 0, 298, 110, 0, 0, 910, 909, 0, - 913, 0, 0, 0, 0, 0, 34, 106, 0, 41, - 39, 40, 36, 42, 0, 0, 0, 0, 0, 296, - 276, 44, 45, 0, 0, 0, 49, 50, 51, 52, + 122, 0, 31, 46, 0, 32, 0, 588, 113, 114, + 115, 0, 280, 281, 282, 283, 284, 305, 306, 307, + 113, 114, 115, 0, 116, 117, 118, 119, 120, 0, + 0, 113, 114, 115, 0, 116, 117, 118, 119, 120, + 100, 0, 300, 0, 101, 0, 0, 0, 110, 0, + 79, 0, 0, 112, 0, 0, 0, 504, 503, 0, + 76, 0, 0, 0, 1046, 1047, 34, 108, 0, 41, + 39, 40, 36, 42, 0, 0, 0, 0, 0, 298, + 278, 44, 45, 508, 509, 77, 49, 50, 51, 52, 43, 54, 55, 56, 47, 53, 57, 0, 0, 0, - 914, 0, 0, 33, 48, 111, 112, 113, 0, 114, - 115, 116, 117, 118, 712, 0, 0, 119, 89, 92, - 90, 91, 94, 95, 96, 97, 0, 0, 0, 0, - 0, 0, 0, 86, 87, 0, 0, 0, 101, 73, - 110, 80, 81, 82, 0, 107, 0, 102, 105, 103, - 104, 22, 74, 79, 0, 0, 37, 38, 0, 0, - 0, 0, 0, 30, 0, 0, 120, 0, 31, 46, - 0, 32, 111, 112, 113, 0, 114, 115, 116, 117, - 118, 0, 0, 0, 0, 111, 112, 113, 0, 278, - 279, 280, 281, 282, 303, 304, 305, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, - 100, 0, 0, 0, 108, 0, 78, 0, 0, 298, - 0, 0, 0, 24, 23, 0, 75, 0, 0, 0, - 0, 0, 34, 106, 0, 41, 39, 40, 36, 42, - 0, 0, 0, 0, 0, 0, 0, 44, 45, 521, - 0, 76, 49, 50, 51, 52, 43, 54, 55, 56, - 47, 53, 57, 0, 0, 0, 0, 0, 0, 33, - 48, 111, 112, 113, 0, 114, 115, 116, 117, 118, - 0, 0, 0, 119, 89, 92, 90, 91, 94, 95, - 96, 97, 221, 230, 229, 220, 219, 222, 218, 86, - 87, 0, 0, 0, 101, 73, 110, 80, 81, 82, - 0, 107, 0, 102, 105, 103, 104, 0, 74, 79, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, - 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 110, 80, 81, 82, 0, 107, 0, - 102, 105, 103, 104, 0, 74, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 127, 0, 0, 120, - 0, 0, 99, 0, 0, 0, 100, 216, 215, 0, - 108, 0, 78, 217, 225, 224, 226, 227, 228, 129, - 126, 0, 0, 0, 0, 0, 0, 0, 0, 106, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 0, 0, 0, 100, 0, 0, 0, 108, 0, 0, - 0, 0, 0, 0, 0, 0, 129, 126, 0, 0, - 0, 0, 0, 0, 0, 128, 106, 111, 112, 113, - 0, 114, 115, 116, 117, 118, 0, 0, 0, 119, - 89, 92, 90, 91, 94, 95, 96, 97, 0, 0, - 0, 0, 0, 0, 0, 86, 87, 0, 0, 0, - 101, 73, 128, 0, 111, 112, 113, 0, 114, 115, - 116, 117, 118, 0, 0, 0, 119, 89, 92, 90, - 91, 94, 95, 96, 97, 221, 661, 229, 220, 219, - 222, 218, 86, 87, 364, 0, 0, 101, 73, 110, - 80, 81, 82, 0, 107, 0, 102, 105, 103, 104, - 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 127, 0, 0, 120, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 110, 80, 81, 82, - 0, 107, 0, 102, 105, 103, 104, 0, 74, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, - 0, 0, 120, 0, 0, 99, 0, 0, 0, 100, - 216, 215, 0, 108, 214, 0, 217, 225, 224, 226, - 227, 228, 129, 126, 0, 0, 0, 0, 0, 0, - 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, - 108, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 126, 0, 0, 0, 0, 0, 0, 0, 128, 106, - 111, 112, 113, 0, 114, 115, 116, 117, 118, 0, - 0, 0, 119, 89, 92, 90, 91, 94, 95, 96, - 97, 0, 0, 0, 0, 0, 0, 0, 86, 87, - 0, 0, 0, 101, 73, 128, 0, 111, 112, 113, - 0, 114, 115, 116, 117, 118, 0, 0, 0, 119, - 89, 92, 90, 91, 94, 95, 96, 97, 221, 525, - 229, 220, 219, 222, 218, 86, 87, 0, 0, 0, - 101, 73, 110, 80, 81, 82, 0, 107, 0, 102, - 105, 103, 104, 0, 74, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 127, 0, 0, 120, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, - 80, 81, 82, 0, 107, 0, 102, 105, 103, 104, - 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 127, 0, 0, 591, 0, 0, 99, 0, - 0, 0, 100, 216, 215, 0, 108, 0, 0, 217, - 225, 224, 226, 227, 228, 129, 126, 0, 0, 0, - 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 0, 0, 0, 100, - 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, - 0, 0, 129, 126, 0, 0, 0, 0, 0, 0, - 0, 128, 106, 111, 112, 113, 0, 114, 115, 116, - 117, 118, 0, 0, 0, 119, 89, 92, 90, 91, - 94, 95, 96, 97, 0, 0, 0, 0, 0, 0, - 0, 86, 87, 0, 0, 0, 101, 123, 128, 0, - 111, 112, 113, 0, 114, 115, 116, 117, 118, 0, - 0, 0, 119, 89, 92, 90, 91, 94, 95, 96, - 97, 0, 0, 0, 0, 0, 0, 0, 86, 87, - 0, 0, 0, 101, 73, 110, 80, 341, 82, 0, - 107, 0, 102, 105, 103, 104, 0, 74, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, - 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, + 1071, 1072, 0, 33, 48, 113, 114, 115, 0, 116, + 117, 118, 119, 120, 714, 0, 0, 121, 90, 93, + 91, 92, 95, 96, 97, 98, 0, 0, 0, 0, + 0, 0, 0, 87, 88, 0, 0, 0, 102, 74, + 112, 81, 82, 83, 0, 109, 0, 103, 107, 104, + 105, 22, 75, 106, 80, 0, 0, 37, 38, 0, + 0, 0, 0, 0, 30, 0, 0, 122, 0, 31, + 46, 0, 32, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 113, 114, 115, 0, 280, + 281, 282, 283, 284, 305, 306, 307, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 100, 0, 112, + 0, 101, 0, 0, 0, 110, 103, 79, 0, 300, + 0, 0, 0, 0, 912, 911, 0, 915, 0, 0, + 0, 0, 0, 34, 108, 0, 41, 39, 40, 36, + 42, 0, 0, 0, 0, 0, 0, 0, 44, 45, + 0, 0, 0, 49, 50, 51, 52, 43, 54, 55, + 56, 47, 53, 57, 0, 0, 0, 916, 0, 0, + 33, 48, 113, 114, 115, 0, 116, 117, 118, 119, + 120, 0, 0, 0, 121, 90, 93, 91, 92, 95, + 96, 97, 98, 0, 0, 0, 0, 0, 0, 0, + 87, 88, 0, 0, 0, 102, 74, 112, 81, 82, + 83, 0, 109, 0, 103, 107, 104, 105, 22, 75, + 106, 80, 0, 0, 37, 38, 0, 0, 0, 0, + 0, 30, 0, 0, 122, 0, 31, 46, 0, 32, + 0, 113, 114, 115, 0, 116, 117, 118, 119, 120, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 100, 0, 0, 0, 101, 0, + 0, 0, 110, 0, 79, 0, 0, 0, 0, 0, + 0, 24, 23, 0, 76, 0, 0, 0, 0, 0, + 34, 108, 0, 41, 39, 40, 36, 42, 0, 0, + 0, 0, 0, 0, 0, 44, 45, 0, 0, 77, + 49, 50, 51, 52, 43, 54, 55, 56, 47, 53, + 57, 0, 0, 0, 0, 0, 0, 33, 48, 113, + 114, 115, 0, 116, 117, 118, 119, 120, 0, 0, + 0, 121, 90, 93, 91, 92, 95, 96, 97, 98, + 0, 0, 0, 0, 0, 0, 0, 87, 88, 0, + 0, 0, 102, 74, 112, 81, 82, 83, 0, 109, + 0, 103, 107, 104, 105, 0, 75, 106, 80, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, + 0, 122, 223, 232, 231, 222, 221, 224, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 100, 0, 0, 0, 101, 0, 0, 0, 110, + 0, 79, 0, 0, 0, 0, 0, 0, 131, 128, + 0, 0, 112, 81, 82, 83, 0, 109, 108, 103, + 107, 104, 105, 0, 75, 106, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 129, 218, 217, 122, + 0, 0, 0, 219, 227, 226, 228, 229, 230, 0, + 0, 0, 0, 0, 130, 0, 113, 114, 115, 0, + 116, 117, 118, 119, 120, 0, 0, 0, 121, 90, + 93, 91, 92, 95, 96, 97, 98, 0, 0, 100, + 0, 0, 0, 101, 87, 88, 0, 110, 0, 102, + 74, 0, 0, 0, 0, 0, 131, 128, 0, 0, + 0, 0, 0, 0, 0, 206, 108, 0, 112, 81, + 82, 83, 0, 109, 0, 103, 107, 104, 105, 0, + 75, 106, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 129, 0, 0, 122, 0, 0, 0, 0, + 0, 0, 205, 0, 113, 114, 115, 0, 116, 117, + 118, 119, 120, 0, 0, 0, 121, 90, 93, 91, + 92, 95, 96, 97, 98, 0, 0, 0, 0, 0, + 0, 0, 87, 88, 0, 100, 0, 102, 74, 101, + 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 0, 131, 128, 0, 0, 112, 81, 82, 83, + 0, 109, 108, 103, 107, 104, 105, 0, 75, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 99, 0, 0, 0, 100, 0, 0, 0, 108, - 0, 0, 0, 0, 0, 0, 0, 0, 129, 126, - 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, + 129, 0, 0, 122, 0, 0, 0, 0, 223, 232, + 231, 222, 221, 224, 220, 0, 0, 0, 130, 0, + 113, 114, 115, 0, 116, 117, 118, 119, 120, 562, + 0, 0, 121, 90, 93, 91, 92, 95, 96, 97, + 98, 0, 0, 100, 0, 0, 0, 101, 87, 88, + 366, 110, 216, 102, 74, 0, 0, 0, 0, 0, + 131, 128, 0, 0, 112, 81, 82, 83, 0, 109, + 108, 103, 107, 104, 105, 0, 75, 106, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, + 0, 122, 0, 218, 217, 0, 0, 0, 0, 219, + 227, 226, 228, 229, 230, 0, 130, 0, 113, 114, + 115, 0, 116, 117, 118, 119, 120, 0, 0, 0, + 121, 90, 93, 91, 92, 95, 96, 97, 98, 0, + 0, 100, 0, 0, 0, 101, 87, 88, 0, 110, + 523, 102, 74, 0, 0, 0, 0, 0, 131, 128, + 0, 0, 112, 81, 82, 83, 0, 109, 108, 103, + 107, 104, 105, 0, 75, 106, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 129, 0, 0, 122, + 0, 0, 0, 223, 232, 231, 222, 221, 224, 220, + 0, 0, 0, 0, 130, 0, 113, 114, 115, 0, + 116, 117, 118, 119, 120, 0, 0, 0, 121, 90, + 93, 91, 92, 95, 96, 97, 98, 0, 0, 100, + 0, 0, 0, 101, 87, 88, 0, 110, 0, 102, + 74, 0, 0, 0, 0, 0, 131, 128, 0, 0, + 112, 81, 82, 83, 0, 109, 108, 103, 107, 104, + 105, 0, 75, 106, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 0, 0, 593, 218, 217, + 0, 0, 0, 0, 219, 227, 226, 228, 229, 230, + 0, 0, 130, 0, 113, 114, 115, 0, 116, 117, + 118, 119, 120, 0, 0, 0, 121, 90, 93, 91, + 92, 95, 96, 97, 98, 0, 0, 100, 0, 0, + 0, 101, 87, 88, 0, 110, 0, 102, 125, 0, + 578, 579, 0, 0, 131, 128, 0, 0, 112, 81, + 343, 83, 0, 109, 108, 103, 107, 104, 105, 0, + 75, 106, 223, 232, 231, 222, 221, 224, 220, 0, + 0, 0, 129, 0, 0, 122, 223, 232, 231, 222, + 221, 224, 220, 0, 0, 0, 0, 0, 0, 0, + 130, 0, 113, 114, 115, 0, 116, 117, 118, 119, + 120, 0, 0, 0, 121, 90, 93, 91, 92, 95, + 96, 97, 98, 0, 0, 100, 0, 0, 0, 101, + 87, 88, 0, 110, 0, 102, 74, 0, 0, 0, + 0, 0, 131, 128, 223, 663, 231, 222, 221, 224, + 220, 0, 108, 0, 0, 0, 0, 218, 217, 0, + 0, 0, 0, 219, 227, 226, 228, 229, 230, 0, + 0, 218, 217, 0, 0, 0, 0, 219, 227, 226, + 228, 229, 230, 0, 0, 0, 0, 0, 130, 0, + 113, 114, 115, 0, 116, 117, 118, 119, 120, 0, + 0, 0, 121, 90, 93, 91, 92, 95, 96, 97, + 98, 223, 527, 231, 222, 221, 224, 220, 87, 88, + 0, 0, 0, 102, 74, 0, 0, 0, 0, 218, + 217, 0, 0, 0, 0, 219, 227, 226, 228, 229, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 128, 0, 111, 112, 113, 0, - 114, 115, 116, 117, 118, 0, 0, 0, 119, 89, - 92, 90, 91, 94, 95, 96, 97, 0, 0, 0, - 0, 0, 0, 0, 86, 87, 0, 0, 0, 101, - 73, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 218, 217, 0, 0, + 0, 0, 219, 227, 226, 228, 229, 230, } var yyPact = [...]int{ - 3056, -1000, 333, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 2993, -1000, 302, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 3608, 3520, -1000, -1000, 920, 71, 1040, + 347, 968, 965, 367, 2895, -1000, 541, 1106, 1107, 2004, + 2004, 511, 2004, 3520, -1000, -1000, 3520, 3520, 1073, 3520, + 3520, 3520, 3520, 3520, 3520, -1000, 2004, 2004, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 307, -1000, + -1000, -1000, -1000, -1000, 3160, -1000, 3248, 1119, 903, 974, + 759, -1000, -1000, -1000, -1000, -1000, 3744, 3520, 3520, -75, + 285, 283, 282, 280, -1000, 279, 275, 271, 265, 382, + 45, 3520, 3520, -1000, -1000, -1000, -1000, -1000, 2004, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3628, 3462, -1000, -1000, 1008, 122, 1186, - 281, 1044, 1035, 358, 2473, -1000, 666, 1208, 1204, 2645, - 2645, 567, 2645, 3462, -1000, -1000, 3462, 3462, 1636, 3462, - 3462, 3462, 3462, 3462, 3462, -1000, 2645, 2645, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 354, -1000, - -1000, -1000, -1000, 3222, -1000, 2249, 1219, 1010, 1051, 869, - -1000, -1000, -1000, -1000, -1000, 2383, 3462, 3462, -73, 320, - 318, 317, 316, -1000, 315, 313, 298, 297, 434, 135, - 3462, 3462, -1000, -1000, -1000, -1000, 2645, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 282, - -82, 3056, 718, 3222, -1000, -1000, 280, 275, 274, 3462, - 741, 2383, -1000, 994, 995, 1008, 1186, 1151, 2339, 1149, - 1277, -1000, 121, 1178, 1154, 1213, 1587, 3462, 2339, 811, - 2339, -1000, 869, 38, 345, -1000, 573, -1000, 2645, 2154, - 2645, 2645, 468, 454, -1000, 937, -1000, 2645, -1000, -1000, - -1000, -1000, 3462, 3462, 1197, 27, 935, 1023, 1195, -1000, - 1190, -1000, -1000, 69, -73, -1000, -1000, 1749, -73, -1000, - -1000, 3831, 3462, 1431, 198, 196, 197, 217, 1178, 656, - 17, 901, 1213, 274, -1000, -1000, 911, 911, 911, -1000, - 35, 2645, -1000, 3259, -1000, 3462, 3462, 3462, 888, 3462, - 880, 64, 3462, 917, 3462, 3462, 3462, 3462, 3462, 3462, - 3462, -1000, -1000, 2957, 3425, 3462, 1939, 869, 869, 869, - 3462, 3462, 3462, 64, 64, 882, 908, -1000, -1000, 1171, - -1000, 437, 3462, 2791, -1000, 3056, 196, 193, 3462, 740, - 668, 664, 3462, 529, 501, 3462, 3462, 3462, 994, 1178, - 2339, 1162, 34, -1000, -1000, -1000, -1000, 271, -1000, -1000, - -1000, -1000, -1000, 2339, 1587, 1189, 32, 1154, 1006, 3462, - -1000, 31, -1000, 48, 2461, -1000, -1000, -1000, 2327, -1000, - -1000, 1790, 269, -1000, -1000, -1000, 188, -1000, 312, 2645, - 891, 1185, 3462, 1213, 3462, 526, 319, 268, 266, -1000, - -1000, -1000, -1000, 3462, 3462, 3462, 3462, 3462, 1146, -1000, - -1000, 1223, 3462, 3462, 1211, 1211, 2339, 3462, 3462, 3462, - -1000, 3462, 2383, -1000, -1000, -1000, -1000, 2724, 2645, 1213, - 2645, 58, 900, 217, -1000, 217, 217, 1051, 270, -1000, - 23, 3141, -1000, -60, -1000, 61, 6, 6, 938, 3547, - 3462, 64, 3462, -1000, 3222, -1000, 6, 64, 64, 288, - 288, -1000, -1000, -1000, 387, 1171, -1000, -1000, 185, 3462, - 181, 1214, -1000, 180, 3462, 3259, 3462, 179, 174, 173, - -1000, -1000, 64, 192, 192, 192, 888, -1000, 1730, -1000, - -1000, 655, -1000, 3462, 613, 3056, 612, 3462, 2057, 707, - 1173, 561, 489, 429, -1000, 22, 2196, 523, 1154, 169, - 1898, 2339, 3665, 177, 1154, 1587, 2154, 1006, 1001, 990, - 2383, 964, 961, 948, 1042, 126, -1000, -1000, -1000, -1000, - -1000, 2645, 77, 1790, -1000, 2645, 3462, -1000, 257, 1898, - 226, 905, 665, 1845, 1898, 2645, 172, -1000, 2383, 394, - 2645, 121, 189, 2645, -1000, -73, -1000, -73, -73, -1000, - -73, -1000, -1000, 20, 1137, 1213, -1000, -1000, -1000, 16, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 611, 330, -1000, - -1000, 3628, 3462, -1000, -1000, -1000, -1000, -1000, 645, -1000, - 642, 2645, 2645, 921, -1000, -1000, 921, -1000, 250, 2645, - 3259, 2645, 1179, -1000, -1000, 3462, 3344, -1000, 6, -1000, - -1000, 485, 170, -1000, 3462, -1000, 157, 146, 144, 143, - 484, 461, 428, 896, -1000, 168, -1000, 248, -1000, -1000, - 560, 3462, 609, 663, 3056, 3462, 826, -1000, -1000, 2383, - 3462, 3056, -1000, 3462, -1000, -1000, 436, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 3462, 389, -1000, -1000, 1172, 1006, - 64, 543, -1000, 1178, 13, 265, -70, -1000, -43, 12, - -73, -82, 241, 1898, -1000, 1154, -1000, 1001, -1000, 3462, - 3462, 2970, 2804, 959, -1000, 952, 948, -1000, 1143, 135, - 11, -1000, -1000, -1000, 10, 1898, 142, 7, 2645, 121, - -1000, -1000, 1078, 2645, 1029, -1000, 1898, 1019, 1015, 477, - -1000, -1000, 141, -3, -1000, 1113, 140, -6, -1000, -1000, - -10, 1014, -50, 3462, 2645, -1000, 3462, 781, 2724, 705, - 739, 2724, 2724, 639, 633, 121, 139, -1000, -1000, -1000, - 1171, 3462, 238, 474, 1715, 473, 467, 448, 446, 232, - 231, 388, 228, 384, 64, 137, -19, -1000, 3462, -1000, - 865, 2039, 809, 608, -1000, 702, -1000, 2209, 735, 489, - 979, -1000, 391, -1000, 1066, -1000, 1001, -1000, 131, 1154, - 1898, 3462, -1000, 3462, 2154, 1898, 124, -1000, 1008, 2383, - -1000, 968, 135, 1076, 135, 2631, 2364, 929, -48, 126, - 3462, 117, 933, 1898, 116, -1000, -1000, -1000, -1000, 1898, - 1898, 114, -58, 3462, 112, 2645, 3462, 225, 1102, 2645, - 419, 1095, 1213, 1213, 3462, 1085, 1213, -1000, -1000, -1000, - -1000, -1000, 2724, 662, 3462, 607, 604, 2724, 2724, 111, - 1079, 1171, 488, 223, -1000, 3462, 222, 221, 220, 1004, - 216, 488, 488, 447, 488, 413, -1000, -1000, 64, 1488, - -1000, -1000, -1000, 806, 3056, -1000, -1000, 3462, 436, -1000, - -1000, -1000, -1000, -1000, 1008, 136, -1000, -1000, 2383, 110, - -52, 109, 927, 994, -1000, -1000, 3462, 214, 947, 1076, - 135, 968, 135, 1574, 126, -1000, -77, -54, 134, 213, - -1000, 1070, -1000, -1000, 1078, 2645, 2383, -1000, -1000, -73, - -1000, 488, 121, -1000, 2890, 411, -1000, -1000, -1000, 1014, - -1000, 403, 108, 652, 603, 2724, 699, 778, 777, 602, - 601, -1000, 208, 107, -1000, 1012, 987, 488, 2024, 488, - 488, 488, 207, 488, 106, 1008, 94, 204, 90, 202, - -1000, 3462, -1000, 789, -1000, 994, 64, -1000, -1000, -1000, - 3462, 133, 201, 521, 2383, 2645, -1000, -1000, 947, -1000, - 968, 135, -1000, -1000, 3462, -1000, 3462, 64, -1000, 1898, - 121, -1000, -1000, 89, -1000, 599, 329, -1000, -1000, 3628, - 3462, -1000, -1000, 2249, 3462, 2890, 2890, 1062, 598, 659, - 2724, 3462, 817, -1000, 2724, -1000, -1000, 776, 774, 121, - -1000, -1000, 985, 3462, 88, -1000, 87, 85, 81, 1008, - 80, -1000, -1000, 488, -1000, 488, 258, -1000, 520, -1000, - 76, 64, -1000, 1898, 1168, 73, -1000, -1000, 72, 71, - -1000, 68, -1000, -1000, -1000, 2890, 698, 734, 632, 9, - 899, 1213, -1000, 597, 593, 399, 805, 592, -1000, 696, - -1000, 732, -1000, -1000, 67, 3462, -1000, -1000, -1000, -1000, - -1000, 66, -1000, 51, 47, -1000, 1167, -1000, -1000, 42, - -1000, -1000, -1000, -1000, 128, -1000, 2890, 658, 3462, 2551, - 2645, 2645, 26, 883, -1000, -1000, 2890, -1000, 803, 2724, - -1000, 3462, -1000, 382, -1000, -1000, -1000, -1000, 84, 64, - -1000, 649, 586, 2890, 680, 581, 296, -1000, -1000, 3628, - 3462, -1000, -1000, -1000, 620, 574, 2645, 2645, 572, -1000, - 785, -1000, 939, 64, -1000, -1000, 571, 653, 2890, 3462, - 816, -1000, 2890, 773, 2551, 679, 729, 2551, 2551, 568, - 544, -1000, -1000, -1000, 918, 861, 855, 836, -1000, 802, - 563, -1000, 678, -1000, 727, -1000, -1000, 2551, 631, 3462, - 559, 556, 2551, 2551, 895, 846, -1000, 857, 832, -1000, - -1000, -1000, -1000, 800, 2890, -1000, 3462, 630, 550, 2551, - 674, 764, 749, 547, 539, 906, -1000, -1000, -1000, -1000, - -1000, 784, 538, 562, 2551, 3462, 815, -1000, 2551, -1000, - -1000, 748, 746, -1000, 839, -1000, -1000, 795, 537, -1000, - 657, -1000, 721, -1000, -1000, -1000, -1000, 791, 2551, -1000, - 3462, -1000, 783, -1000, + -1000, 263, -86, 2993, 619, 3160, -1000, -1000, 259, 258, + 254, 3520, 636, 3744, -1000, 889, 908, 920, 1040, 1029, + 1804, 1023, 897, -1000, 149, 1081, 1033, 1113, 2562, 3520, + 1804, 704, 1804, -1000, 759, 35, 306, -1000, 448, -1000, + 2004, 1776, 2004, 2004, 415, 412, -1000, 830, -1000, 2004, + -1000, -1000, -1000, -1000, 3520, 3520, 1096, 19, 824, 937, + 1095, -1000, 1090, -1000, -1000, 80, -75, -1000, -1000, 1891, + -75, -1000, -1000, 3784, 3520, 1694, 198, 194, 197, 342, + 1081, 583, 40, 796, 1113, 254, -1000, -1000, 804, 804, + 804, -1000, 22, 2004, -1000, 3344, -1000, 3520, 3520, 3520, + 766, 3520, 780, 43, 3520, 811, 3520, 3520, 3520, 3520, + 3520, 3520, 3520, -1000, -1000, 2585, 3432, 3520, 2265, 759, + 759, 759, 3520, 3520, 3520, 43, 43, 789, 801, -1000, + -1000, 1821, -1000, 392, 3520, 2574, -1000, 2993, 194, 190, + 3520, 635, 597, 596, 3520, 469, 447, 3520, 3520, 3520, + 889, 1081, 1804, 1039, 21, -1000, -1000, -1000, -1000, 252, + -1000, -1000, -1000, -1000, -1000, 1804, 2562, 1089, 12, 1033, + 918, 3520, -1000, 11, -1000, 50, 2186, -1000, -1000, -1000, + 167, -1000, -1000, 1571, 251, -1000, -1000, -1000, 182, -1000, + 303, 2004, 768, 1063, 3520, 1113, 3520, 467, 322, 249, + 247, -1000, -1000, -1000, -1000, 3520, 3520, 3520, 3520, 3520, + 1004, -1000, -1000, 1125, 3520, 3520, 1110, 1110, 1804, 3520, + 3520, 3520, -1000, 3520, 3744, -1000, -1000, -1000, -1000, 2659, + 2004, 1113, 2004, 44, 794, 342, -1000, 342, 342, 974, + 270, -1000, 10, 3571, -1000, -68, -1000, 38, 180, 180, + 833, 3869, 3520, 43, 3520, -1000, 3160, -1000, 180, 43, + 43, 246, 246, -1000, -1000, -1000, 1383, 1821, -1000, -1000, + 181, 3520, 178, 1310, -1000, 171, 3520, 3344, 3520, 168, + 165, 164, -1000, -1000, 43, 184, 184, 184, 766, -1000, + 1852, -1000, -1000, 585, -1000, 3520, 534, 2993, 531, 3520, + 3396, 618, 1069, 485, 413, 384, -1000, 6, 3730, 463, + 1033, 245, 1299, 1804, 3696, 255, 1033, 2562, 1776, 918, + 904, 906, 3744, 875, 874, 850, 955, 1268, -1000, -1000, + -1000, -1000, -1000, 2004, 69, 1571, -1000, 2004, 3520, -1000, + 240, 1299, 192, 798, 391, 113, 1299, 2004, 162, -1000, + 3744, 1673, 2004, 149, 169, 2004, -1000, -75, -1000, -75, + -75, -1000, -75, -1000, -1000, 0, 1000, 1113, -1000, -1000, + -1000, -2, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 530, + 301, -1000, -1000, 3608, 3520, -1000, -1000, -1000, -1000, -1000, + 579, -1000, 578, 2004, 2004, 805, -1000, -1000, 805, -1000, + 239, 2004, 3344, 2004, 1046, -1000, -1000, 3520, 3802, -1000, + 180, -1000, -1000, 432, 159, -1000, 3520, -1000, 158, 157, + 156, 150, 425, 433, 409, 786, -1000, 136, -1000, 234, + -1000, -1000, 454, 3520, 528, 595, 2993, 3520, 716, -1000, + -1000, 3744, 3520, 2993, -1000, 3520, -1000, -1000, 401, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 3520, 349, -1000, -1000, + 1066, 918, 43, 1591, -1000, 1081, -3, 253, -70, -1000, + -13, -4, -75, -86, 233, 1299, -1000, 1033, -1000, 904, + -1000, 3520, 3520, 2739, 2407, 860, -1000, 859, 850, -1000, + 926, 45, -8, -1000, -1000, -1000, -10, 1299, 118, -11, + 2004, 149, -1000, -1000, 1123, 2004, 949, -1000, 1299, 936, + 932, 410, -1000, -1000, 117, -31, -1000, 999, 115, -33, + -1000, -1000, -35, 946, -15, 3520, 2004, -1000, 3520, 660, + 2659, 616, 634, 2659, 2659, 573, 572, 149, 114, -1000, + -1000, -1000, 1821, 3520, 232, 398, 1352, 397, 396, 390, + 386, 231, 230, 346, 228, 344, 43, 111, -38, -1000, + 3520, -1000, 756, 2214, 699, 527, -1000, 615, -1000, 3120, + 633, 413, 894, -1000, 343, -1000, 957, -1000, 904, -1000, + 110, 1033, 1299, 3520, -1000, 3520, 1776, 1299, 109, -1000, + 920, 3744, -1000, 967, 45, 1252, 45, 2392, 2098, 853, + -40, 1268, 3520, 108, 822, 1299, 106, -1000, -1000, -1000, + -1000, 1299, 1299, 105, -49, 3520, 104, 2004, 3520, 227, + 995, 2004, 365, 991, 1113, 1113, 3520, 989, 1113, -1000, + -1000, -1000, -1000, -1000, 2659, 593, 3520, 524, 519, 2659, + 2659, 103, 988, 1821, 414, 224, -1000, 3520, 221, 220, + 217, 914, 216, 414, 414, 387, 414, 385, -1000, -1000, + 43, 1490, -1000, -1000, -1000, 689, 2993, -1000, -1000, 3520, + 401, -1000, -1000, -1000, -1000, -1000, 920, 161, -1000, -1000, + 3744, 100, -19, 98, 813, 889, -1000, -1000, 3520, 215, + 820, 1252, 45, 967, 45, 1968, 1268, -1000, -52, -21, + 147, 213, -1000, 987, -1000, -1000, 1123, 2004, 3744, -1000, + -1000, -75, -1000, 414, 149, -1000, 2826, 364, -1000, -1000, + -1000, 946, -1000, 359, 97, 576, 517, 2659, 614, 659, + 657, 507, 506, -1000, 212, 96, -1000, 929, 902, 414, + 2150, 414, 414, 414, 206, 414, 93, 920, 91, 205, + 90, 202, -1000, 3520, -1000, 667, -1000, 889, 43, -1000, + -1000, -1000, 3520, 128, 201, 461, 3744, 2004, -1000, -1000, + 820, -1000, 967, 45, -1000, -1000, 3520, -1000, 3520, 43, + -1000, 1299, 149, -1000, -1000, 89, -1000, 505, 300, -1000, + -1000, 3608, 3520, -1000, -1000, 3248, 3520, 2826, 2826, 979, + 502, 591, 2659, 3520, 713, -1000, 2659, -1000, -1000, 654, + 652, 149, -1000, -1000, 899, 3520, 74, -1000, 73, 72, + 68, 920, 65, -1000, -1000, 414, -1000, 414, 1529, -1000, + 457, -1000, 63, 43, -1000, 1299, 1055, 62, -1000, -1000, + 60, 58, -1000, 56, -1000, -1000, -1000, 2826, 611, 632, + 554, 18, 792, 1113, -1000, 501, 499, 354, 688, 496, + -1000, 610, -1000, 628, -1000, -1000, 55, 3520, -1000, -1000, + -1000, -1000, -1000, 52, -1000, 48, 47, -1000, 1054, -1000, + -1000, 37, -1000, -1000, -1000, -1000, 120, -1000, 2826, 588, + 3520, 2484, 2004, 2004, 14, 790, -1000, -1000, 2826, -1000, + 682, 2659, -1000, 3520, -1000, 338, -1000, -1000, -1000, -1000, + 95, 43, -1000, 558, 495, 2826, 608, 493, 299, -1000, + -1000, 3608, 3520, -1000, -1000, -1000, 539, 537, 2004, 2004, + 491, -1000, 666, -1000, 777, 43, -1000, -1000, 486, 587, + 2826, 3520, 709, -1000, 2826, 651, 2484, 607, 624, 2484, + 2484, 536, 512, -1000, -1000, -1000, 834, 750, 749, 723, + -1000, 679, 484, -1000, 603, -1000, 622, -1000, -1000, 2484, + 586, 3520, 483, 478, 2484, 2484, 773, 744, -1000, 735, + 720, -1000, -1000, -1000, -1000, 677, 2826, -1000, 3520, 552, + 477, 2484, 601, 643, 640, 476, 475, 803, -1000, -1000, + -1000, -1000, -1000, 663, 474, 553, 2484, 3520, 708, -1000, + 2484, -1000, -1000, 639, 638, -1000, 737, -1000, -1000, 676, + 473, -1000, 600, -1000, 621, -1000, -1000, -1000, -1000, 675, + 2484, -1000, 3520, -1000, 662, -1000, } var yyPgo = [...]int{ - 0, 67, 69, 15, 87, 85, 18, 1361, 52, 22, - 44, 1360, 1359, 1358, 1357, 192, 125, 1355, 1354, 1351, - 1350, 1349, 1348, 1346, 58, 27, 32, 1343, 1342, 1340, - 51, 1332, 33, 1331, 1330, 31, 35, 1329, 1326, 1325, - 1324, 1317, 869, 1313, 75, 91, 1692, 522, 66, 40, - 57, 50, 21, 20, 28, 1310, 1309, 41, 1306, 37, - 465, 1301, 76, 1300, 73, 72, 729, 1444, 517, 56, - 30, 7, 10, 1296, 1294, 1293, 0, 1292, 71, 1283, - 1282, 1280, 83, 1279, 1278, 1277, 1274, 23, 48, 17, - 1273, 1271, 6, 1269, 1268, 63, 1267, 1266, 1265, 1264, - 81, 62, 70, 1263, 47, 34, 61, 1260, 38, 1259, - 1258, 3, 46, 1257, 19, 24, 42, 68, 25, 59, - 1256, 1253, 1252, 36, 1250, 1249, 26, 55, 13, 14, - 5, 9, 4, 2, 43, 1243, 16, 1241, 11, 1240, - 8, 1239, 1705, 142, 12, 387, 1237, 79, 1124, 1235, - 77, 82, 64, 65, 54, 60, 84, 1231, 39, 612, - 1229, + 0, 57, 51, 273, 21, 210, 9, 1283, 42, 17, + 36, 1279, 1278, 1276, 1274, 316, 74, 1270, 1268, 1267, + 1265, 1261, 1259, 1257, 65, 23, 28, 1256, 1254, 1253, + 49, 1251, 34, 1250, 1249, 24, 33, 1248, 1245, 1244, + 1243, 1240, 1252, 1239, 78, 88, 1463, 469, 50, 73, + 59, 40, 35, 20, 45, 1238, 1237, 44, 1236, 39, + 266, 1233, 79, 1232, 72, 71, 92, 1269, 609, 60, + 46, 13, 11, 1228, 1227, 1226, 0, 1224, 70, 1223, + 1221, 1220, 1354, 1218, 1208, 1207, 1204, 31, 100, 25, + 1203, 1201, 5, 1199, 1197, 52, 1195, 1194, 1193, 1185, + 84, 66, 77, 1180, 32, 41, 187, 1179, 19, 1177, + 1176, 8, 47, 1174, 54, 22, 48, 68, 16, 58, + 1170, 1168, 1165, 38, 1159, 1156, 26, 55, 10, 18, + 2, 12, 3, 6, 53, 1155, 14, 1146, 7, 1145, + 4, 1143, 1741, 27, 15, 135, 1142, 80, 1043, 1141, + 1138, 93, 83, 81, 69, 56, 67, 85, 1137, 30, + 563, 1134, } var yyR1 = [...]int{ @@ -1467,34 +1473,34 @@ var yyR1 = [...]int{ 60, 60, 61, 61, 62, 62, 63, 63, 63, 63, 63, 64, 65, 66, 66, 66, 66, 66, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, - 70, 70, 70, 71, 71, 72, 72, 73, 73, 74, - 74, 74, 75, 75, 76, 77, 78, 78, 78, 79, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 69, 70, 70, 70, 71, 71, 72, 72, 73, 73, + 74, 74, 74, 75, 75, 76, 77, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, - 80, 80, 80, 80, 80, 81, 81, 81, 81, 82, - 82, 83, 83, 83, 83, 83, 83, 83, 83, 84, - 84, 84, 84, 84, 84, 85, 85, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, - 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, - 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, - 96, 96, 96, 98, 98, 98, 97, 97, 97, 97, - 99, 99, 99, 99, 100, 100, 103, 103, 104, 104, - 104, 105, 105, 105, 105, 106, 106, 106, 106, 106, - 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 108, 108, 109, 109, 109, 109, 110, 111, - 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, - 116, 117, 117, 101, 101, 102, 102, 118, 118, 119, - 119, 120, 120, 120, 120, 121, 122, 123, 123, 124, - 124, 124, 124, 124, 124, 124, 124, 125, 125, 126, - 126, 127, 127, 128, 128, 129, 129, 130, 130, 131, - 131, 132, 132, 133, 133, 134, 134, 135, 135, 136, - 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, - 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 143, 144, 144, 145, 146, 146, 147, 147, 148, 149, - 150, 151, 151, 152, 152, 153, 153, 154, 154, 155, - 155, 155, 156, 156, 157, 157, 158, 158, 159, 159, - 160, 160, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 80, + 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, + 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, + 84, 84, 84, 84, 84, 84, 85, 85, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 87, 88, 88, 89, 89, 90, 90, 91, 91, 91, + 92, 92, 92, 93, 93, 94, 94, 95, 95, 96, + 96, 96, 96, 96, 98, 98, 98, 97, 97, 97, + 97, 99, 99, 99, 99, 100, 100, 103, 103, 104, + 104, 104, 105, 105, 105, 105, 106, 106, 106, 106, + 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 108, 108, 109, 109, 109, 109, 110, + 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, + 116, 116, 117, 117, 101, 101, 102, 102, 118, 118, + 119, 119, 120, 120, 120, 120, 121, 122, 123, 123, + 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, + 126, 126, 127, 127, 128, 128, 129, 129, 130, 130, + 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, + 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, + 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 143, 144, 144, 145, 146, 146, 147, 147, 148, + 149, 150, 151, 152, 152, 153, 153, 154, 154, 155, + 155, 156, 156, 156, 157, 157, 158, 158, 159, 159, + 160, 160, 161, 161, } var yyR2 = [...]int{ @@ -1523,282 +1529,282 @@ var yyR2 = [...]int{ 0, 2, 6, 9, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, - 3, 1, 6, 1, 3, 1, 3, 2, 4, 0, - 1, 1, 1, 1, 3, 3, 3, 1, 6, 3, - 3, 3, 3, 4, 4, 5, 6, 6, 3, 4, - 4, 3, 4, 4, 4, 4, 4, 2, 3, 3, - 3, 3, 3, 2, 2, 3, 3, 2, 2, 0, - 1, 4, 4, 6, 8, 3, 4, 4, 4, 5, - 5, 5, 5, 5, 1, 5, 10, 8, 9, 9, - 9, 9, 9, 9, 8, 8, 10, 8, 10, 2, - 1, 5, 0, 3, 2, 5, 2, 2, 2, 2, - 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 4, 6, 6, 8, - 6, 8, 6, 8, 1, 1, 1, 1, 1, 2, - 3, 1, 2, 3, 4, 1, 2, 3, 1, 1, - 1, 3, 4, 5, 6, 5, 6, 5, 6, 7, - 6, 7, 2, 4, 1, 3, 1, 3, 5, 0, - 1, 4, 5, 0, 2, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 6, 9, 5, 8, 7, 3, 1, 3, 10, - 13, 9, 12, 9, 12, 8, 11, 5, 6, 4, - 5, 0, 2, 4, 5, 0, 2, 4, 5, 0, - 2, 4, 5, 0, 2, 4, 5, 0, 2, 4, - 5, 0, 2, 4, 5, 0, 2, 4, 5, 0, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, - 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, - 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 1, 3, 1, 6, 1, 3, 1, 3, 2, 4, + 0, 1, 1, 1, 1, 3, 3, 3, 1, 6, + 3, 3, 3, 3, 4, 4, 5, 6, 6, 3, + 4, 4, 3, 4, 4, 4, 4, 4, 2, 3, + 3, 3, 3, 3, 2, 2, 3, 3, 2, 2, + 0, 1, 4, 4, 6, 8, 3, 4, 4, 4, + 5, 5, 5, 5, 5, 1, 5, 10, 8, 9, + 9, 9, 9, 9, 9, 8, 8, 10, 8, 10, + 2, 1, 5, 0, 3, 2, 5, 2, 2, 2, + 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 6, 6, + 8, 6, 8, 6, 8, 1, 1, 1, 1, 1, + 2, 3, 1, 2, 3, 4, 1, 2, 3, 1, + 1, 1, 3, 4, 5, 6, 5, 6, 5, 6, + 7, 6, 7, 2, 4, 1, 3, 1, 3, 5, + 0, 1, 4, 5, 0, 2, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 6, 9, 5, 8, 7, 3, 1, 3, + 10, 13, 9, 12, 9, 12, 8, 11, 5, 6, + 4, 5, 0, 2, 4, 5, 0, 2, 4, 5, + 0, 2, 4, 5, 0, 2, 4, 5, 0, 2, + 4, 5, 0, 2, 4, 5, 0, 2, 4, 5, + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 1, 3, 1, 3, 1, + 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, + 1, 1, 0, 3, } var yyChk = [...]int{ -1000, -1, -7, -5, -11, -42, -43, -120, -121, -124, -125, -23, -20, -21, -27, -28, -31, -37, -22, -40, - -41, -68, 15, 88, 87, -8, -10, -44, -60, -46, - 27, 32, 35, 133, 96, -145, 102, 20, 21, 100, - 101, 99, 103, 120, 111, 112, 33, 124, 134, 116, - 117, 118, 119, 125, 121, 122, 123, 126, -63, -80, + -41, -68, 15, 89, 88, -8, -10, -44, -60, -46, + 28, 33, 36, 134, 97, -145, 103, 21, 22, 101, + 102, 100, 104, 121, 112, 113, 34, 125, 135, 117, + 118, 119, 120, 126, 122, 123, 124, 127, -63, -80, -77, -76, -83, -84, -86, -110, -79, -81, -143, -148, - -149, -150, -39, 169, 16, 90, 115, -45, 80, 17, - 5, 6, 7, -64, -65, -67, 163, 164, -142, 148, - 150, 151, 149, -85, 152, 153, 154, 155, -70, 70, - 74, 168, 11, 13, 14, 12, 97, 9, 78, -66, - 4, 135, 136, 137, 139, 140, 141, 142, 143, 147, - 30, 161, -68, 169, -76, -145, 88, 27, 133, 87, - -111, -67, -68, -52, 45, -44, -46, 24, 19, 27, - 22, -76, 169, -47, -48, 25, 18, 169, 25, 36, - 36, -147, 169, -146, -143, -147, -142, -143, 97, 44, - 103, 127, -148, -150, -148, -142, -142, -38, 104, 105, - 37, 38, 106, 107, -142, -142, -68, -68, -68, -150, - -142, -68, -68, -68, -142, -68, -115, -67, -142, -68, - -142, -142, 158, -67, -68, -115, -42, -60, -46, -68, - -143, -144, -9, 133, 96, 6, 65, 66, 67, -62, - -61, -157, 31, -151, 79, 157, 156, 162, 77, 75, - 74, 71, 76, -159, 164, 163, 165, 166, 167, 73, - 72, -67, -67, 172, 169, 169, 169, 169, 169, 169, - 169, 169, 169, 156, 162, -152, -159, 74, -76, -67, - -67, -142, 169, 172, -1, 92, -115, -82, 169, -111, - -134, -112, 91, -53, -59, 51, 52, 48, -52, -47, - 25, -102, -100, -95, -97, -142, 30, -96, 139, 140, - 141, 142, 143, 25, 18, -101, -95, -48, -49, 23, - -144, -143, -117, -106, -103, -107, 29, -104, 169, -100, - -99, -76, -98, 144, 145, 146, -82, -115, -100, -160, - 88, -100, -151, 171, 158, 97, 44, 127, 128, -142, - -95, -142, -142, 162, 43, 162, 43, 62, -142, -68, - -68, 18, 62, 62, 43, 18, 18, 171, 62, 171, - -68, 6, -67, 170, 170, 170, 170, 94, 71, 171, - 71, -143, -144, -156, 68, -156, -156, 171, -142, -119, - -109, -67, -69, -142, 165, -67, -67, -67, -152, -67, - 75, 71, 76, -70, 169, -76, -67, 69, 68, -67, - -67, -67, -67, -67, -67, -67, -142, 6, -82, -151, - -82, -67, 170, -119, -151, -151, -151, -82, -82, -82, - -70, -70, 75, 71, 69, 68, 77, 149, -67, -142, - 6, -1, 170, 91, -135, 93, -113, 93, -67, -68, - 98, 99, -68, -68, -72, -73, -67, -53, -48, -100, - 20, 171, 169, -100, -117, 18, 171, -49, -50, 46, - -67, 60, -153, -155, 63, 171, 55, 57, 58, 59, - -142, 28, -106, -76, -142, 28, 169, 170, 62, 169, - -142, 74, 33, 34, 42, 20, -82, -147, -67, 98, - 169, 28, 169, 169, -68, -142, -68, -142, -142, -68, - -142, -68, -30, -29, -68, 25, 5, -30, -116, -68, - -150, -150, -100, -116, -116, -115, -68, -2, -12, -5, - -13, 88, 87, -8, -10, -6, 113, 114, -142, -144, - -142, 71, 71, -45, -44, -45, -45, -62, 28, 169, - 171, 28, 172, -64, -65, 72, -67, -70, -67, -70, - -70, 170, -82, 170, 18, 170, -82, -82, -69, -82, - 170, 170, 170, -70, -78, 169, -76, 147, -78, -78, - -152, 171, -127, -126, 93, 89, 95, -1, 95, -67, - 92, 92, 19, -55, 37, 104, -56, -57, 53, 86, - 137, -58, 86, 137, 171, -74, 49, 50, 98, -49, - 26, 169, -42, -123, -122, -66, -142, -102, -95, -68, - -142, 30, 62, 169, -49, -117, -101, -50, -51, 47, - 48, 54, 54, -154, 56, -153, -155, -105, -106, 64, - -104, -142, 170, -142, -68, 169, -114, -66, 169, -158, - 28, 70, -24, 169, -142, -66, 169, -66, -142, 170, - -42, -142, -118, -142, -42, 170, -36, -33, -35, -32, - -34, -143, -142, 171, 28, -144, 171, 95, 161, -68, - -111, 94, 94, -142, -142, 169, -118, -119, -142, -69, - -67, 72, 110, 170, -67, 170, 170, 170, 170, 110, - 110, 131, 110, 131, 72, -71, -70, -76, 169, 100, - 71, -67, 95, -127, -1, -68, 87, -67, -1, -68, - -54, 138, 80, -72, 136, 19, -50, -71, -114, -48, - 171, 162, 170, 171, 171, 169, -114, -49, -51, -67, - -115, -106, 64, -106, 64, 54, 54, -154, -104, 171, - 171, -114, 170, 171, -118, -42, -26, 37, 38, 39, - 40, -25, -24, 41, -114, 43, 43, 110, 170, 171, - 28, 170, 171, 171, 41, 170, 171, -30, -142, -116, - 90, -2, 92, -136, 91, -2, -2, 94, 94, -42, - 170, -67, 169, 110, 170, 98, 110, 110, 110, 132, - 110, 169, 169, 136, 169, 136, -70, 170, 171, -67, - 81, 170, 88, 95, 92, -112, -134, 91, -57, -59, - 135, -75, 37, 38, -51, 170, -49, -123, -67, -82, - -95, -114, 170, -52, -104, -108, 61, 62, -104, -106, - 64, -106, 64, 54, 171, -105, -142, -68, 170, 62, - -114, 170, -66, -66, 170, 171, -67, 170, -142, -142, - -68, 169, 28, -118, 129, 28, -32, -35, -35, -143, - -68, 28, -36, -2, -137, 93, -68, 95, 95, -2, - -2, 170, 28, -88, -87, -89, 109, 169, -67, 169, - 169, 169, 46, 169, -87, -89, -88, 110, -87, 110, - -71, 171, 88, -1, -54, -52, 26, -42, 170, 170, - 171, 170, 62, -53, -67, 169, -108, -108, -104, -104, - -106, 64, -105, 170, 171, 170, 171, 26, -42, 169, - -158, -26, -25, -88, -42, -3, -14, -5, -18, 88, - 87, -15, -16, 90, 130, 129, 129, 170, -129, -128, - 93, 89, 95, -2, 92, 90, 90, 95, 95, 169, - 170, -52, 45, 48, -88, 170, -88, -88, -88, 169, - -87, 170, 170, 169, 170, 169, -67, -126, -53, -71, - -82, 26, -42, 169, 98, -118, -108, -104, -82, -82, - -71, -114, -42, 170, 95, 161, -68, -111, -68, -143, - -144, -9, -68, -3, -3, 28, 95, -129, -2, -68, - 87, -2, 90, 90, -42, 48, -115, 170, 170, 170, - 170, -52, 170, -88, -87, 170, 98, 170, -71, -114, - 19, 170, 170, 170, 170, -3, 92, -138, 91, 94, - 71, 71, -143, -144, 95, 95, 129, 88, 95, 92, - -136, 91, 170, -72, 170, 170, 170, 19, 170, 26, - -42, -3, -139, 93, -68, -4, -17, -5, -19, 88, - 87, -15, -16, -6, -142, -142, 71, 71, -3, 88, - -2, -90, 137, 26, -42, -71, -131, -130, 93, 89, - 95, -3, 92, 95, 161, -68, -111, 94, 94, -142, - -142, 95, -128, -91, 75, 82, 6, 85, -71, 95, - -131, -3, -68, 87, -3, 90, -4, 92, -140, 91, - -4, -4, 94, 94, -93, 82, -92, 6, 85, 83, - 83, 86, 88, 95, 92, -138, 91, -4, -141, 93, - -68, 95, 95, -4, -4, 72, 83, 83, 84, 86, - 88, -3, -133, -132, 93, 89, 95, -4, 92, 90, - 90, 95, 95, -94, 82, -92, -130, 95, -133, -4, - -68, 87, -4, 90, 90, 84, 88, 95, 92, -140, - 91, 88, -4, -132, + -149, -150, -151, -39, 170, 16, 91, 116, -45, 81, + 18, 5, 6, 7, -64, -65, -67, 164, 165, -142, + 149, 151, 152, 150, -85, 153, 154, 155, 156, -70, + 71, 75, 169, 11, 13, 14, 17, 12, 98, 9, + 79, -66, 4, 136, 137, 138, 140, 141, 142, 143, + 144, 148, 31, 162, -68, 170, -76, -145, 89, 28, + 134, 88, -111, -67, -68, -52, 46, -44, -46, 25, + 20, 28, 23, -76, 170, -47, -48, 26, 19, 170, + 26, 37, 37, -147, 170, -146, -143, -147, -142, -143, + 98, 45, 104, 128, -148, -151, -148, -142, -142, -38, + 105, 106, 38, 39, 107, 108, -142, -142, -68, -68, + -68, -151, -142, -68, -68, -68, -142, -68, -115, -67, + -142, -68, -142, -142, 159, -67, -68, -115, -42, -60, + -46, -68, -143, -144, -9, 134, 97, 6, 66, 67, + 68, -62, -61, -158, 32, -152, 80, 158, 157, 163, + 78, 76, 75, 72, 77, -160, 165, 164, 166, 167, + 168, 74, 73, -67, -67, 173, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 157, 163, -153, -160, 75, + -76, -67, -67, -142, 170, 173, -1, 93, -115, -82, + 170, -111, -134, -112, 92, -53, -59, 52, 53, 49, + -52, -47, 26, -102, -100, -95, -97, -142, 31, -96, + 140, 141, 142, 143, 144, 26, 19, -101, -95, -48, + -49, 24, -144, -143, -117, -106, -103, -107, 30, -104, + 170, -100, -99, -76, -98, 145, 146, 147, -82, -115, + -100, -161, 89, -100, -152, 172, 159, 98, 45, 128, + 129, -142, -95, -142, -142, 163, 44, 163, 44, 63, + -142, -68, -68, 19, 63, 63, 44, 19, 19, 172, + 63, 172, -68, 6, -67, 171, 171, 171, 171, 95, + 72, 172, 72, -143, -144, -157, 69, -157, -157, 172, + -142, -119, -109, -67, -69, -142, 166, -67, -67, -67, + -153, -67, 76, 72, 77, -70, 170, -76, -67, 70, + 69, -67, -67, -67, -67, -67, -67, -67, -142, 6, + -82, -152, -82, -67, 171, -119, -152, -152, -152, -82, + -82, -82, -70, -70, 76, 72, 70, 69, 78, 150, + -67, -142, 6, -1, 171, 92, -135, 94, -113, 94, + -67, -68, 99, 100, -68, -68, -72, -73, -67, -53, + -48, -100, 21, 172, 170, -100, -117, 19, 172, -49, + -50, 47, -67, 61, -154, -156, 64, 172, 56, 58, + 59, 60, -142, 29, -106, -76, -142, 29, 170, 171, + 63, 170, -142, 75, 34, 35, 43, 21, -82, -147, + -67, 99, 170, 29, 170, 170, -68, -142, -68, -142, + -142, -68, -142, -68, -30, -29, -68, 26, 5, -30, + -116, -68, -151, -151, -100, -116, -116, -115, -68, -2, + -12, -5, -13, 89, 88, -8, -10, -6, 114, 115, + -142, -144, -142, 72, 72, -45, -44, -45, -45, -62, + 29, 170, 172, 29, 173, -64, -65, 73, -67, -70, + -67, -70, -70, 171, -82, 171, 19, 171, -82, -82, + -69, -82, 171, 171, 171, -70, -78, 170, -76, 148, + -78, -78, -153, 172, -127, -126, 94, 90, 96, -1, + 96, -67, 93, 93, 20, -55, 38, 105, -56, -57, + 54, 87, 138, -58, 87, 138, 172, -74, 50, 51, + 99, -49, 27, 170, -42, -123, -122, -66, -142, -102, + -95, -68, -142, 31, 63, 170, -49, -117, -101, -50, + -51, 48, 49, 55, 55, -155, 57, -154, -156, -105, + -106, 65, -104, -142, 171, -142, -68, 170, -114, -66, + 170, -159, 29, 71, -24, 170, -142, -66, 170, -66, + -142, 171, -42, -142, -118, -142, -42, 171, -36, -33, + -35, -32, -34, -143, -142, 172, 29, -144, 172, 96, + 162, -68, -111, 95, 95, -142, -142, 170, -118, -119, + -142, -69, -67, 73, 111, 171, -67, 171, 171, 171, + 171, 111, 111, 132, 111, 132, 73, -71, -70, -76, + 170, 101, 72, -67, 96, -127, -1, -68, 88, -67, + -1, -68, -54, 139, 81, -72, 137, 20, -50, -71, + -114, -48, 172, 163, 171, 172, 172, 170, -114, -49, + -51, -67, -115, -106, 65, -106, 65, 55, 55, -155, + -104, 172, 172, -114, 171, 172, -118, -42, -26, 38, + 39, 40, 41, -25, -24, 42, -114, 44, 44, 111, + 171, 172, 29, 171, 172, 172, 42, 171, 172, -30, + -142, -116, 91, -2, 93, -136, 92, -2, -2, 95, + 95, -42, 171, -67, 170, 111, 171, 99, 111, 111, + 111, 133, 111, 170, 170, 137, 170, 137, -70, 171, + 172, -67, 82, 171, 89, 96, 93, -112, -134, 92, + -57, -59, 136, -75, 38, 39, -51, 171, -49, -123, + -67, -82, -95, -114, 171, -52, -104, -108, 62, 63, + -104, -106, 65, -106, 65, 55, 172, -105, -142, -68, + 171, 63, -114, 171, -66, -66, 171, 172, -67, 171, + -142, -142, -68, 170, 29, -118, 130, 29, -32, -35, + -35, -143, -68, 29, -36, -2, -137, 94, -68, 96, + 96, -2, -2, 171, 29, -88, -87, -89, 110, 170, + -67, 170, 170, 170, 47, 170, -87, -89, -88, 111, + -87, 111, -71, 172, 89, -1, -54, -52, 27, -42, + 171, 171, 172, 171, 63, -53, -67, 170, -108, -108, + -104, -104, -106, 65, -105, 171, 172, 171, 172, 27, + -42, 170, -159, -26, -25, -88, -42, -3, -14, -5, + -18, 89, 88, -15, -16, 91, 131, 130, 130, 171, + -129, -128, 94, 90, 96, -2, 93, 91, 91, 96, + 96, 170, 171, -52, 46, 49, -88, 171, -88, -88, + -88, 170, -87, 171, 171, 170, 171, 170, -67, -126, + -53, -71, -82, 27, -42, 170, 99, -118, -108, -104, + -82, -82, -71, -114, -42, 171, 96, 162, -68, -111, + -68, -143, -144, -9, -68, -3, -3, 29, 96, -129, + -2, -68, 88, -2, 91, 91, -42, 49, -115, 171, + 171, 171, 171, -52, 171, -88, -87, 171, 99, 171, + -71, -114, 20, 171, 171, 171, 171, -3, 93, -138, + 92, 95, 72, 72, -143, -144, 96, 96, 130, 89, + 96, 93, -136, 92, 171, -72, 171, 171, 171, 20, + 171, 27, -42, -3, -139, 94, -68, -4, -17, -5, + -19, 89, 88, -15, -16, -6, -142, -142, 72, 72, + -3, 89, -2, -90, 138, 27, -42, -71, -131, -130, + 94, 90, 96, -3, 93, 96, 162, -68, -111, 95, + 95, -142, -142, 96, -128, -91, 76, 83, 6, 86, + -71, 96, -131, -3, -68, 88, -3, 91, -4, 93, + -140, 92, -4, -4, 95, 95, -93, 83, -92, 6, + 86, 84, 84, 87, 89, 96, 93, -138, 92, -4, + -141, 94, -68, 96, 96, -4, -4, 73, 84, 84, + 85, 87, 89, -3, -133, -132, 94, 90, 96, -4, + 93, 91, 91, 96, 96, -94, 83, -92, -130, 96, + -133, -4, -68, 88, -4, 91, 91, 85, 89, 96, + 93, -140, 92, 89, -4, -132, } var yyDef = [...]int{ -2, -2, 2, 30, 31, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, -2, 27, 0, 409, 46, 47, -2, 0, 192, + 25, -2, 27, 0, 410, 46, 47, -2, 0, 192, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 139, 0, 0, 85, 86, 0, 0, 0, 0, 0, 0, 0, 165, 0, 171, 0, 0, 241, 242, 243, -2, 245, 246, 247, 248, 249, 250, 251, 253, - 254, 255, 256, 0, 258, 0, 39, 0, 514, 501, - 226, 227, 228, 229, 230, 0, 0, 0, 233, 0, - 0, 0, 0, 324, 0, 0, 0, 0, 503, 0, - 0, 0, 490, 498, 499, 500, 0, 231, 232, 238, - 481, 482, 483, 484, 485, 486, 487, 488, 489, 0, - 0, -2, 239, 309, 244, 252, 0, 0, 0, 409, - 0, 410, 239, 218, 0, -2, 192, 0, 0, 0, - 0, 189, 0, 192, 194, 0, 0, 309, 0, 520, - 0, 76, 501, 496, 494, 77, 0, 79, 0, 0, - 0, 0, 0, 0, 84, 108, 110, 0, 140, 141, - 142, 143, 0, 0, 0, -2, -2, 239, 239, 155, - 167, -2, -2, -2, -2, -2, 166, 417, -2, -2, - 172, 173, 0, 0, 239, 0, 0, 0, 192, 239, - 251, 0, 0, 37, 38, 40, 512, 512, 512, 221, - 224, 0, 515, 0, 502, 0, 518, 519, 503, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 303, 304, 0, 309, 309, 0, 501, 501, 501, - 309, 309, 309, 518, 519, 0, 0, 504, 297, 307, - 308, 0, 0, 0, 3, -2, 0, 0, 309, 0, - 467, 413, 0, 176, 202, 0, 0, 0, 218, 192, - 0, 0, 425, 374, 375, 356, 357, 0, -2, -2, - -2, -2, -2, 0, 0, 0, 423, 194, 196, 0, - 191, 491, 193, -2, 385, 388, 389, 390, 0, 376, - 377, 378, 0, 363, 364, 365, 0, 310, 0, 0, - 0, 0, 309, 0, 0, 0, 0, 0, 0, 111, - 116, 124, 138, 0, 0, 0, 0, 0, 0, -2, - -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -2, 227, 493, 240, 257, 260, 274, -2, 0, 0, - 0, 0, 0, 0, 513, 0, 0, 514, 0, 190, - 429, 404, 406, 233, 259, 275, -2, -2, 0, 0, - 0, 0, 0, 288, 0, 261, -2, 0, 0, 298, - 299, 300, 301, 302, 305, 306, 234, 236, 0, 309, - 0, 417, 315, 0, 309, 309, 309, 0, 0, 0, - 280, 282, 0, 0, 0, 0, 503, 148, 0, 235, - 237, 451, 317, 0, 0, -2, 0, 0, 0, 239, - 0, 0, -2, -2, 201, 265, 269, 178, 194, 0, - 0, 0, 0, 0, 194, 0, 0, 196, 198, 0, - 195, 0, 0, 507, 505, 0, 506, 509, 510, 511, - 386, 0, 505, -2, 379, 0, 0, 318, 0, 0, - 516, 0, 0, 0, 0, 0, 0, 497, 495, 0, - 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, - -2, -2, 109, 119, -2, 0, 121, 123, 164, -2, - 153, 154, 168, 159, 160, 418, -2, 0, 0, 41, - 42, 0, 409, 51, 52, 53, 28, 29, 0, 492, - 0, 0, 0, 185, 188, 186, 187, 225, 0, 0, - 0, 0, 0, 283, 284, 0, 0, 289, -2, 293, - 295, 311, 0, 312, 0, 316, 0, 0, 0, 0, - 0, 0, 0, 0, 290, 0, 277, 0, 294, 296, - 0, 0, 0, 451, -2, 0, 0, 468, 408, 414, - 0, -2, 177, 0, 208, 209, 205, 211, 212, 213, - 214, 219, 216, 217, 0, 267, 270, 271, 0, 196, - 0, 0, 433, 192, 437, 0, 233, 426, 0, 239, - -2, 357, 0, 0, 447, 194, 424, 198, 184, 0, - 0, 0, 0, 0, 508, 0, 507, 422, -2, 0, - 390, 387, 391, 380, 239, 0, 0, 415, 0, 0, - 517, 521, 101, 0, 97, 92, 0, 0, 0, 321, - 106, 107, 0, 427, 115, 0, 0, 131, 132, 126, - 129, 125, 0, 0, 0, 112, 0, 0, -2, 239, - 0, -2, -2, 0, 0, 0, 0, 430, 405, 407, - 285, 0, 0, 319, 0, 320, 322, 323, 325, 0, - 0, 0, 0, 0, 0, 0, 263, -2, 0, 146, - 0, 0, 0, 0, 452, 239, 45, 411, 465, 239, - 218, 206, 0, 266, 0, 179, 198, 431, 0, 194, - 0, 0, 366, 309, 0, 0, 0, 448, 200, 199, - 197, 392, 0, 505, 0, 0, 0, 0, 382, 0, - 0, 0, 0, 0, 0, 89, 90, 102, 103, 0, - 0, 0, 99, 0, 0, 0, 0, 0, 113, 0, - 0, 0, 0, 0, 0, 0, 0, 120, 118, 420, - 32, 5, -2, 471, 0, 0, 0, -2, -2, 0, - 0, 286, 342, 0, 313, 0, 0, 0, 0, 0, - 0, 342, 342, 0, 342, 0, 287, 276, 0, 0, - 147, 262, 43, 0, -2, 412, 466, 0, 205, 204, - 207, 268, 272, 273, 200, 0, 435, 438, 436, 0, - 0, 0, 0, 218, 397, 393, 0, 0, 0, 505, - 0, 395, 0, 0, 0, 383, 233, 239, 0, 0, - 416, -2, 104, 105, 101, 0, 98, 93, 94, -2, - -2, 342, 0, 428, -2, 0, 127, 133, 130, 0, - -2, 0, 0, 455, 0, -2, 239, 0, 0, 0, - 0, 222, 0, 0, 340, 200, 0, 342, 0, 342, - 342, 342, 0, 342, 0, 200, 0, 0, 0, 0, - 264, 0, 44, 449, 203, 218, 0, 434, 367, 368, - 309, 0, 0, 180, 402, 0, 398, 394, 0, 400, - 396, 0, 384, 370, 309, 372, 309, 0, 445, 0, - 0, 91, 100, 0, 114, 0, 0, 54, 55, 0, - 409, 68, 69, 0, 61, -2, -2, 0, 0, 455, - -2, 0, 0, 472, -2, 33, 34, 0, 0, 0, - 327, 339, 0, 0, 0, 314, 0, 0, 0, 200, - 0, 334, 335, 342, 337, 342, 0, 450, 182, 432, - 0, 0, 441, 0, 0, 0, 399, 401, 0, 0, - 443, 0, 88, 330, 134, -2, 239, 0, 239, 251, - 0, 0, -2, 0, 0, 0, 0, 0, 456, 239, - 50, 469, 35, 36, 0, 0, 343, 328, 329, 331, - 332, 0, 333, 0, 0, 278, 0, 369, 439, 0, - 181, 403, 371, 373, 0, 7, -2, 475, 0, -2, - 0, 0, 0, 0, 135, 136, -2, 48, 0, -2, - 470, 0, 223, 201, 326, 336, 338, 183, 0, 0, - 446, 459, 0, -2, 239, 0, 0, 63, 64, 0, - 409, 73, 74, 75, 0, 0, 0, 0, 0, 49, - 453, 341, 0, 0, 442, 444, 0, 459, -2, 0, - 0, 476, -2, 0, -2, 239, 0, -2, -2, 0, - 0, 137, 454, 344, 0, 0, 0, 0, 440, 0, - 0, 460, 239, 67, 473, 56, 9, -2, 479, 0, - 0, 0, -2, -2, 0, 0, 353, 0, 0, 346, - 347, 348, 65, 0, -2, 474, 0, 463, 0, -2, - 239, 0, 0, 0, 0, 0, 352, 349, 350, 351, - 66, 457, 0, 463, -2, 0, 0, 480, -2, 57, - 58, 0, 0, 345, 0, 355, 458, 0, 0, 464, - 239, 72, 477, 59, 60, 354, 70, 0, -2, 478, - 0, 71, 461, 462, + 254, 255, 256, 257, 0, 259, 0, 39, 0, 516, + 503, 226, 227, 228, 229, 230, 0, 0, 0, 233, + 0, 0, 0, 0, 325, 0, 0, 0, 0, 505, + 0, 0, 0, 491, 499, 500, 501, 502, 0, 231, + 232, 238, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 0, 0, -2, 239, 310, 244, 252, 0, 0, + 0, 410, 0, 411, 239, 218, 0, -2, 192, 0, + 0, 0, 0, 189, 0, 192, 194, 0, 0, 310, + 0, 522, 0, 76, 503, 497, 495, 77, 0, 79, + 0, 0, 0, 0, 0, 0, 84, 108, 110, 0, + 140, 141, 142, 143, 0, 0, 0, -2, -2, 239, + 239, 155, 167, -2, -2, -2, -2, -2, 166, 418, + -2, -2, 172, 173, 0, 0, 239, 0, 0, 0, + 192, 239, 251, 0, 0, 37, 38, 40, 514, 514, + 514, 221, 224, 0, 517, 0, 504, 0, 520, 521, + 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 304, 305, 0, 310, 310, 0, 503, + 503, 503, 310, 310, 310, 520, 521, 0, 0, 506, + 298, 308, 309, 0, 0, 0, 3, -2, 0, 0, + 310, 0, 468, 414, 0, 176, 202, 0, 0, 0, + 218, 192, 0, 0, 426, 375, 376, 357, 358, 0, + -2, -2, -2, -2, -2, 0, 0, 0, 424, 194, + 196, 0, 191, 492, 193, -2, 386, 389, 390, 391, + 0, 377, 378, 379, 0, 364, 365, 366, 0, 311, + 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, + 0, 111, 116, 124, 138, 0, 0, 0, 0, 0, + 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -2, 227, 494, 240, 258, 261, 275, -2, + 0, 0, 0, 0, 0, 0, 515, 0, 0, 516, + 0, 190, 430, 405, 407, 233, 260, 276, -2, -2, + 0, 0, 0, 0, 0, 289, 0, 262, -2, 0, + 0, 299, 300, 301, 302, 303, 306, 307, 234, 236, + 0, 310, 0, 418, 316, 0, 310, 310, 310, 0, + 0, 0, 281, 283, 0, 0, 0, 0, 505, 148, + 0, 235, 237, 452, 318, 0, 0, -2, 0, 0, + 0, 239, 0, 0, -2, -2, 201, 266, 270, 178, + 194, 0, 0, 0, 0, 0, 194, 0, 0, 196, + 198, 0, 195, 0, 0, 509, 507, 0, 508, 511, + 512, 513, 387, 0, 507, -2, 380, 0, 0, 319, + 0, 0, 518, 0, 0, 0, 0, 0, 0, 498, + 496, 0, 0, 0, 0, 0, -2, -2, -2, -2, + -2, -2, -2, -2, 109, 119, -2, 0, 121, 123, + 164, -2, 153, 154, 168, 159, 160, 419, -2, 0, + 0, 41, 42, 0, 410, 51, 52, 53, 28, 29, + 0, 493, 0, 0, 0, 185, 188, 186, 187, 225, + 0, 0, 0, 0, 0, 284, 285, 0, 0, 290, + -2, 294, 296, 312, 0, 313, 0, 317, 0, 0, + 0, 0, 0, 0, 0, 0, 291, 0, 278, 0, + 295, 297, 0, 0, 0, 452, -2, 0, 0, 469, + 409, 415, 0, -2, 177, 0, 208, 209, 205, 211, + 212, 213, 214, 219, 216, 217, 0, 268, 271, 272, + 0, 196, 0, 0, 434, 192, 438, 0, 233, 427, + 0, 239, -2, 358, 0, 0, 448, 194, 425, 198, + 184, 0, 0, 0, 0, 0, 510, 0, 509, 423, + -2, 0, 391, 388, 392, 381, 239, 0, 0, 416, + 0, 0, 519, 523, 101, 0, 97, 92, 0, 0, + 0, 322, 106, 107, 0, 428, 115, 0, 0, 131, + 132, 126, 129, 125, 0, 0, 0, 112, 0, 0, + -2, 239, 0, -2, -2, 0, 0, 0, 0, 431, + 406, 408, 286, 0, 0, 320, 0, 321, 323, 324, + 326, 0, 0, 0, 0, 0, 0, 0, 264, -2, + 0, 146, 0, 0, 0, 0, 453, 239, 45, 412, + 466, 239, 218, 206, 0, 267, 0, 179, 198, 432, + 0, 194, 0, 0, 367, 310, 0, 0, 0, 449, + 200, 199, 197, 393, 0, 507, 0, 0, 0, 0, + 383, 0, 0, 0, 0, 0, 0, 89, 90, 102, + 103, 0, 0, 0, 99, 0, 0, 0, 0, 0, + 113, 0, 0, 0, 0, 0, 0, 0, 0, 120, + 118, 421, 32, 5, -2, 472, 0, 0, 0, -2, + -2, 0, 0, 287, 343, 0, 314, 0, 0, 0, + 0, 0, 0, 343, 343, 0, 343, 0, 288, 277, + 0, 0, 147, 263, 43, 0, -2, 413, 467, 0, + 205, 204, 207, 269, 273, 274, 200, 0, 436, 439, + 437, 0, 0, 0, 0, 218, 398, 394, 0, 0, + 0, 507, 0, 396, 0, 0, 0, 384, 233, 239, + 0, 0, 417, -2, 104, 105, 101, 0, 98, 93, + 94, -2, -2, 343, 0, 429, -2, 0, 127, 133, + 130, 0, -2, 0, 0, 456, 0, -2, 239, 0, + 0, 0, 0, 222, 0, 0, 341, 200, 0, 343, + 0, 343, 343, 343, 0, 343, 0, 200, 0, 0, + 0, 0, 265, 0, 44, 450, 203, 218, 0, 435, + 368, 369, 310, 0, 0, 180, 403, 0, 399, 395, + 0, 401, 397, 0, 385, 371, 310, 373, 310, 0, + 446, 0, 0, 91, 100, 0, 114, 0, 0, 54, + 55, 0, 410, 68, 69, 0, 61, -2, -2, 0, + 0, 456, -2, 0, 0, 473, -2, 33, 34, 0, + 0, 0, 328, 340, 0, 0, 0, 315, 0, 0, + 0, 200, 0, 335, 336, 343, 338, 343, 0, 451, + 182, 433, 0, 0, 442, 0, 0, 0, 400, 402, + 0, 0, 444, 0, 88, 331, 134, -2, 239, 0, + 239, 251, 0, 0, -2, 0, 0, 0, 0, 0, + 457, 239, 50, 470, 35, 36, 0, 0, 344, 329, + 330, 332, 333, 0, 334, 0, 0, 279, 0, 370, + 440, 0, 181, 404, 372, 374, 0, 7, -2, 476, + 0, -2, 0, 0, 0, 0, 135, 136, -2, 48, + 0, -2, 471, 0, 223, 201, 327, 337, 339, 183, + 0, 0, 447, 460, 0, -2, 239, 0, 0, 63, + 64, 0, 410, 73, 74, 75, 0, 0, 0, 0, + 0, 49, 454, 342, 0, 0, 443, 445, 0, 460, + -2, 0, 0, 477, -2, 0, -2, 239, 0, -2, + -2, 0, 0, 137, 455, 345, 0, 0, 0, 0, + 441, 0, 0, 461, 239, 67, 474, 56, 9, -2, + 480, 0, 0, 0, -2, -2, 0, 0, 354, 0, + 0, 347, 348, 349, 65, 0, -2, 475, 0, 464, + 0, -2, 239, 0, 0, 0, 0, 0, 353, 350, + 351, 352, 66, 458, 0, 464, -2, 0, 0, 481, + -2, 57, 58, 0, 0, 346, 0, 356, 459, 0, + 0, 465, 239, 72, 478, 59, 60, 355, 70, 0, + -2, 479, 0, 71, 462, 463, } var yyTok1 = [...]int{ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 168, 3, 3, 3, 167, 3, 3, - 169, 170, 165, 164, 171, 163, 172, 166, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 161, - 3, 162, + 3, 3, 3, 169, 3, 3, 3, 168, 3, 3, + 170, 171, 166, 165, 172, 164, 173, 167, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 162, + 3, 163, } var yyTok2 = [...]int{ @@ -1817,7 +1823,7 @@ var yyTok2 = [...]int{ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, } var yyTok3 = [...]int{ @@ -2163,1060 +2169,1060 @@ yydefault: case 1: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:251 +//line lib/parser/parser.y:253 { yyVAL.program = nil yylex.(*Lexer).program = yyVAL.program } case 2: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:256 +//line lib/parser/parser.y:258 { yyVAL.program = []Statement{yyDollar[1].statement} yylex.(*Lexer).program = yyVAL.program } case 3: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:261 +//line lib/parser/parser.y:263 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[3].program...) yylex.(*Lexer).program = yyVAL.program } case 4: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:268 +//line lib/parser/parser.y:270 { yyVAL.program = nil } case 5: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:272 +//line lib/parser/parser.y:274 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[3].program...) } case 6: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:278 +//line lib/parser/parser.y:280 { yyVAL.program = nil } case 7: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:282 +//line lib/parser/parser.y:284 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[3].program...) } case 8: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:288 +//line lib/parser/parser.y:290 { yyVAL.program = nil } case 9: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:292 +//line lib/parser/parser.y:294 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[3].program...) } case 10: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:298 +//line lib/parser/parser.y:300 { yyVAL.statement = yyDollar[1].queryexpr } case 11: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:302 +//line lib/parser/parser.y:304 { yyVAL.statement = yyDollar[1].queryexpr } case 12: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:306 +//line lib/parser/parser.y:308 { yyVAL.statement = yyDollar[1].expression } case 13: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:310 +//line lib/parser/parser.y:312 { yyVAL.statement = yyDollar[1].expression } case 14: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:314 +//line lib/parser/parser.y:316 { yyVAL.statement = yyDollar[1].expression } case 15: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:318 +//line lib/parser/parser.y:320 { yyVAL.statement = yyDollar[1].expression } case 16: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:322 +//line lib/parser/parser.y:324 { yyVAL.statement = yyDollar[1].statement } case 17: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:326 +//line lib/parser/parser.y:328 { yyVAL.statement = yyDollar[1].statement } case 18: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:330 +//line lib/parser/parser.y:332 { yyVAL.statement = yyDollar[1].statement } case 19: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:334 +//line lib/parser/parser.y:336 { yyVAL.statement = yyDollar[1].statement } case 20: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:338 +//line lib/parser/parser.y:340 { yyVAL.statement = yyDollar[1].statement } case 21: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:342 +//line lib/parser/parser.y:344 { yyVAL.statement = yyDollar[1].statement } case 22: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:346 +//line lib/parser/parser.y:348 { yyVAL.statement = yyDollar[1].statement } case 23: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:350 +//line lib/parser/parser.y:352 { yyVAL.statement = yyDollar[1].statement } case 24: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:354 +//line lib/parser/parser.y:356 { yyVAL.statement = yyDollar[1].statement } case 25: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:358 +//line lib/parser/parser.y:360 { yyVAL.statement = yyDollar[1].statement } case 26: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:362 +//line lib/parser/parser.y:364 { yyVAL.statement = yyDollar[1].queryexpr } case 27: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:366 +//line lib/parser/parser.y:368 { yyVAL.statement = ExternalCommand{BaseExpr: NewBaseExpr(yyDollar[1].token), Command: yyDollar[1].token.Literal} } case 28: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:372 +//line lib/parser/parser.y:374 { yyVAL.statement = FlowControl{Token: yyDollar[1].token.Token} } case 29: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:376 +//line lib/parser/parser.y:378 { yyVAL.statement = FlowControl{Token: yyDollar[1].token.Token} } case 30: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:382 +//line lib/parser/parser.y:384 { yyVAL.statement = yyDollar[1].statement } case 31: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:386 +//line lib/parser/parser.y:388 { yyVAL.statement = yyDollar[1].statement } case 32: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:392 +//line lib/parser/parser.y:394 { yyVAL.statement = While{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program} } case 33: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:396 +//line lib/parser/parser.y:398 { yyVAL.statement = WhileInCursor{Variables: []Variable{yyDollar[2].variable}, Cursor: yyDollar[4].identifier, Statements: yyDollar[6].program} } case 34: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:400 +//line lib/parser/parser.y:402 { yyVAL.statement = WhileInCursor{Variables: yyDollar[2].variables, Cursor: yyDollar[4].identifier, Statements: yyDollar[6].program} } case 35: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:404 +//line lib/parser/parser.y:406 { yyVAL.statement = WhileInCursor{WithDeclaration: true, Variables: []Variable{yyDollar[3].variable}, Cursor: yyDollar[5].identifier, Statements: yyDollar[7].program} } case 36: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:408 +//line lib/parser/parser.y:410 { yyVAL.statement = WhileInCursor{WithDeclaration: true, Variables: yyDollar[3].variables, Cursor: yyDollar[5].identifier, Statements: yyDollar[7].program} } case 37: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:414 +//line lib/parser/parser.y:416 { yyVAL.token = yyDollar[1].token } case 38: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:418 +//line lib/parser/parser.y:420 { yyVAL.token = yyDollar[1].token } case 39: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:424 +//line lib/parser/parser.y:426 { yyVAL.statement = Exit{} } case 40: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:428 +//line lib/parser/parser.y:430 { yyVAL.statement = Exit{Code: value.NewIntegerFromString(yyDollar[2].token.Literal)} } case 41: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:434 +//line lib/parser/parser.y:436 { yyVAL.statement = yyDollar[1].statement } case 42: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:438 +//line lib/parser/parser.y:440 { yyVAL.statement = yyDollar[1].statement } case 43: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:444 +//line lib/parser/parser.y:446 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, Else: yyDollar[5].elseexpr} } case 44: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:448 +//line lib/parser/parser.y:450 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, ElseIf: yyDollar[5].elseif, Else: yyDollar[6].elseexpr} } case 45: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:452 +//line lib/parser/parser.y:454 { yyVAL.statement = Case{Value: yyDollar[2].queryexpr, When: yyDollar[3].casewhen, Else: yyDollar[4].caseelse} } case 46: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:456 +//line lib/parser/parser.y:458 { yyVAL.statement = yyDollar[1].statement } case 47: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:460 +//line lib/parser/parser.y:462 { yyVAL.statement = yyDollar[1].statement } case 48: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:466 +//line lib/parser/parser.y:468 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, Else: yyDollar[5].elseexpr} } case 49: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:470 +//line lib/parser/parser.y:472 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, ElseIf: yyDollar[5].elseif, Else: yyDollar[6].elseexpr} } case 50: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:474 +//line lib/parser/parser.y:476 { yyVAL.statement = Case{Value: yyDollar[2].queryexpr, When: yyDollar[3].casewhen, Else: yyDollar[4].caseelse} } case 51: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:478 +//line lib/parser/parser.y:480 { yyVAL.statement = yyDollar[1].statement } case 52: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:482 +//line lib/parser/parser.y:484 { yyVAL.statement = yyDollar[1].statement } case 53: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:486 +//line lib/parser/parser.y:488 { yyVAL.statement = yyDollar[1].statement } case 54: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:492 +//line lib/parser/parser.y:494 { yyVAL.statement = yyDollar[1].statement } case 55: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:496 +//line lib/parser/parser.y:498 { yyVAL.statement = yyDollar[1].statement } case 56: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:502 +//line lib/parser/parser.y:504 { yyVAL.statement = While{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program} } case 57: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:506 +//line lib/parser/parser.y:508 { yyVAL.statement = WhileInCursor{Variables: []Variable{yyDollar[2].variable}, Cursor: yyDollar[4].identifier, Statements: yyDollar[6].program} } case 58: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:510 +//line lib/parser/parser.y:512 { yyVAL.statement = WhileInCursor{Variables: yyDollar[2].variables, Cursor: yyDollar[4].identifier, Statements: yyDollar[6].program} } case 59: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:514 +//line lib/parser/parser.y:516 { yyVAL.statement = WhileInCursor{WithDeclaration: true, Variables: []Variable{yyDollar[3].variable}, Cursor: yyDollar[5].identifier, Statements: yyDollar[7].program} } case 60: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:518 +//line lib/parser/parser.y:520 { yyVAL.statement = WhileInCursor{WithDeclaration: true, Variables: yyDollar[3].variables, Cursor: yyDollar[5].identifier, Statements: yyDollar[7].program} } case 61: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:524 +//line lib/parser/parser.y:526 { yyVAL.statement = Return{Value: NewNullValue()} } case 62: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:528 +//line lib/parser/parser.y:530 { yyVAL.statement = Return{Value: yyDollar[2].queryexpr} } case 63: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:534 +//line lib/parser/parser.y:536 { yyVAL.statement = yyDollar[1].statement } case 64: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:538 +//line lib/parser/parser.y:540 { yyVAL.statement = yyDollar[1].statement } case 65: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:544 +//line lib/parser/parser.y:546 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, Else: yyDollar[5].elseexpr} } case 66: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:548 +//line lib/parser/parser.y:550 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, ElseIf: yyDollar[5].elseif, Else: yyDollar[6].elseexpr} } case 67: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:552 +//line lib/parser/parser.y:554 { yyVAL.statement = Case{Value: yyDollar[2].queryexpr, When: yyDollar[3].casewhen, Else: yyDollar[4].caseelse} } case 68: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:556 +//line lib/parser/parser.y:558 { yyVAL.statement = yyDollar[1].statement } case 69: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:560 +//line lib/parser/parser.y:562 { yyVAL.statement = yyDollar[1].statement } case 70: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:566 +//line lib/parser/parser.y:568 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, Else: yyDollar[5].elseexpr} } case 71: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:570 +//line lib/parser/parser.y:572 { yyVAL.statement = If{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program, ElseIf: yyDollar[5].elseif, Else: yyDollar[6].elseexpr} } case 72: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:574 +//line lib/parser/parser.y:576 { yyVAL.statement = Case{Value: yyDollar[2].queryexpr, When: yyDollar[3].casewhen, Else: yyDollar[4].caseelse} } case 73: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:578 +//line lib/parser/parser.y:580 { yyVAL.statement = yyDollar[1].statement } case 74: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:582 +//line lib/parser/parser.y:584 { yyVAL.statement = yyDollar[1].statement } case 75: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:586 +//line lib/parser/parser.y:588 { yyVAL.statement = yyDollar[1].statement } case 76: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:592 +//line lib/parser/parser.y:594 { yyVAL.statement = VariableDeclaration{Assignments: yyDollar[2].varassigns} } case 77: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:596 +//line lib/parser/parser.y:598 { yyVAL.statement = VariableDeclaration{Assignments: yyDollar[2].varassigns} } case 78: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:600 +//line lib/parser/parser.y:602 { yyVAL.statement = yyDollar[1].queryexpr } case 79: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:604 +//line lib/parser/parser.y:606 { yyVAL.statement = DisposeVariable{Variable: yyDollar[2].variable} } case 80: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:610 +//line lib/parser/parser.y:612 { yyVAL.statement = SetEnvVar{EnvVar: yyDollar[2].envvar, Value: yyDollar[4].queryexpr} } case 81: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:614 +//line lib/parser/parser.y:616 { yyVAL.statement = SetEnvVar{EnvVar: yyDollar[2].envvar, Value: yyDollar[4].identifier} } case 82: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:618 +//line lib/parser/parser.y:620 { yyVAL.statement = SetEnvVar{EnvVar: yyDollar[2].envvar, Value: yyDollar[4].queryexpr} } case 83: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:622 +//line lib/parser/parser.y:624 { yyVAL.statement = SetEnvVar{EnvVar: yyDollar[2].envvar, Value: yyDollar[4].identifier} } case 84: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:626 +//line lib/parser/parser.y:628 { yyVAL.statement = UnsetEnvVar{EnvVar: yyDollar[2].envvar} } case 85: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:632 +//line lib/parser/parser.y:634 { yyVAL.statement = TransactionControl{BaseExpr: NewBaseExpr(yyDollar[1].token), Token: yyDollar[1].token.Token} } case 86: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:636 +//line lib/parser/parser.y:638 { yyVAL.statement = TransactionControl{BaseExpr: NewBaseExpr(yyDollar[1].token), Token: yyDollar[1].token.Token} } case 87: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:642 +//line lib/parser/parser.y:644 { yyVAL.statement = CreateTable{Table: yyDollar[4].identifier, Fields: yyDollar[6].queryexprs, IfNotExists: yyDollar[3].bool} } case 88: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:646 +//line lib/parser/parser.y:648 { yyVAL.statement = CreateTable{Table: yyDollar[4].identifier, Fields: yyDollar[6].queryexprs, Query: yyDollar[9].queryexpr, IfNotExists: yyDollar[3].bool} } case 89: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:650 +//line lib/parser/parser.y:652 { yyVAL.statement = CreateTable{Table: yyDollar[4].identifier, Query: yyDollar[6].queryexpr, IfNotExists: yyDollar[3].bool} } case 90: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:654 +//line lib/parser/parser.y:656 { yyVAL.statement = AddColumns{Table: yyDollar[3].queryexpr, Columns: []ColumnDefault{yyDollar[5].columndef}, Position: yyDollar[6].expression} } case 91: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:658 +//line lib/parser/parser.y:660 { yyVAL.statement = AddColumns{Table: yyDollar[3].queryexpr, Columns: yyDollar[6].columndefs, Position: yyDollar[8].expression} } case 92: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:662 +//line lib/parser/parser.y:664 { yyVAL.statement = DropColumns{Table: yyDollar[3].queryexpr, Columns: []QueryExpression{yyDollar[5].queryexpr}} } case 93: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:666 +//line lib/parser/parser.y:668 { yyVAL.statement = DropColumns{Table: yyDollar[3].queryexpr, Columns: yyDollar[6].queryexprs} } case 94: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:670 +//line lib/parser/parser.y:672 { yyVAL.statement = RenameColumn{Table: yyDollar[3].queryexpr, Old: yyDollar[5].queryexpr, New: yyDollar[7].identifier} } case 95: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:674 +//line lib/parser/parser.y:676 { yyVAL.statement = SetTableAttribute{BaseExpr: NewBaseExpr(yyDollar[1].token), Table: yyDollar[3].queryexpr, Attribute: yyDollar[5].identifier, Value: yyDollar[7].identifier} } case 96: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:678 +//line lib/parser/parser.y:680 { yyVAL.statement = SetTableAttribute{BaseExpr: NewBaseExpr(yyDollar[1].token), Table: yyDollar[3].queryexpr, Attribute: yyDollar[5].identifier, Value: yyDollar[7].queryexpr} } case 97: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:684 +//line lib/parser/parser.y:686 { yyVAL.columndef = ColumnDefault{Column: yyDollar[1].identifier} } case 98: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:688 +//line lib/parser/parser.y:690 { yyVAL.columndef = ColumnDefault{Column: yyDollar[1].identifier, Value: yyDollar[3].queryexpr} } case 99: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:694 +//line lib/parser/parser.y:696 { yyVAL.columndefs = []ColumnDefault{yyDollar[1].columndef} } case 100: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:698 +//line lib/parser/parser.y:700 { yyVAL.columndefs = append([]ColumnDefault{yyDollar[1].columndef}, yyDollar[3].columndefs...) } case 101: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:704 +//line lib/parser/parser.y:706 { yyVAL.expression = nil } case 102: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:708 +//line lib/parser/parser.y:710 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token} } case 103: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:712 +//line lib/parser/parser.y:714 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token} } case 104: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:716 +//line lib/parser/parser.y:718 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token, Column: yyDollar[2].queryexpr} } case 105: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:720 +//line lib/parser/parser.y:722 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token, Column: yyDollar[2].queryexpr} } case 106: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:726 +//line lib/parser/parser.y:728 { yyVAL.statement = CursorDeclaration{Cursor: yyDollar[2].identifier, Query: yyDollar[5].queryexpr.(SelectQuery)} } case 107: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:730 +//line lib/parser/parser.y:732 { yyVAL.statement = CursorDeclaration{Cursor: yyDollar[2].identifier, Statement: yyDollar[5].identifier} } case 108: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:734 +//line lib/parser/parser.y:736 { yyVAL.statement = OpenCursor{Cursor: yyDollar[2].identifier} } case 109: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:738 +//line lib/parser/parser.y:740 { yyVAL.statement = OpenCursor{Cursor: yyDollar[2].identifier, Values: yyDollar[4].replacevals} } case 110: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:742 +//line lib/parser/parser.y:744 { yyVAL.statement = CloseCursor{Cursor: yyDollar[2].identifier} } case 111: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:746 +//line lib/parser/parser.y:748 { yyVAL.statement = DisposeCursor{Cursor: yyDollar[3].identifier} } case 112: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:750 +//line lib/parser/parser.y:752 { yyVAL.statement = FetchCursor{Position: yyDollar[2].fetchpos, Cursor: yyDollar[3].identifier, Variables: yyDollar[5].variables} } case 113: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:756 +//line lib/parser/parser.y:758 { yyVAL.statement = ViewDeclaration{View: yyDollar[2].identifier, Fields: yyDollar[5].queryexprs} } case 114: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:760 +//line lib/parser/parser.y:762 { yyVAL.statement = ViewDeclaration{View: yyDollar[2].identifier, Fields: yyDollar[5].queryexprs, Query: yyDollar[8].queryexpr} } case 115: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:764 +//line lib/parser/parser.y:766 { yyVAL.statement = ViewDeclaration{View: yyDollar[2].identifier, Query: yyDollar[5].queryexpr} } case 116: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:768 +//line lib/parser/parser.y:770 { yyVAL.statement = DisposeView{View: yyDollar[3].queryexpr} } case 117: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:774 +//line lib/parser/parser.y:776 { yyVAL.replaceval = ReplaceValue{Value: yyDollar[1].queryexpr} } case 118: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:778 +//line lib/parser/parser.y:780 { yyVAL.replaceval = ReplaceValue{Value: yyDollar[1].queryexpr, Name: yyDollar[3].identifier} } case 119: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:784 +//line lib/parser/parser.y:786 { yyVAL.replacevals = []ReplaceValue{yyDollar[1].replaceval} } case 120: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:788 +//line lib/parser/parser.y:790 { yyVAL.replacevals = append([]ReplaceValue{yyDollar[1].replaceval}, yyDollar[3].replacevals...) } case 121: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:794 +//line lib/parser/parser.y:796 { yyVAL.statement = StatementPreparation{Name: yyDollar[2].identifier, Statement: value.NewString(yyDollar[4].token.Literal)} } case 122: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:798 +//line lib/parser/parser.y:800 { yyVAL.statement = ExecuteStatement{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[2].identifier} } case 123: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:802 +//line lib/parser/parser.y:804 { yyVAL.statement = ExecuteStatement{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[2].identifier, Values: yyDollar[4].replacevals} } case 124: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:806 +//line lib/parser/parser.y:808 { yyVAL.statement = DisposeStatement{Name: yyDollar[3].identifier} } case 125: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:812 +//line lib/parser/parser.y:814 { yyVAL.varassign = VariableAssignment{Variable: yyDollar[1].variable} } case 126: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:818 +//line lib/parser/parser.y:820 { yyVAL.varassigns = []VariableAssignment{yyDollar[1].varassign} } case 127: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:822 +//line lib/parser/parser.y:824 { yyVAL.varassigns = append(yyDollar[1].varassigns, yyDollar[3].varassign) } case 128: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:828 +//line lib/parser/parser.y:830 { yyVAL.varassign = VariableAssignment{Variable: yyDollar[1].variable, Value: yyDollar[3].queryexpr} } case 129: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:834 +//line lib/parser/parser.y:836 { yyVAL.varassigns = []VariableAssignment{yyDollar[1].varassign} } case 130: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:838 +//line lib/parser/parser.y:840 { yyVAL.varassigns = append([]VariableAssignment{yyDollar[1].varassign}, yyDollar[3].varassigns...) } case 131: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:844 +//line lib/parser/parser.y:846 { yyVAL.varassigns = yyDollar[1].varassigns } case 132: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:848 +//line lib/parser/parser.y:850 { yyVAL.varassigns = yyDollar[1].varassigns } case 133: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:852 +//line lib/parser/parser.y:854 { yyVAL.varassigns = append(yyDollar[1].varassigns, yyDollar[3].varassigns...) } case 134: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:858 +//line lib/parser/parser.y:860 { yyVAL.statement = FunctionDeclaration{Name: yyDollar[2].identifier, Statements: yyDollar[8].program} } case 135: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:862 +//line lib/parser/parser.y:864 { yyVAL.statement = FunctionDeclaration{Name: yyDollar[2].identifier, Parameters: yyDollar[5].varassigns, Statements: yyDollar[9].program} } case 136: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:866 +//line lib/parser/parser.y:868 { yyVAL.statement = AggregateDeclaration{Name: yyDollar[2].identifier, Cursor: yyDollar[5].identifier, Statements: yyDollar[9].program} } case 137: yyDollar = yyS[yypt-12 : yypt+1] -//line parser.y:870 +//line lib/parser/parser.y:872 { yyVAL.statement = AggregateDeclaration{Name: yyDollar[2].identifier, Cursor: yyDollar[5].identifier, Parameters: yyDollar[7].varassigns, Statements: yyDollar[11].program} } case 138: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:874 +//line lib/parser/parser.y:876 { yyVAL.statement = DisposeFunction{Name: yyDollar[3].identifier} } case 139: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:880 +//line lib/parser/parser.y:882 { yyVAL.fetchpos = FetchPosition{} } case 140: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:884 +//line lib/parser/parser.y:886 { yyVAL.fetchpos = FetchPosition{Position: yyDollar[1].token} } case 141: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:888 +//line lib/parser/parser.y:890 { yyVAL.fetchpos = FetchPosition{Position: yyDollar[1].token} } case 142: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:892 +//line lib/parser/parser.y:894 { yyVAL.fetchpos = FetchPosition{Position: yyDollar[1].token} } case 143: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:896 +//line lib/parser/parser.y:898 { yyVAL.fetchpos = FetchPosition{Position: yyDollar[1].token} } case 144: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:900 +//line lib/parser/parser.y:902 { yyVAL.fetchpos = FetchPosition{BaseExpr: NewBaseExpr(yyDollar[1].token), Position: yyDollar[1].token, Number: yyDollar[2].queryexpr} } case 145: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:904 +//line lib/parser/parser.y:906 { yyVAL.fetchpos = FetchPosition{BaseExpr: NewBaseExpr(yyDollar[1].token), Position: yyDollar[1].token, Number: yyDollar[2].queryexpr} } case 146: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:910 +//line lib/parser/parser.y:912 { yyVAL.queryexpr = CursorStatus{Cursor: yyDollar[2].identifier, Negation: yyDollar[4].token, Type: yyDollar[5].token} } case 147: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:914 +//line lib/parser/parser.y:916 { yyVAL.queryexpr = CursorStatus{Cursor: yyDollar[2].identifier, Negation: yyDollar[4].token, Type: yyDollar[6].token} } case 148: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:918 +//line lib/parser/parser.y:920 { yyVAL.queryexpr = CursorAttrebute{Cursor: yyDollar[2].identifier, Attrebute: yyDollar[3].token} } case 149: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:924 +//line lib/parser/parser.y:926 { yyVAL.statement = SetFlag{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[2].flag, Value: yyDollar[4].identifier} } case 150: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:928 +//line lib/parser/parser.y:930 { yyVAL.statement = SetFlag{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[2].flag, Value: yyDollar[4].queryexpr} } case 151: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:932 +//line lib/parser/parser.y:934 { yyVAL.statement = SetFlag{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[2].flag, Value: yyDollar[4].identifier} } case 152: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:936 +//line lib/parser/parser.y:938 { yyVAL.statement = SetFlag{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[2].flag, Value: yyDollar[4].queryexpr} } case 153: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:940 +//line lib/parser/parser.y:942 { yyVAL.statement = AddFlagElement{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[4].flag, Value: yyDollar[2].queryexpr} } case 154: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:944 +//line lib/parser/parser.y:946 { yyVAL.statement = RemoveFlagElement{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[4].flag, Value: yyDollar[2].queryexpr} } case 155: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:948 +//line lib/parser/parser.y:950 { yyVAL.statement = ShowFlag{BaseExpr: NewBaseExpr(yyDollar[1].token), Flag: yyDollar[2].flag} } case 156: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:952 +//line lib/parser/parser.y:954 { yyVAL.statement = Echo{Value: yyDollar[2].queryexpr} } case 157: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:956 +//line lib/parser/parser.y:958 { yyVAL.statement = Print{Value: yyDollar[2].queryexpr} } case 158: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:960 +//line lib/parser/parser.y:962 { yyVAL.statement = Printf{BaseExpr: NewBaseExpr(yyDollar[1].token), Format: yyDollar[2].queryexpr} } case 159: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:964 +//line lib/parser/parser.y:966 { yyVAL.statement = Printf{BaseExpr: NewBaseExpr(yyDollar[1].token), Format: yyDollar[2].queryexpr, Values: yyDollar[4].queryexprs} } case 160: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:968 +//line lib/parser/parser.y:970 { yyVAL.statement = Printf{BaseExpr: NewBaseExpr(yyDollar[1].token), Format: yyDollar[2].queryexpr, Values: yyDollar[4].queryexprs} } case 161: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:972 +//line lib/parser/parser.y:974 { yyVAL.statement = Source{BaseExpr: NewBaseExpr(yyDollar[1].token), FilePath: yyDollar[2].identifier} } case 162: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:976 +//line lib/parser/parser.y:978 { yyVAL.statement = Source{BaseExpr: NewBaseExpr(yyDollar[1].token), FilePath: yyDollar[2].queryexpr} } case 163: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:980 +//line lib/parser/parser.y:982 { yyVAL.statement = Execute{BaseExpr: NewBaseExpr(yyDollar[1].token), Statements: yyDollar[2].queryexpr} } case 164: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:984 +//line lib/parser/parser.y:986 { yyVAL.statement = Execute{BaseExpr: NewBaseExpr(yyDollar[1].token), Statements: yyDollar[2].queryexpr, Values: yyDollar[4].queryexprs} } case 165: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:988 +//line lib/parser/parser.y:990 { yyVAL.statement = Syntax{BaseExpr: NewBaseExpr(yyDollar[1].token)} } case 166: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:992 +//line lib/parser/parser.y:994 { yyVAL.statement = Syntax{BaseExpr: NewBaseExpr(yyDollar[1].token), Keywords: yyDollar[2].queryexprs} } case 167: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:996 +//line lib/parser/parser.y:998 { yyVAL.statement = ShowObjects{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[2].identifier} } case 168: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1000 +//line lib/parser/parser.y:1002 { yyVAL.statement = ShowFields{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[2].identifier, Table: yyDollar[4].queryexpr} } case 169: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1004 +//line lib/parser/parser.y:1006 { yyVAL.statement = Chdir{BaseExpr: NewBaseExpr(yyDollar[1].token), DirPath: yyDollar[2].identifier} } case 170: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1008 +//line lib/parser/parser.y:1010 { yyVAL.statement = Chdir{BaseExpr: NewBaseExpr(yyDollar[1].token), DirPath: yyDollar[2].queryexpr} } case 171: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1012 +//line lib/parser/parser.y:1014 { yyVAL.statement = Pwd{BaseExpr: NewBaseExpr(yyDollar[1].token)} } case 172: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1016 +//line lib/parser/parser.y:1018 { yyVAL.statement = Reload{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[2].identifier} } case 173: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1022 +//line lib/parser/parser.y:1024 { yyVAL.statement = Trigger{BaseExpr: NewBaseExpr(yyDollar[1].token), Event: yyDollar[2].identifier} } case 174: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1026 +//line lib/parser/parser.y:1028 { yyVAL.statement = Trigger{BaseExpr: NewBaseExpr(yyDollar[1].token), Event: yyDollar[2].identifier, Message: yyDollar[3].queryexpr} } case 175: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1030 +//line lib/parser/parser.y:1032 { yyVAL.statement = Trigger{BaseExpr: NewBaseExpr(yyDollar[1].token), Event: yyDollar[2].identifier, Message: yyDollar[4].queryexpr, Code: value.NewIntegerFromString(yyDollar[3].token.Literal)} } case 176: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1036 +//line lib/parser/parser.y:1038 { yyVAL.queryexpr = SelectQuery{ SelectEntity: yyDollar[1].queryexpr, @@ -3226,7 +3232,7 @@ yydefault: } case 177: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1044 +//line lib/parser/parser.y:1046 { yyVAL.queryexpr = SelectQuery{ SelectEntity: yyDollar[1].queryexpr, @@ -3237,7 +3243,7 @@ yydefault: } case 178: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1053 +//line lib/parser/parser.y:1055 { yyVAL.queryexpr = SelectQuery{ WithClause: yyDollar[1].queryexpr, @@ -3248,7 +3254,7 @@ yydefault: } case 179: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1062 +//line lib/parser/parser.y:1064 { yyVAL.queryexpr = SelectQuery{ WithClause: yyDollar[1].queryexpr, @@ -3260,7 +3266,7 @@ yydefault: } case 180: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1074 +//line lib/parser/parser.y:1076 { yyVAL.queryexpr = SelectQuery{ SelectEntity: SelectEntity{ @@ -3277,7 +3283,7 @@ yydefault: } case 181: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:1089 +//line lib/parser/parser.y:1091 { yyVAL.queryexpr = SelectQuery{ SelectEntity: SelectEntity{ @@ -3295,7 +3301,7 @@ yydefault: } case 182: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1105 +//line lib/parser/parser.y:1107 { yyVAL.queryexpr = SelectQuery{ WithClause: yyDollar[1].queryexpr, @@ -3313,7 +3319,7 @@ yydefault: } case 183: yyDollar = yyS[yypt-11 : yypt+1] -//line parser.y:1121 +//line lib/parser/parser.y:1123 { yyVAL.queryexpr = SelectQuery{ WithClause: yyDollar[1].queryexpr, @@ -3332,7 +3338,7 @@ yydefault: } case 184: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1140 +//line lib/parser/parser.y:1142 { yyVAL.queryexpr = SelectEntity{ SelectClause: yyDollar[1].queryexpr, @@ -3344,7 +3350,7 @@ yydefault: } case 185: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1150 +//line lib/parser/parser.y:1152 { yyVAL.queryexpr = SelectSet{ LHS: yyDollar[1].queryexpr, @@ -3355,7 +3361,7 @@ yydefault: } case 186: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1159 +//line lib/parser/parser.y:1161 { yyVAL.queryexpr = SelectSet{ LHS: yyDollar[1].queryexpr, @@ -3366,7 +3372,7 @@ yydefault: } case 187: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1168 +//line lib/parser/parser.y:1170 { yyVAL.queryexpr = SelectSet{ LHS: yyDollar[1].queryexpr, @@ -3377,91 +3383,91 @@ yydefault: } case 188: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1179 +//line lib/parser/parser.y:1181 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 189: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1183 +//line lib/parser/parser.y:1185 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 190: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1189 +//line lib/parser/parser.y:1191 { yyVAL.queryexpr = SelectClause{BaseExpr: NewBaseExpr(yyDollar[1].token), Distinct: yyDollar[2].token, Fields: yyDollar[3].queryexprs} } case 191: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1195 +//line lib/parser/parser.y:1197 { yyVAL.queryexpr = IntoClause{Variables: yyDollar[2].variables} } case 192: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1201 +//line lib/parser/parser.y:1203 { yyVAL.queryexpr = nil } case 193: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1205 +//line lib/parser/parser.y:1207 { yyVAL.queryexpr = FromClause{Tables: yyDollar[2].queryexprs} } case 194: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1211 +//line lib/parser/parser.y:1213 { yyVAL.queryexpr = nil } case 195: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1215 +//line lib/parser/parser.y:1217 { yyVAL.queryexpr = WhereClause{Filter: yyDollar[2].queryexpr} } case 196: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1221 +//line lib/parser/parser.y:1223 { yyVAL.queryexpr = nil } case 197: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1225 +//line lib/parser/parser.y:1227 { yyVAL.queryexpr = GroupByClause{Items: yyDollar[3].queryexprs} } case 198: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1231 +//line lib/parser/parser.y:1233 { yyVAL.queryexpr = nil } case 199: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1235 +//line lib/parser/parser.y:1237 { yyVAL.queryexpr = HavingClause{Filter: yyDollar[2].queryexpr} } case 200: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1241 +//line lib/parser/parser.y:1243 { yyVAL.queryexpr = nil } case 201: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1245 +//line lib/parser/parser.y:1247 { yyVAL.queryexpr = OrderByClause{Items: yyDollar[3].queryexprs} } case 202: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1251 +//line lib/parser/parser.y:1253 { if yyDollar[1].queryexpr == nil { yyVAL.queryexpr = yyDollar[1].queryexpr @@ -3471,7 +3477,7 @@ yydefault: } case 203: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1259 +//line lib/parser/parser.y:1261 { var base *BaseExpr if yyDollar[1].queryexpr == nil { @@ -3483,145 +3489,145 @@ yydefault: } case 204: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1269 +//line lib/parser/parser.y:1271 { yyVAL.queryexpr = LimitClause{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, Value: yyDollar[2].queryexpr, Unit: yyDollar[3].token, Restriction: yyDollar[4].token, OffsetClause: yyDollar[5].queryexpr} } case 205: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1275 +//line lib/parser/parser.y:1277 { yyVAL.token = Token{} } case 206: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1279 +//line lib/parser/parser.y:1281 { yyVAL.token = yyDollar[1].token } case 207: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1283 +//line lib/parser/parser.y:1285 { yyVAL.token = yyDollar[2].token } case 208: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1289 +//line lib/parser/parser.y:1291 { yyVAL.token = yyDollar[1].token } case 209: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1293 +//line lib/parser/parser.y:1295 { yyVAL.token = yyDollar[1].token } case 210: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1299 +//line lib/parser/parser.y:1301 { yyVAL.token = Token{} } case 211: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1303 +//line lib/parser/parser.y:1305 { yyVAL.token = yyDollar[1].token } case 212: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1309 +//line lib/parser/parser.y:1311 { yyVAL.token = yyDollar[1].token } case 213: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1313 +//line lib/parser/parser.y:1315 { yyVAL.token = yyDollar[1].token } case 214: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1317 +//line lib/parser/parser.y:1319 { yyVAL.token = yyDollar[1].token } case 215: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1323 +//line lib/parser/parser.y:1325 { yyVAL.token = Token{} } case 216: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1327 +//line lib/parser/parser.y:1329 { yyVAL.token = yyDollar[1].token } case 217: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1331 +//line lib/parser/parser.y:1333 { yyVAL.token = yyDollar[1].token } case 218: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1337 +//line lib/parser/parser.y:1339 { yyVAL.queryexpr = nil } case 219: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1341 +//line lib/parser/parser.y:1343 { yyVAL.queryexpr = OffsetClause{BaseExpr: NewBaseExpr(yyDollar[1].token), Value: yyDollar[2].queryexpr, Unit: yyDollar[3].token} } case 220: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1347 +//line lib/parser/parser.y:1349 { yyVAL.queryexpr = nil } case 221: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1351 +//line lib/parser/parser.y:1353 { yyVAL.queryexpr = WithClause{InlineTables: yyDollar[2].queryexprs} } case 222: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1357 +//line lib/parser/parser.y:1359 { yyVAL.queryexpr = InlineTable{Recursive: yyDollar[1].token, Name: yyDollar[2].identifier, Query: yyDollar[5].queryexpr.(SelectQuery)} } case 223: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1361 +//line lib/parser/parser.y:1363 { yyVAL.queryexpr = InlineTable{Recursive: yyDollar[1].token, Name: yyDollar[2].identifier, Fields: yyDollar[4].queryexprs, Query: yyDollar[8].queryexpr.(SelectQuery)} } case 224: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1367 +//line lib/parser/parser.y:1369 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } case 225: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1371 +//line lib/parser/parser.y:1373 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } case 226: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1377 +//line lib/parser/parser.y:1379 { yyVAL.queryexpr = NewStringValue(yyDollar[1].token.Literal) } case 227: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1381 +//line lib/parser/parser.y:1383 { i, err := strconv.ParseInt(yyDollar[1].token.Literal, 10, 64) if err != nil { @@ -3634,187 +3640,193 @@ yydefault: } case 228: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1392 +//line lib/parser/parser.y:1394 { yyVAL.queryexpr = NewFloatValueFromString(yyDollar[1].token.Literal) } case 229: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1396 +//line lib/parser/parser.y:1398 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 230: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1400 +//line lib/parser/parser.y:1402 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 231: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1406 +//line lib/parser/parser.y:1408 { yyVAL.queryexpr = NewTernaryValueFromString(yyDollar[1].token.Literal) } case 232: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1412 +//line lib/parser/parser.y:1414 { yyVAL.queryexpr = NewNullValue() } case 233: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1418 +//line lib/parser/parser.y:1420 { yyVAL.queryexpr = FieldReference{BaseExpr: yyDollar[1].identifier.BaseExpr, Column: yyDollar[1].identifier} } case 234: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1422 +//line lib/parser/parser.y:1424 { yyVAL.queryexpr = FieldReference{BaseExpr: yyDollar[1].identifier.BaseExpr, View: yyDollar[1].identifier, Column: yyDollar[3].identifier} } case 235: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1426 +//line lib/parser/parser.y:1428 { yyVAL.queryexpr = FieldReference{BaseExpr: NewBaseExpr(yyDollar[1].token), View: Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal}, Column: yyDollar[3].identifier} } case 236: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1430 +//line lib/parser/parser.y:1432 { yyVAL.queryexpr = ColumnNumber{BaseExpr: yyDollar[1].identifier.BaseExpr, View: yyDollar[1].identifier, Number: value.NewIntegerFromString(yyDollar[3].token.Literal)} } case 237: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1434 +//line lib/parser/parser.y:1436 { yyVAL.queryexpr = ColumnNumber{BaseExpr: NewBaseExpr(yyDollar[1].token), View: Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal}, Number: value.NewIntegerFromString(yyDollar[3].token.Literal)} } case 238: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1440 +//line lib/parser/parser.y:1442 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 239: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1444 +//line lib/parser/parser.y:1446 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 240: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1448 +//line lib/parser/parser.y:1450 { yyVAL.queryexpr = Parentheses{Expr: yyDollar[2].queryexpr} } case 241: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1454 +//line lib/parser/parser.y:1456 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 242: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1458 +//line lib/parser/parser.y:1460 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 243: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1462 +//line lib/parser/parser.y:1464 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 244: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1466 +//line lib/parser/parser.y:1468 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 245: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1470 +//line lib/parser/parser.y:1472 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 246: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1474 +//line lib/parser/parser.y:1476 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 247: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1478 +//line lib/parser/parser.y:1480 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 248: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1482 +//line lib/parser/parser.y:1484 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 249: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1486 +//line lib/parser/parser.y:1488 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 250: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1490 +//line lib/parser/parser.y:1492 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 251: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1494 +//line lib/parser/parser.y:1496 { yyVAL.queryexpr = yyDollar[1].variable } case 252: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1498 +//line lib/parser/parser.y:1500 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 253: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1502 +//line lib/parser/parser.y:1504 { yyVAL.queryexpr = yyDollar[1].envvar } case 254: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1506 +//line lib/parser/parser.y:1508 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 255: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1510 +//line lib/parser/parser.y:1512 { - yyVAL.queryexpr = yyDollar[1].flag + yyVAL.queryexpr = yyDollar[1].queryexpr } case 256: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1514 +//line lib/parser/parser.y:1516 { - yyVAL.queryexpr = yyDollar[1].queryexpr + yyVAL.queryexpr = yyDollar[1].flag } case 257: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:1520 + { + yyVAL.queryexpr = yyDollar[1].queryexpr + } + case 258: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1518 +//line lib/parser/parser.y:1524 { yyVAL.queryexpr = Parentheses{Expr: yyDollar[2].queryexpr} } - case 258: + case 259: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1522 +//line lib/parser/parser.y:1528 { name := "" if yyDollar[1].token.Literal[0] == ':' { @@ -3822,105 +3834,105 @@ yydefault: } yyVAL.queryexpr = Placeholder{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Ordinal: yyDollar[1].token.HolderOrdinal, Name: name} } - case 259: + case 260: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1532 +//line lib/parser/parser.y:1538 { yyVAL.queryexpr = AllColumns{BaseExpr: NewBaseExpr(yyDollar[1].token)} } - case 260: + case 261: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1538 +//line lib/parser/parser.y:1544 { yyVAL.queryexpr = RowValue{BaseExpr: NewBaseExpr(yyDollar[1].token), Value: ValueList{Values: yyDollar[2].queryexprs}} } - case 261: + case 262: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1542 +//line lib/parser/parser.y:1548 { yyVAL.queryexpr = RowValue{BaseExpr: yyDollar[1].queryexpr.GetBaseExpr(), Value: yyDollar[1].queryexpr} } - case 262: + case 263: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1546 +//line lib/parser/parser.y:1552 { yyVAL.queryexpr = RowValue{BaseExpr: NewBaseExpr(yyDollar[1].token), Value: JsonQuery{JsonQuery: yyDollar[1].token, Query: yyDollar[3].queryexpr, JsonText: yyDollar[5].queryexpr}} } - case 263: + case 264: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1552 +//line lib/parser/parser.y:1558 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 264: + case 265: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1556 +//line lib/parser/parser.y:1562 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 265: + case 266: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1562 +//line lib/parser/parser.y:1568 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 266: + case 267: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1566 +//line lib/parser/parser.y:1572 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 267: + case 268: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1572 +//line lib/parser/parser.y:1578 { yyVAL.queryexpr = OrderItem{Value: yyDollar[1].queryexpr, Direction: yyDollar[2].token} } - case 268: + case 269: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1576 +//line lib/parser/parser.y:1582 { yyVAL.queryexpr = OrderItem{Value: yyDollar[1].queryexpr, Direction: yyDollar[2].token, NullsPosition: yyDollar[4].token} } - case 269: + case 270: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1582 +//line lib/parser/parser.y:1588 { yyVAL.token = Token{} } - case 270: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1586 - { - yyVAL.token = yyDollar[1].token - } case 271: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1590 +//line lib/parser/parser.y:1592 { yyVAL.token = yyDollar[1].token } case 272: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1596 +//line lib/parser/parser.y:1596 { yyVAL.token = yyDollar[1].token } case 273: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1600 +//line lib/parser/parser.y:1602 { yyVAL.token = yyDollar[1].token } case 274: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:1606 + { + yyVAL.token = yyDollar[1].token + } + case 275: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1606 +//line lib/parser/parser.y:1612 { yyVAL.queryexpr = Subquery{BaseExpr: NewBaseExpr(yyDollar[1].token), Query: yyDollar[2].queryexpr.(SelectQuery)} } - case 275: + case 276: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1612 +//line lib/parser/parser.y:1618 { var item1 []QueryExpression var item2 []QueryExpression @@ -3941,1497 +3953,1513 @@ yydefault: yyVAL.queryexpr = Concat{Items: append(item1, item2...)} } - case 276: + case 277: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1635 +//line lib/parser/parser.y:1641 { yyVAL.queryexpr = RowValueList{RowValues: yyDollar[2].queryexprs} } - case 277: + case 278: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1639 +//line lib/parser/parser.y:1645 { yyVAL.queryexpr = yyDollar[1].queryexpr } - case 278: + case 279: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1643 +//line lib/parser/parser.y:1649 { yyVAL.queryexpr = JsonQuery{BaseExpr: NewBaseExpr(yyDollar[1].token), JsonQuery: yyDollar[1].token, Query: yyDollar[3].queryexpr, JsonText: yyDollar[5].queryexpr} } - case 279: - yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1649 - { - yyVAL.queryexpr = Comparison{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} - } case 280: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1653 +//line lib/parser/parser.y:1655 { yyVAL.queryexpr = Comparison{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 281: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1657 +//line lib/parser/parser.y:1659 { yyVAL.queryexpr = Comparison{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 282: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1661 +//line lib/parser/parser.y:1663 { yyVAL.queryexpr = Comparison{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 283: - yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1665 + yyDollar = yyS[yypt-3 : yypt+1] +//line lib/parser/parser.y:1667 { - yyVAL.queryexpr = Is{LHS: yyDollar[1].queryexpr, RHS: yyDollar[4].queryexpr, Negation: yyDollar[3].token} + yyVAL.queryexpr = Comparison{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 284: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1669 +//line lib/parser/parser.y:1671 { yyVAL.queryexpr = Is{LHS: yyDollar[1].queryexpr, RHS: yyDollar[4].queryexpr, Negation: yyDollar[3].token} } case 285: + yyDollar = yyS[yypt-4 : yypt+1] +//line lib/parser/parser.y:1675 + { + yyVAL.queryexpr = Is{LHS: yyDollar[1].queryexpr, RHS: yyDollar[4].queryexpr, Negation: yyDollar[3].token} + } + case 286: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1673 +//line lib/parser/parser.y:1679 { yyVAL.queryexpr = Between{LHS: yyDollar[1].queryexpr, Low: yyDollar[3].queryexpr, High: yyDollar[5].queryexpr} } - case 286: + case 287: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1677 +//line lib/parser/parser.y:1683 { yyVAL.queryexpr = Between{LHS: yyDollar[1].queryexpr, Low: yyDollar[4].queryexpr, High: yyDollar[6].queryexpr, Negation: yyDollar[2].token} } - case 287: + case 288: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1681 +//line lib/parser/parser.y:1687 { yyVAL.queryexpr = Between{LHS: yyDollar[1].queryexpr, Low: yyDollar[4].queryexpr, High: yyDollar[6].queryexpr, Negation: yyDollar[2].token} } - case 288: + case 289: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1685 +//line lib/parser/parser.y:1691 { yyVAL.queryexpr = In{LHS: yyDollar[1].queryexpr, Values: yyDollar[3].queryexpr} } - case 289: + case 290: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1689 +//line lib/parser/parser.y:1695 { yyVAL.queryexpr = In{LHS: yyDollar[1].queryexpr, Values: yyDollar[4].queryexpr, Negation: yyDollar[2].token} } - case 290: + case 291: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1693 +//line lib/parser/parser.y:1699 { yyVAL.queryexpr = In{LHS: yyDollar[1].queryexpr, Values: yyDollar[4].queryexpr, Negation: yyDollar[2].token} } - case 291: + case 292: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1697 +//line lib/parser/parser.y:1703 { yyVAL.queryexpr = Like{LHS: yyDollar[1].queryexpr, Pattern: yyDollar[3].queryexpr} } - case 292: - yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1701 - { - yyVAL.queryexpr = Like{LHS: yyDollar[1].queryexpr, Pattern: yyDollar[4].queryexpr, Negation: yyDollar[2].token} - } case 293: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1705 +//line lib/parser/parser.y:1707 { - yyVAL.queryexpr = Any{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} + yyVAL.queryexpr = Like{LHS: yyDollar[1].queryexpr, Pattern: yyDollar[4].queryexpr, Negation: yyDollar[2].token} } case 294: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1709 +//line lib/parser/parser.y:1711 { yyVAL.queryexpr = Any{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} } case 295: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1713 +//line lib/parser/parser.y:1715 { - yyVAL.queryexpr = All{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} + yyVAL.queryexpr = Any{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} } case 296: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1717 +//line lib/parser/parser.y:1719 { yyVAL.queryexpr = All{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} } case 297: - yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1721 + yyDollar = yyS[yypt-4 : yypt+1] +//line lib/parser/parser.y:1723 { - yyVAL.queryexpr = Exists{Query: yyDollar[2].queryexpr.(Subquery)} + yyVAL.queryexpr = All{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, Values: yyDollar[4].queryexpr} } case 298: - yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1727 + yyDollar = yyS[yypt-2 : yypt+1] +//line lib/parser/parser.y:1727 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Exists{Query: yyDollar[2].queryexpr.(Subquery)} } case 299: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1731 +//line lib/parser/parser.y:1733 { yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 300: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1735 +//line lib/parser/parser.y:1737 { yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 301: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1739 +//line lib/parser/parser.y:1741 { yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 302: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1743 +//line lib/parser/parser.y:1745 { yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 303: - yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1747 + yyDollar = yyS[yypt-3 : yypt+1] +//line lib/parser/parser.y:1749 { - yyVAL.queryexpr = UnaryArithmetic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} + yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 304: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1751 +//line lib/parser/parser.y:1753 { yyVAL.queryexpr = UnaryArithmetic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} } case 305: - yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1757 + yyDollar = yyS[yypt-2 : yypt+1] +//line lib/parser/parser.y:1757 { - yyVAL.queryexpr = Logic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = UnaryArithmetic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} } case 306: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1761 +//line lib/parser/parser.y:1763 { yyVAL.queryexpr = Logic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 307: - yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1765 + yyDollar = yyS[yypt-3 : yypt+1] +//line lib/parser/parser.y:1767 { - yyVAL.queryexpr = UnaryLogic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} + yyVAL.queryexpr = Logic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 308: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1769 +//line lib/parser/parser.y:1771 { yyVAL.queryexpr = UnaryLogic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} } case 309: + yyDollar = yyS[yypt-2 : yypt+1] +//line lib/parser/parser.y:1775 + { + yyVAL.queryexpr = UnaryLogic{Operand: yyDollar[2].queryexpr, Operator: yyDollar[1].token} + } + case 310: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1775 +//line lib/parser/parser.y:1781 { yyVAL.queryexprs = nil } - case 310: + case 311: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1779 +//line lib/parser/parser.y:1785 { yyVAL.queryexprs = yyDollar[1].queryexprs } - case 311: + case 312: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1785 +//line lib/parser/parser.y:1791 { yyVAL.queryexpr = Function{BaseExpr: yyDollar[1].identifier.BaseExpr, Name: yyDollar[1].identifier.Literal, Args: yyDollar[3].queryexprs} } - case 312: + case 313: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1789 +//line lib/parser/parser.y:1795 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs} } - case 313: + case 314: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:1793 +//line lib/parser/parser.y:1799 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: []QueryExpression{yyDollar[3].queryexpr, yyDollar[5].queryexpr}, From: yyDollar[4].token} } - case 314: + case 315: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1797 +//line lib/parser/parser.y:1803 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: []QueryExpression{yyDollar[3].queryexpr, yyDollar[5].queryexpr, yyDollar[7].queryexpr}, From: yyDollar[4].token, For: yyDollar[6].token} } - case 315: + case 316: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1801 +//line lib/parser/parser.y:1807 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} } - case 316: - yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1805 - { - yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs} - } case 317: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1809 +//line lib/parser/parser.y:1811 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs} } case 318: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:1813 +//line lib/parser/parser.y:1815 { yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs} } case 319: - yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1820 + yyDollar = yyS[yypt-4 : yypt+1] +//line lib/parser/parser.y:1819 { - yyVAL.queryexpr = AggregateFunction{BaseExpr: yyDollar[1].identifier.BaseExpr, Name: yyDollar[1].identifier.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} + yyVAL.queryexpr = Function{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs} } case 320: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1824 +//line lib/parser/parser.y:1826 { - yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} + yyVAL.queryexpr = AggregateFunction{BaseExpr: yyDollar[1].identifier.BaseExpr, Name: yyDollar[1].identifier.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} } case 321: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1828 +//line lib/parser/parser.y:1830 { yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} } case 322: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1832 +//line lib/parser/parser.y:1834 { yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} } case 323: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1836 +//line lib/parser/parser.y:1838 { - yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: []QueryExpression{yyDollar[4].queryexpr}} + yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} } case 324: + yyDollar = yyS[yypt-5 : yypt+1] +//line lib/parser/parser.y:1842 + { + yyVAL.queryexpr = AggregateFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: []QueryExpression{yyDollar[4].queryexpr}} + } + case 325: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1840 +//line lib/parser/parser.y:1846 { yyVAL.queryexpr = yyDollar[1].queryexpr } - case 325: + case 326: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1846 +//line lib/parser/parser.y:1852 { yyVAL.queryexpr = ListFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs} } - case 326: + case 327: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:1850 +//line lib/parser/parser.y:1856 { yyVAL.queryexpr = ListFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, OrderBy: yyDollar[9].queryexpr} } - case 327: + case 328: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1856 +//line lib/parser/parser.y:1862 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: yyDollar[1].identifier.BaseExpr, Name: yyDollar[1].identifier.Literal, Args: yyDollar[3].queryexprs, AnalyticClause: yyDollar[7].queryexpr.(AnalyticClause)} } - case 328: + case 329: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1860 +//line lib/parser/parser.y:1866 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: yyDollar[1].identifier.BaseExpr, Name: yyDollar[1].identifier.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 329: + case 330: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1864 +//line lib/parser/parser.y:1870 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 330: + case 331: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1868 +//line lib/parser/parser.y:1874 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 331: + case 332: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1872 +//line lib/parser/parser.y:1878 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 332: + case 333: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1876 +//line lib/parser/parser.y:1882 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: []QueryExpression{yyDollar[4].queryexpr}, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 333: + case 334: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:1880 +//line lib/parser/parser.y:1886 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Distinct: yyDollar[3].token, Args: yyDollar[4].queryexprs, AnalyticClause: yyDollar[8].queryexpr.(AnalyticClause)} } - case 334: + case 335: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1884 +//line lib/parser/parser.y:1890 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs, AnalyticClause: yyDollar[7].queryexpr.(AnalyticClause)} } - case 335: + case 336: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1888 +//line lib/parser/parser.y:1894 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs, AnalyticClause: yyDollar[7].queryexpr.(AnalyticClause)} } - case 336: + case 337: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:1892 +//line lib/parser/parser.y:1898 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs, IgnoreType: yyDollar[6].token, AnalyticClause: yyDollar[9].queryexpr.(AnalyticClause)} } - case 337: + case 338: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:1896 +//line lib/parser/parser.y:1902 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs, AnalyticClause: yyDollar[7].queryexpr.(AnalyticClause)} } - case 338: + case 339: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:1900 +//line lib/parser/parser.y:1906 { yyVAL.queryexpr = AnalyticFunction{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Args: yyDollar[3].queryexprs, IgnoreType: yyDollar[6].token, AnalyticClause: yyDollar[9].queryexpr.(AnalyticClause)} } - case 339: + case 340: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1906 +//line lib/parser/parser.y:1912 { yyVAL.queryexpr = AnalyticClause{PartitionClause: yyDollar[1].queryexpr, OrderByClause: yyDollar[2].queryexpr} } - case 340: + case 341: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1912 +//line lib/parser/parser.y:1918 { yyVAL.queryexpr = yyDollar[1].queryexpr } - case 341: + case 342: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1916 +//line lib/parser/parser.y:1922 { yyVAL.queryexpr = AnalyticClause{PartitionClause: yyDollar[1].queryexpr, OrderByClause: OrderByClause{Items: yyDollar[4].queryexprs}, WindowingClause: yyDollar[5].queryexpr} } - case 342: + case 343: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:1922 +//line lib/parser/parser.y:1928 { yyVAL.queryexpr = nil } - case 343: + case 344: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:1926 +//line lib/parser/parser.y:1932 { yyVAL.queryexpr = PartitionClause{Values: yyDollar[3].queryexprs} } - case 344: + case 345: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1932 +//line lib/parser/parser.y:1938 { yyVAL.queryexpr = WindowingClause{FrameLow: yyDollar[2].queryexpr} } - case 345: + case 346: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:1936 +//line lib/parser/parser.y:1942 { yyVAL.queryexpr = WindowingClause{FrameLow: yyDollar[3].queryexpr, FrameHigh: yyDollar[5].queryexpr} } - case 346: + case 347: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1942 +//line lib/parser/parser.y:1948 { yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Unbounded: yyDollar[1].token} } - case 347: + case 348: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1946 +//line lib/parser/parser.y:1952 { i, _ := strconv.Atoi(yyDollar[1].token.Literal) yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Offset: i} } - case 348: + case 349: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1951 +//line lib/parser/parser.y:1957 { yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[1].token} } - case 349: + case 350: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1957 +//line lib/parser/parser.y:1963 { i, _ := strconv.Atoi(yyDollar[1].token.Literal) yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Offset: i} } - case 350: + case 351: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1962 +//line lib/parser/parser.y:1968 { i, _ := strconv.Atoi(yyDollar[1].token.Literal) yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Offset: i} } - case 351: + case 352: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1967 +//line lib/parser/parser.y:1973 { yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[1].token} } - case 352: + case 353: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1973 +//line lib/parser/parser.y:1979 { yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Unbounded: yyDollar[1].token} } - case 353: + case 354: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1977 +//line lib/parser/parser.y:1983 { yyVAL.queryexpr = yyDollar[1].queryexpr } - case 354: + case 355: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:1983 +//line lib/parser/parser.y:1989 { yyVAL.queryexpr = WindowFramePosition{Direction: yyDollar[2].token, Unbounded: yyDollar[1].token} } - case 355: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1987 - { - yyVAL.queryexpr = yyDollar[1].queryexpr - } case 356: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1993 +//line lib/parser/parser.y:1993 { - yyVAL.queryexpr = yyDollar[1].identifier + yyVAL.queryexpr = yyDollar[1].queryexpr } case 357: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:1997 +//line lib/parser/parser.y:1999 { - yyVAL.queryexpr = Stdin{BaseExpr: NewBaseExpr(yyDollar[1].token)} + yyVAL.queryexpr = yyDollar[1].identifier } case 358: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2003 +//line lib/parser/parser.y:2003 { - yyVAL.token = yyDollar[1].token + yyVAL.queryexpr = Stdin{BaseExpr: NewBaseExpr(yyDollar[1].token)} } case 359: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2007 +//line lib/parser/parser.y:2009 { yyVAL.token = yyDollar[1].token } case 360: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2011 +//line lib/parser/parser.y:2013 { yyVAL.token = yyDollar[1].token } case 361: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2015 +//line lib/parser/parser.y:2017 { yyVAL.token = yyDollar[1].token } case 362: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2019 +//line lib/parser/parser.y:2021 { yyVAL.token = yyDollar[1].token } case 363: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2025 +//line lib/parser/parser.y:2025 { yyVAL.token = yyDollar[1].token } case 364: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2029 +//line lib/parser/parser.y:2031 { yyVAL.token = yyDollar[1].token } case 365: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2033 +//line lib/parser/parser.y:2035 { yyVAL.token = yyDollar[1].token } case 366: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2039 + { + yyVAL.token = yyDollar[1].token + } + case 367: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2039 +//line lib/parser/parser.y:2045 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, Path: yyDollar[3].queryexpr, Args: nil} } - case 367: + case 368: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2043 +//line lib/parser/parser.y:2049 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, Path: yyDollar[3].queryexpr, Args: yyDollar[5].queryexprs} } - case 368: + case 369: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2047 +//line lib/parser/parser.y:2053 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].queryexpr, Args: nil} } - case 369: + case 370: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:2051 +//line lib/parser/parser.y:2057 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].queryexpr, Args: yyDollar[7].queryexprs} } - case 370: + case 371: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2057 +//line lib/parser/parser.y:2063 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].identifier, Args: nil} } - case 371: + case 372: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:2061 +//line lib/parser/parser.y:2067 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].identifier, Args: yyDollar[7].queryexprs} } - case 372: + case 373: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2065 +//line lib/parser/parser.y:2071 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].queryexpr, Args: nil} } - case 373: + case 374: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:2069 +//line lib/parser/parser.y:2075 { yyVAL.queryexpr = TableObject{BaseExpr: NewBaseExpr(yyDollar[1].token), Type: yyDollar[1].token, FormatElement: yyDollar[3].queryexpr, Path: yyDollar[5].queryexpr, Args: yyDollar[7].queryexprs} } - case 374: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2075 - { - yyVAL.queryexpr = yyDollar[1].queryexpr - } case 375: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2079 +//line lib/parser/parser.y:2081 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 376: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2085 +//line lib/parser/parser.y:2085 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 377: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2089 +//line lib/parser/parser.y:2091 { yyVAL.queryexpr = yyDollar[1].queryexpr } case 378: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2095 +//line lib/parser/parser.y:2095 { - yyVAL.table = Table{Object: yyDollar[1].queryexpr} + yyVAL.queryexpr = yyDollar[1].queryexpr } case 379: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2101 + { + yyVAL.table = Table{Object: yyDollar[1].queryexpr} + } + case 380: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2099 +//line lib/parser/parser.y:2105 { yyVAL.table = Table{Object: yyDollar[1].queryexpr, Alias: yyDollar[2].identifier} } - case 380: + case 381: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2103 +//line lib/parser/parser.y:2109 { yyVAL.table = Table{Object: yyDollar[1].queryexpr, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 381: + case 382: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2109 +//line lib/parser/parser.y:2115 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 382: + case 383: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2113 +//line lib/parser/parser.y:2119 { yyDollar[2].table.Lateral = yyDollar[1].token yyDollar[2].table.BaseExpr = NewBaseExpr(yyDollar[1].token) yyVAL.queryexprs = []QueryExpression{yyDollar[2].table} } - case 383: + case 384: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2119 +//line lib/parser/parser.y:2125 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].table}, yyDollar[3].queryexprs...) } - case 384: + case 385: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2123 +//line lib/parser/parser.y:2129 { yyDollar[2].table.Lateral = yyDollar[1].token yyDollar[2].table.BaseExpr = NewBaseExpr(yyDollar[1].token) yyVAL.queryexprs = append([]QueryExpression{yyDollar[2].table}, yyDollar[4].queryexprs...) } - case 385: + case 386: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2131 +//line lib/parser/parser.y:2137 { yyVAL.queryexpr = Table{Object: yyDollar[1].queryexpr} } - case 386: + case 387: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2135 +//line lib/parser/parser.y:2141 { yyVAL.queryexpr = Table{Object: yyDollar[1].queryexpr, Alias: yyDollar[2].identifier} } - case 387: + case 388: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2139 +//line lib/parser/parser.y:2145 { yyVAL.queryexpr = Table{Object: yyDollar[1].queryexpr, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 388: + case 389: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2143 +//line lib/parser/parser.y:2149 { yyVAL.queryexpr = Table{Object: yyDollar[1].queryexpr} } - case 389: + case 390: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2147 +//line lib/parser/parser.y:2153 { yyVAL.queryexpr = Table{Object: Dual{}} } - case 390: + case 391: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2151 +//line lib/parser/parser.y:2157 { yyVAL.queryexpr = yyDollar[1].table } - case 391: + case 392: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2155 +//line lib/parser/parser.y:2161 { yyVAL.queryexpr = Parentheses{Expr: yyDollar[2].queryexpr} } - case 392: + case 393: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2161 +//line lib/parser/parser.y:2167 { yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[4].queryexpr, JoinType: yyDollar[2].token, Condition: nil} } - case 393: + case 394: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2165 +//line lib/parser/parser.y:2171 { yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[4].queryexpr, JoinType: yyDollar[2].token, Condition: yyDollar[5].queryexpr} } - case 394: + case 395: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2169 +//line lib/parser/parser.y:2175 { yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[5].queryexpr, JoinType: yyDollar[3].token, Direction: yyDollar[2].token, Condition: yyDollar[6].queryexpr} } - case 395: + case 396: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2173 +//line lib/parser/parser.y:2179 { yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[5].queryexpr, JoinType: yyDollar[3].token, Natural: yyDollar[2].token} } - case 396: + case 397: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2177 +//line lib/parser/parser.y:2183 { yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[6].queryexpr, JoinType: yyDollar[4].token, Direction: yyDollar[3].token, Natural: yyDollar[2].token} } - case 397: + case 398: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2181 +//line lib/parser/parser.y:2187 { yyDollar[5].table.Lateral = yyDollar[4].token yyDollar[5].table.BaseExpr = NewBaseExpr(yyDollar[4].token) yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[5].table, JoinType: yyDollar[2].token, Condition: nil} } - case 398: + case 399: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2187 +//line lib/parser/parser.y:2193 { yyDollar[5].table.Lateral = yyDollar[4].token yyDollar[5].table.BaseExpr = NewBaseExpr(yyDollar[4].token) yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[5].table, JoinType: yyDollar[2].token, Condition: yyDollar[6].queryexpr} } - case 399: + case 400: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:2193 +//line lib/parser/parser.y:2199 { yyDollar[6].table.Lateral = yyDollar[5].token yyDollar[6].table.BaseExpr = NewBaseExpr(yyDollar[5].token) yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[6].table, JoinType: yyDollar[3].token, Direction: yyDollar[2].token, Condition: yyDollar[7].queryexpr} } - case 400: + case 401: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2199 +//line lib/parser/parser.y:2205 { yyDollar[6].table.Lateral = yyDollar[5].token yyDollar[6].table.BaseExpr = NewBaseExpr(yyDollar[5].token) yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[6].table, JoinType: yyDollar[3].token, Natural: yyDollar[2].token} } - case 401: + case 402: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:2205 +//line lib/parser/parser.y:2211 { yyDollar[7].table.Lateral = yyDollar[6].token yyDollar[7].table.BaseExpr = NewBaseExpr(yyDollar[6].token) yyVAL.queryexpr = Join{Table: yyDollar[1].queryexpr, JoinTable: yyDollar[7].table, JoinType: yyDollar[4].token, Direction: yyDollar[3].token, Natural: yyDollar[2].token} } - case 402: + case 403: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2213 +//line lib/parser/parser.y:2219 { yyVAL.queryexpr = JoinCondition{On: yyDollar[2].queryexpr} } - case 403: + case 404: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2217 +//line lib/parser/parser.y:2223 { yyVAL.queryexpr = JoinCondition{Using: yyDollar[3].queryexprs} } - case 404: + case 405: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2223 +//line lib/parser/parser.y:2229 { yyVAL.queryexpr = Field{Object: yyDollar[1].queryexpr} } - case 405: + case 406: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2227 +//line lib/parser/parser.y:2233 { yyVAL.queryexpr = Field{Object: yyDollar[1].queryexpr, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 406: + case 407: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2231 +//line lib/parser/parser.y:2237 { yyVAL.queryexpr = Field{Object: yyDollar[1].queryexpr} } - case 407: + case 408: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2235 +//line lib/parser/parser.y:2241 { yyVAL.queryexpr = Field{Object: FieldReference{BaseExpr: yyDollar[1].identifier.BaseExpr, View: yyDollar[1].identifier, Column: yyDollar[3].queryexpr}} } - case 408: + case 409: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2241 +//line lib/parser/parser.y:2247 { yyVAL.queryexpr = CaseExpr{Value: yyDollar[2].queryexpr, When: yyDollar[3].queryexprs, Else: yyDollar[4].queryexpr} } - case 409: + case 410: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2247 +//line lib/parser/parser.y:2253 { yyVAL.queryexpr = nil } - case 410: + case 411: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2251 +//line lib/parser/parser.y:2257 { yyVAL.queryexpr = yyDollar[1].queryexpr } - case 411: + case 412: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2257 +//line lib/parser/parser.y:2263 { yyVAL.queryexprs = []QueryExpression{CaseExprWhen{Condition: yyDollar[2].queryexpr, Result: yyDollar[4].queryexpr}} } - case 412: + case 413: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2261 +//line lib/parser/parser.y:2267 { yyVAL.queryexprs = append([]QueryExpression{CaseExprWhen{Condition: yyDollar[2].queryexpr, Result: yyDollar[4].queryexpr}}, yyDollar[5].queryexprs...) } - case 413: + case 414: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2267 +//line lib/parser/parser.y:2273 { yyVAL.queryexpr = nil } - case 414: + case 415: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2271 +//line lib/parser/parser.y:2277 { yyVAL.queryexpr = CaseExprElse{Result: yyDollar[2].queryexpr} } - case 415: + case 416: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2277 +//line lib/parser/parser.y:2283 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 416: + case 417: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2281 +//line lib/parser/parser.y:2287 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 417: + case 418: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2287 +//line lib/parser/parser.y:2293 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 418: + case 419: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2291 +//line lib/parser/parser.y:2297 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 419: + case 420: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2297 +//line lib/parser/parser.y:2303 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 420: + case 421: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2301 +//line lib/parser/parser.y:2307 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 421: + case 422: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2307 +//line lib/parser/parser.y:2313 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 422: + case 423: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2311 +//line lib/parser/parser.y:2317 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 423: + case 424: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2317 +//line lib/parser/parser.y:2323 { yyVAL.queryexprs = []QueryExpression{Table{Object: yyDollar[1].queryexpr}} } - case 424: + case 425: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2321 +//line lib/parser/parser.y:2327 { yyVAL.queryexprs = append([]QueryExpression{Table{Object: yyDollar[1].queryexpr}}, yyDollar[3].queryexprs...) } - case 425: + case 426: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2327 +//line lib/parser/parser.y:2333 { yyVAL.queryexprs = []QueryExpression{Table{Object: yyDollar[1].queryexpr}} } - case 426: + case 427: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2331 +//line lib/parser/parser.y:2337 { yyVAL.queryexprs = append([]QueryExpression{Table{Object: yyDollar[1].queryexpr}}, yyDollar[3].queryexprs...) } - case 427: + case 428: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2337 +//line lib/parser/parser.y:2343 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].identifier} } - case 428: + case 429: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2341 +//line lib/parser/parser.y:2347 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].identifier}, yyDollar[3].queryexprs...) } - case 429: + case 430: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2347 +//line lib/parser/parser.y:2353 { yyVAL.queryexprs = []QueryExpression{yyDollar[1].queryexpr} } - case 430: + case 431: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2351 +//line lib/parser/parser.y:2357 { yyVAL.queryexprs = append([]QueryExpression{yyDollar[1].queryexpr}, yyDollar[3].queryexprs...) } - case 431: + case 432: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2357 +//line lib/parser/parser.y:2363 { yyVAL.expression = InsertQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, ValuesList: yyDollar[6].queryexprs} } - case 432: + case 433: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:2361 +//line lib/parser/parser.y:2367 { yyVAL.expression = InsertQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Fields: yyDollar[6].queryexprs, ValuesList: yyDollar[9].queryexprs} } - case 433: + case 434: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2365 +//line lib/parser/parser.y:2371 { yyVAL.expression = InsertQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Query: yyDollar[5].queryexpr.(SelectQuery)} } - case 434: + case 435: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:2369 +//line lib/parser/parser.y:2375 { yyVAL.expression = InsertQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Fields: yyDollar[6].queryexprs, Query: yyDollar[8].queryexpr.(SelectQuery)} } - case 435: + case 436: yyDollar = yyS[yypt-7 : yypt+1] -//line parser.y:2375 +//line lib/parser/parser.y:2381 { yyVAL.expression = UpdateQuery{WithClause: yyDollar[1].queryexpr, Tables: yyDollar[3].queryexprs, SetList: yyDollar[5].updatesets, FromClause: yyDollar[6].queryexpr, WhereClause: yyDollar[7].queryexpr} } - case 436: + case 437: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2381 +//line lib/parser/parser.y:2387 { yyVAL.updateset = UpdateSet{Field: yyDollar[1].queryexpr, Value: yyDollar[3].queryexpr} } - case 437: + case 438: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2387 +//line lib/parser/parser.y:2393 { yyVAL.updatesets = []UpdateSet{yyDollar[1].updateset} } - case 438: + case 439: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2391 +//line lib/parser/parser.y:2397 { yyVAL.updatesets = append([]UpdateSet{yyDollar[1].updateset}, yyDollar[3].updatesets...) } - case 439: + case 440: yyDollar = yyS[yypt-10 : yypt+1] -//line parser.y:2397 +//line lib/parser/parser.y:2403 { yyVAL.expression = ReplaceQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Keys: yyDollar[7].queryexprs, ValuesList: yyDollar[10].queryexprs} } - case 440: + case 441: yyDollar = yyS[yypt-13 : yypt+1] -//line parser.y:2401 +//line lib/parser/parser.y:2407 { yyVAL.expression = ReplaceQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Fields: yyDollar[6].queryexprs, Keys: yyDollar[10].queryexprs, ValuesList: yyDollar[13].queryexprs} } - case 441: + case 442: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:2405 +//line lib/parser/parser.y:2411 { yyVAL.expression = ReplaceQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Keys: yyDollar[7].queryexprs, Query: yyDollar[9].queryexpr.(SelectQuery)} } - case 442: + case 443: yyDollar = yyS[yypt-12 : yypt+1] -//line parser.y:2409 +//line lib/parser/parser.y:2415 { yyVAL.expression = ReplaceQuery{WithClause: yyDollar[1].queryexpr, Table: Table{Object: yyDollar[4].queryexpr}, Fields: yyDollar[6].queryexprs, Keys: yyDollar[10].queryexprs, Query: yyDollar[12].queryexpr.(SelectQuery)} } - case 443: + case 444: yyDollar = yyS[yypt-9 : yypt+1] -//line parser.y:2413 +//line lib/parser/parser.y:2419 { yyVAL.expression = ReplaceQuery{Table: Table{Object: yyDollar[3].queryexpr}, Keys: yyDollar[6].queryexprs, ValuesList: yyDollar[9].queryexprs} } - case 444: + case 445: yyDollar = yyS[yypt-12 : yypt+1] -//line parser.y:2417 +//line lib/parser/parser.y:2423 { yyVAL.expression = ReplaceQuery{Table: Table{Object: yyDollar[3].queryexpr}, Fields: yyDollar[5].queryexprs, Keys: yyDollar[9].queryexprs, ValuesList: yyDollar[12].queryexprs} } - case 445: + case 446: yyDollar = yyS[yypt-8 : yypt+1] -//line parser.y:2421 +//line lib/parser/parser.y:2427 { yyVAL.expression = ReplaceQuery{Table: Table{Object: yyDollar[3].queryexpr}, Keys: yyDollar[6].queryexprs, Query: yyDollar[8].queryexpr.(SelectQuery)} } - case 446: + case 447: yyDollar = yyS[yypt-11 : yypt+1] -//line parser.y:2425 +//line lib/parser/parser.y:2431 { yyVAL.expression = ReplaceQuery{Table: Table{Object: yyDollar[3].queryexpr}, Fields: yyDollar[5].queryexprs, Keys: yyDollar[9].queryexprs, Query: yyDollar[11].queryexpr.(SelectQuery)} } - case 447: + case 448: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2431 +//line lib/parser/parser.y:2437 { yyVAL.expression = DeleteQuery{BaseExpr: NewBaseExpr(yyDollar[2].token), WithClause: yyDollar[1].queryexpr, FromClause: FromClause{Tables: yyDollar[4].queryexprs}, WhereClause: yyDollar[5].queryexpr} } - case 448: + case 449: yyDollar = yyS[yypt-6 : yypt+1] -//line parser.y:2435 +//line lib/parser/parser.y:2441 { yyVAL.expression = DeleteQuery{BaseExpr: NewBaseExpr(yyDollar[2].token), WithClause: yyDollar[1].queryexpr, Tables: yyDollar[3].queryexprs, FromClause: FromClause{Tables: yyDollar[5].queryexprs}, WhereClause: yyDollar[6].queryexpr} } - case 449: + case 450: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2441 +//line lib/parser/parser.y:2447 { yyVAL.elseif = []ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 450: + case 451: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2445 +//line lib/parser/parser.y:2451 { yyVAL.elseif = append([]ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].elseif...) } - case 451: + case 452: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2451 +//line lib/parser/parser.y:2457 { yyVAL.elseexpr = Else{} } - case 452: + case 453: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2455 +//line lib/parser/parser.y:2461 { yyVAL.elseexpr = Else{Statements: yyDollar[2].program} } - case 453: + case 454: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2461 +//line lib/parser/parser.y:2467 { yyVAL.elseif = []ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 454: + case 455: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2465 +//line lib/parser/parser.y:2471 { yyVAL.elseif = append([]ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].elseif...) } - case 455: + case 456: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2471 +//line lib/parser/parser.y:2477 { yyVAL.elseexpr = Else{} } - case 456: + case 457: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2475 +//line lib/parser/parser.y:2481 { yyVAL.elseexpr = Else{Statements: yyDollar[2].program} } - case 457: + case 458: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2481 +//line lib/parser/parser.y:2487 { yyVAL.elseif = []ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 458: + case 459: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2485 +//line lib/parser/parser.y:2491 { yyVAL.elseif = append([]ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].elseif...) } - case 459: + case 460: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2491 +//line lib/parser/parser.y:2497 { yyVAL.elseexpr = Else{} } - case 460: + case 461: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2495 +//line lib/parser/parser.y:2501 { yyVAL.elseexpr = Else{Statements: yyDollar[2].program} } - case 461: + case 462: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2501 +//line lib/parser/parser.y:2507 { yyVAL.elseif = []ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 462: + case 463: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2505 +//line lib/parser/parser.y:2511 { yyVAL.elseif = append([]ElseIf{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].elseif...) } - case 463: + case 464: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2511 +//line lib/parser/parser.y:2517 { yyVAL.elseexpr = Else{} } - case 464: + case 465: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2515 +//line lib/parser/parser.y:2521 { yyVAL.elseexpr = Else{Statements: yyDollar[2].program} } - case 465: + case 466: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2521 +//line lib/parser/parser.y:2527 { yyVAL.casewhen = []CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 466: + case 467: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2525 +//line lib/parser/parser.y:2531 { yyVAL.casewhen = append([]CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].casewhen...) } - case 467: + case 468: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2531 +//line lib/parser/parser.y:2537 { yyVAL.caseelse = CaseElse{} } - case 468: + case 469: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2535 +//line lib/parser/parser.y:2541 { yyVAL.caseelse = CaseElse{Statements: yyDollar[2].program} } - case 469: + case 470: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2541 +//line lib/parser/parser.y:2547 { yyVAL.casewhen = []CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 470: + case 471: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2545 +//line lib/parser/parser.y:2551 { yyVAL.casewhen = append([]CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].casewhen...) } - case 471: + case 472: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2551 +//line lib/parser/parser.y:2557 { yyVAL.caseelse = CaseElse{} } - case 472: + case 473: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2555 +//line lib/parser/parser.y:2561 { yyVAL.caseelse = CaseElse{Statements: yyDollar[2].program} } - case 473: + case 474: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2561 +//line lib/parser/parser.y:2567 { yyVAL.casewhen = []CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 474: + case 475: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2565 +//line lib/parser/parser.y:2571 { yyVAL.casewhen = append([]CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].casewhen...) } - case 475: + case 476: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2571 +//line lib/parser/parser.y:2577 { yyVAL.caseelse = CaseElse{} } - case 476: + case 477: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2575 +//line lib/parser/parser.y:2581 { yyVAL.caseelse = CaseElse{Statements: yyDollar[2].program} } - case 477: + case 478: yyDollar = yyS[yypt-4 : yypt+1] -//line parser.y:2581 +//line lib/parser/parser.y:2587 { yyVAL.casewhen = []CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}} } - case 478: + case 479: yyDollar = yyS[yypt-5 : yypt+1] -//line parser.y:2585 +//line lib/parser/parser.y:2591 { yyVAL.casewhen = append([]CaseWhen{{Condition: yyDollar[2].queryexpr, Statements: yyDollar[4].program}}, yyDollar[5].casewhen...) } - case 479: + case 480: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2591 +//line lib/parser/parser.y:2597 { yyVAL.caseelse = CaseElse{} } - case 480: + case 481: yyDollar = yyS[yypt-2 : yypt+1] -//line parser.y:2595 +//line lib/parser/parser.y:2601 { yyVAL.caseelse = CaseElse{Statements: yyDollar[2].program} } - case 481: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2601 - { - yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} - } case 482: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2605 +//line lib/parser/parser.y:2607 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 483: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2609 +//line lib/parser/parser.y:2611 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 484: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2613 +//line lib/parser/parser.y:2615 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 485: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2617 +//line lib/parser/parser.y:2619 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 486: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2621 +//line lib/parser/parser.y:2623 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 487: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2625 +//line lib/parser/parser.y:2627 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 488: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2629 +//line lib/parser/parser.y:2631 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 489: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2633 +//line lib/parser/parser.y:2635 { yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 490: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2639 +//line lib/parser/parser.y:2639 { - yyVAL.variable = Variable{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} + yyVAL.identifier = Identifier{BaseExpr: NewBaseExpr(yyDollar[1].token), Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 491: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2645 +//line lib/parser/parser.y:2645 { - yyVAL.variables = []Variable{yyDollar[1].variable} + yyVAL.variable = Variable{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} } case 492: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2651 + { + yyVAL.variables = []Variable{yyDollar[1].variable} + } + case 493: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2649 +//line lib/parser/parser.y:2655 { yyVAL.variables = append([]Variable{yyDollar[1].variable}, yyDollar[3].variables...) } - case 493: + case 494: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2655 +//line lib/parser/parser.y:2661 { yyVAL.queryexpr = VariableSubstitution{Variable: yyDollar[1].variable, Value: yyDollar[3].queryexpr} } - case 494: + case 495: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2661 +//line lib/parser/parser.y:2667 { yyVAL.varassign = VariableAssignment{Variable: yyDollar[1].variable} } - case 495: + case 496: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2665 +//line lib/parser/parser.y:2671 { yyVAL.varassign = VariableAssignment{Variable: yyDollar[1].variable, Value: yyDollar[3].queryexpr} } - case 496: + case 497: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2671 +//line lib/parser/parser.y:2677 { yyVAL.varassigns = []VariableAssignment{yyDollar[1].varassign} } - case 497: + case 498: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2675 +//line lib/parser/parser.y:2681 { yyVAL.varassigns = append([]VariableAssignment{yyDollar[1].varassign}, yyDollar[3].varassigns...) } - case 498: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2681 - { - yyVAL.envvar = EnvironmentVariable{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} - } case 499: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2687 +//line lib/parser/parser.y:2687 { - yyVAL.queryexpr = RuntimeInformation{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} + yyVAL.envvar = EnvironmentVariable{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } case 500: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2693 +//line lib/parser/parser.y:2693 { - yyVAL.flag = Flag{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} + yyVAL.queryexpr = RuntimeInformation{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} } case 501: - yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2699 + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2699 { - yyVAL.token = Token{} + items := strings.Split(yyDollar[1].token.Literal, ConstantDelimiter) + space := "" + if 0 < len(items) { + space = items[0] + } + name := "" + if 1 < len(items) { + name = items[1] + } + + yyVAL.queryexpr = Constant{BaseExpr: NewBaseExpr(yyDollar[1].token), Space: space, Name: name} } case 502: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2703 +//line lib/parser/parser.y:2715 { - yyVAL.token = yyDollar[1].token + yyVAL.flag = Flag{BaseExpr: NewBaseExpr(yyDollar[1].token), Name: yyDollar[1].token.Literal} } case 503: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2709 +//line lib/parser/parser.y:2721 { yyVAL.token = Token{} } case 504: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2713 +//line lib/parser/parser.y:2725 { yyVAL.token = yyDollar[1].token } case 505: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2719 +//line lib/parser/parser.y:2731 { yyVAL.token = Token{} } case 506: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2723 +//line lib/parser/parser.y:2735 { yyVAL.token = yyDollar[1].token } case 507: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2729 +//line lib/parser/parser.y:2741 { yyVAL.token = Token{} } case 508: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2733 +//line lib/parser/parser.y:2745 { yyVAL.token = yyDollar[1].token } case 509: - yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2739 + yyDollar = yyS[yypt-0 : yypt+1] +//line lib/parser/parser.y:2751 { - yyVAL.token = yyDollar[1].token + yyVAL.token = Token{} } case 510: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2743 +//line lib/parser/parser.y:2755 { yyVAL.token = yyDollar[1].token } case 511: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2747 +//line lib/parser/parser.y:2761 { yyVAL.token = yyDollar[1].token } case 512: - yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2753 + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2765 { - yyVAL.token = Token{} + yyVAL.token = yyDollar[1].token } case 513: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2757 +//line lib/parser/parser.y:2769 { yyVAL.token = yyDollar[1].token } case 514: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2763 +//line lib/parser/parser.y:2775 { yyVAL.token = Token{} } case 515: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2767 +//line lib/parser/parser.y:2779 { yyVAL.token = yyDollar[1].token } case 516: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2773 +//line lib/parser/parser.y:2785 { yyVAL.token = Token{} } case 517: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2777 +//line lib/parser/parser.y:2789 { yyVAL.token = yyDollar[1].token } case 518: + yyDollar = yyS[yypt-0 : yypt+1] +//line lib/parser/parser.y:2795 + { + yyVAL.token = Token{} + } + case 519: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2783 +//line lib/parser/parser.y:2799 { yyVAL.token = yyDollar[1].token } - case 519: + case 520: yyDollar = yyS[yypt-1 : yypt+1] -//line parser.y:2787 +//line lib/parser/parser.y:2805 + { + yyVAL.token = yyDollar[1].token + } + case 521: + yyDollar = yyS[yypt-1 : yypt+1] +//line lib/parser/parser.y:2809 { yyDollar[1].token.Token = COMPARISON_OP yyVAL.token = yyDollar[1].token } - case 520: + case 522: yyDollar = yyS[yypt-0 : yypt+1] -//line parser.y:2794 +//line lib/parser/parser.y:2816 { yyVAL.bool = false } - case 521: + case 523: yyDollar = yyS[yypt-3 : yypt+1] -//line parser.y:2798 +//line lib/parser/parser.y:2820 { yyVAL.bool = true } diff --git a/lib/parser/parser.y b/lib/parser/parser.y index 8e95275..7a1037c 100644 --- a/lib/parser/parser.y +++ b/lib/parser/parser.y @@ -3,6 +3,7 @@ package parser import ( "strconv" + "strings" "github.com/mithrandie/csvq/lib/value" ) @@ -187,6 +188,7 @@ import ( %type variable_assignments %type environment_variable %type runtime_information +%type constant %type flag %type distinct %type negation @@ -200,7 +202,7 @@ import ( %type if_not_exists %token IDENTIFIER STRING INTEGER FLOAT BOOLEAN TERNARY DATETIME -%token VARIABLE FLAG ENVIRONMENT_VARIABLE RUNTIME_INFORMATION EXTERNAL_COMMAND PLACEHOLDER +%token VARIABLE FLAG ENVIRONMENT_VARIABLE RUNTIME_INFORMATION EXTERNAL_COMMAND PLACEHOLDER CONSTANT %token SELECT FROM UPDATE SET UNSET DELETE WHERE INSERT INTO VALUES REPLACE AS DUAL STDIN %token RECURSIVE %token CREATE ADD DROP ALTER TABLE FIRST LAST AFTER BEFORE DEFAULT RENAME TO VIEW @@ -1506,6 +1508,10 @@ substantial_value { $$ = $1 } + | constant + { + $$ = $1 + } | flag { $$ = $1 @@ -2688,6 +2694,22 @@ runtime_information $$ = RuntimeInformation{BaseExpr: NewBaseExpr($1), Name: $1.Literal} } +constant + : CONSTANT + { + items := strings.Split($1.Literal, ConstantDelimiter) + space := "" + if 0 < len(items) { + space = items[0] + } + name := "" + if 1 < len(items) { + name = items[1] + } + + $$ = Constant{BaseExpr: NewBaseExpr($1), Space: space, Name: name} + } + flag : FLAG { diff --git a/lib/parser/parser_test.go b/lib/parser/parser_test.go index d5411c6..e0fe927 100644 --- a/lib/parser/parser_test.go +++ b/lib/parser/parser_test.go @@ -6412,6 +6412,25 @@ var parseTests = []struct { }}, }, }, + { + Input: "select math::pi", + Output: []Statement{ + SelectQuery{SelectEntity: SelectEntity{ + SelectClause: SelectClause{ + BaseExpr: &BaseExpr{line: 1, char: 1}, + Fields: []QueryExpression{ + Field{ + Object: Constant{ + BaseExpr: &BaseExpr{line: 1, char: 8}, + Space: "math", + Name: "pi", + }, + }, + }, + }, + }}, + }, + }, { Input: "select @@flag", Output: []Statement{ diff --git a/lib/parser/scanner.go b/lib/parser/scanner.go index a3ecf65..de73e9f 100644 --- a/lib/parser/scanner.go +++ b/lib/parser/scanner.go @@ -35,9 +35,12 @@ const ( BeginExpression = '{' EndExpression = '}' + + ConstantSign = ':' ) var errTokenIsNotKeyword = errors.New("token is not keyword") +var errInvalidConstantSyntax = errors.New("invalid constant syntax") var comparisonOperators = []string{ ">", @@ -89,6 +92,8 @@ var functionsWithIgnoreNulls = []string{ "LEAD", } +var ConstantDelimiter = string(ConstantSign) + string(ConstantSign) + func TokenLiteral(token int) string { if TokenFrom <= token && token <= TokenTo { return yyToknames[token-TokenFrom+3] @@ -239,7 +244,17 @@ func (s *Scanner) Scan() (Token, error) { } else if s.isFunctionsWithIgnoreNulls(literal) { token = FUNCTION_WITH_INS } else { - token = IDENTIFIER + if s.peek() == ':' { + err = s.scanConstant() + literal = s.literal.String() + if err != nil { + token = Uncategorized + } else { + token = CONSTANT + } + } else { + token = IDENTIFIER + } } case s.isOperatorRune(ch): s.scanOperator(ch) @@ -351,6 +366,22 @@ func (s *Scanner) scanIdentifier(head rune) { } } +func (s *Scanner) scanConstant() error { + s.literal.WriteRune(s.next()) + if s.peek() != ':' { + return errInvalidConstantSyntax + } + s.literal.WriteRune(s.next()) + if !s.isIdentRune(s.peek()) { + return errInvalidConstantSyntax + } + s.literal.WriteRune(s.next()) + for s.isIdentRune(s.peek()) { + s.literal.WriteRune(s.next()) + } + return nil +} + func (s *Scanner) isIdentRune(ch rune) bool { return ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) } diff --git a/lib/parser/scanner_test.go b/lib/parser/scanner_test.go index fbb3b14..f30a544 100644 --- a/lib/parser/scanner_test.go +++ b/lib/parser/scanner_test.go @@ -210,6 +210,26 @@ var scanTests = []struct { }, }, }, + { + Name: "Constant", + Input: "SPACE::NAME", + Output: []scanResult{ + { + Token: CONSTANT, + Literal: "SPACE::NAME", + }, + }, + }, + { + Name: "Constant Syntax Error", + Input: "SPACE:Name", + Error: "invalid constant syntax", + }, + { + Name: "Constant Syntax Error", + Input: "SPACE::+", + Error: "invalid constant syntax", + }, { Name: "EqualSign", Input: "=", diff --git a/lib/query/error.go b/lib/query/error.go index b6d0f28..003558c 100644 --- a/lib/query/error.go +++ b/lib/query/error.go @@ -38,6 +38,7 @@ const ( ErrMsgNotAllowedAnalyticFunction = "analytic function %s is only available in select clause or order by clause" ErrMsgUndeclaredVariable = "variable %s is undeclared" ErrMsgVariableRedeclared = "variable %s is redeclared" + ErrMsgUndefinedConstant = "constant %s is not defined" ErrMsgFunctionNotExist = "function %s does not exist" ErrMsgFunctionArgumentsLength = "function %s takes %s" ErrMsgFunctionInvalidArgument = "%s for function %s" @@ -523,6 +524,16 @@ func NewVariableRedeclaredError(expr parser.Variable) error { } } +type UndefinedConstantError struct { + *BaseError +} + +func NewUndefinedConstantError(expr parser.Constant) error { + return &UndefinedConstantError{ + NewBaseError(expr, fmt.Sprintf(ErrMsgUndefinedConstant, expr), ReturnCodeApplicationError, ErrorUndefinedConstant), + } +} + type FunctionNotExistError struct { *BaseError } diff --git a/lib/query/error_code.go b/lib/query/error_code.go index a2eecbb..e2bb993 100644 --- a/lib/query/error_code.go +++ b/lib/query/error_code.go @@ -24,6 +24,7 @@ const ( ErrorNotAllowedAnalyticFunction = 10202 ErrorUndeclaredVariable = 10301 ErrorVariableRedeclared = 10302 + ErrorUndefinedConstant = 10321 ErrorFunctionNotExist = 10401 ErrorFunctionArgumentsLength = 10402 ErrorFunctionInvalidArgument = 10403 diff --git a/lib/query/eval.go b/lib/query/eval.go index 3f923de..7ab2f96 100644 --- a/lib/query/eval.go +++ b/lib/query/eval.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/constant" "github.com/mithrandie/csvq/lib/excmd" "github.com/mithrandie/csvq/lib/json" "github.com/mithrandie/csvq/lib/parser" @@ -74,6 +75,11 @@ func Evaluate(ctx context.Context, scope *ReferenceScope, expr parser.QueryExpre val = value.NewString(os.Getenv(expr.(parser.EnvironmentVariable).Name)) case parser.RuntimeInformation: val, err = GetRuntimeInformation(scope.Tx, expr.(parser.RuntimeInformation)) + case parser.Constant: + val, err = constant.Get(expr.(parser.Constant)) + if err != nil { + err = NewUndefinedConstantError(expr.(parser.Constant)) + } case parser.Flag: if v, ok := scope.Tx.GetFlag(expr.(parser.Flag).Name); ok { val = v diff --git a/lib/query/eval_test.go b/lib/query/eval_test.go index 0ab653c..18efd4e 100644 --- a/lib/query/eval_test.go +++ b/lib/query/eval_test.go @@ -2,6 +2,7 @@ package query import ( "context" + "math" "os" "reflect" "sync" @@ -3990,6 +3991,22 @@ var evaluateTests = []struct { }, Result: value.NewString("v1.0.0"), }, + { + Name: "Constant", + Expr: parser.Constant{ + Space: "math", + Name: "pi", + }, + Result: value.NewFloat(math.Pi), + }, + { + Name: "Constant Undefined Error", + Expr: parser.Constant{ + Space: "math", + Name: "undefined", + }, + Error: "constant MATH::UNDEFINED is not defined", + }, { Name: "Flag", Expr: parser.Flag{ diff --git a/lib/query/field_analyzer.go b/lib/query/field_analyzer.go index 4f60253..b07317c 100644 --- a/lib/query/field_analyzer.go +++ b/lib/query/field_analyzer.go @@ -16,7 +16,7 @@ func HasAggregateFunction(expr parser.QueryExpression, scope *ReferenceScope) (b return HasAggregateFunctionInList(e.Args, scope) case parser.PrimitiveType, parser.FieldReference, parser.ColumnNumber, parser.Subquery, parser.Exists, - parser.Variable, parser.EnvironmentVariable, parser.RuntimeInformation, parser.Flag, + parser.Variable, parser.EnvironmentVariable, parser.RuntimeInformation, parser.Constant, parser.Flag, parser.CursorStatus, parser.CursorAttrebute, parser.Placeholder, parser.AllColumns: return false, nil @@ -171,7 +171,7 @@ func SearchAnalyticFunctions(expr parser.QueryExpression) ([]parser.AnalyticFunc return appendAnalyticFunctionToListIfNotExist(childFuncs, []parser.AnalyticFunction{e}), nil case parser.PrimitiveType, parser.FieldReference, parser.ColumnNumber, parser.Subquery, parser.Exists, - parser.Variable, parser.EnvironmentVariable, parser.RuntimeInformation, parser.Flag, + parser.Variable, parser.EnvironmentVariable, parser.RuntimeInformation, parser.Constant, parser.Flag, parser.CursorStatus, parser.CursorAttrebute, parser.Placeholder, parser.AllColumns: return nil, nil diff --git a/lib/syntax/syntax.go b/lib/syntax/syntax.go index 9bb020e..17a9f95 100644 --- a/lib/syntax/syntax.go +++ b/lib/syntax/syntax.go @@ -953,6 +953,13 @@ var CsvqSyntax = []Expression{ Values: []Element{Link("Runtime Information")}, }, }, + { + Name: "system_defined_constant", + Description: Description{ + Template: "cf. %s", + Values: []Element{Link("System Defined Constant")}, + }, + }, { Name: "flag", Description: Description{ @@ -1188,6 +1195,33 @@ var CsvqSyntax = []Expression{ }, }, }, + { + Label: "System Defined Constant", + Description: Description{ + Template: "" + + "```\n" + + " +----------+------------------+---------+\n" + + " | Category | Name | Type |\n" + + " +----------+------------------+---------+\n" + + " | MATH | E | float |\n" + + " | | PI | float |\n" + + " | | PHI | float |\n" + + " | | SQRT2 | float |\n" + + " | | SQRTE | float |\n" + + " | | SQRTPI | float |\n" + + " | | SQRTPHI | float |\n" + + " | | LN2 | float |\n" + + " | | LOG2E | float |\n" + + " | | LN10 | float |\n" + + " | | LOG10E | float |\n" + + " | FLOAT | MAX | float |\n" + + " | | SMALLEST_NONZERO | float |\n" + + " | INTEGER | MAX | integer |\n" + + " | | MIN | integer |\n" + + " +----------+------------------+---------+\n" + + "```", + }, + }, { Label: "JSON Query", Description: Description{ @@ -2885,26 +2919,30 @@ var CsvqSyntax = []Expression{ " > A null is represented by a keyword NULL.\n" + "\n" + "%s\n" + - " > A variable is a word starting with “@” and followed by a" + + " > A variable is a word starting with \"@\" and followed by a" + " character string that contains any unicode letters, any digits or" + " Low Lines(U+005F _).\n" + "\n" + "%s\n" + - " > A flag is a word starting with “@@” and followed by a character" + + " > A flag is a word starting with \"@@\" and followed by a character" + " string that contains any unicode letters, any digits or" + " Low Lines(U+005F _). Character case is ignored.\n" + "\n" + "%s\n" + - " > A environment variable is a word starting with “@%%” and followed" + + " > A environment variable is a word starting with \"@%%\" and followed" + " by a character string that contains any unicode letters, any digits" + " or Low Lines(U+005F _). If a environment variable includes other" + " characters, you can use the variable by enclosing" + " in Back Quotes(U+0060 `).\n" + "\n" + "%s\n" + - " > A runtime information is a word starting with “@#” and followed" + + " > A runtime information is a word starting with \"@#\" and followed" + " by a character string that contains any unicode letters, any digits" + - " or Low Lines(U+005F _). Character case is ignored.", + " or Low Lines(U+005F _). Character case is ignored." + + "\n" + + "%s\n" + + " > A system defined constant is a group of words represented by two" + + " words separated by \"::\". Character case is ignored.", Values: []Element{ Identifier("Identifier"), Link("reserved words"), @@ -2918,6 +2956,7 @@ var CsvqSyntax = []Expression{ Flag("Flag"), Variable("Environment Variable"), Variable("Runtime Information"), + Variable("System Defined Constant"), }, }, }, diff --git a/lib/terminal/completer_readline.go b/lib/terminal/completer_readline.go index 450468d..18a007c 100644 --- a/lib/terminal/completer_readline.go +++ b/lib/terminal/completer_readline.go @@ -3,6 +3,7 @@ package terminal import ( + "github.com/mithrandie/csvq/lib/constant" "io/ioutil" "os" "path/filepath" @@ -148,6 +149,8 @@ type Completer struct { aggFuncs []string analyticFuncs []string + constants []string + statementList []string userFuncs []string userAggFuncs []string @@ -209,6 +212,14 @@ func NewCompleter(scope *query.ReferenceScope) *Completer { completer.analyticFuncs = append(completer.analyticFuncs, k) } + completer.constants = make([]string, 0, constant.Count()) + for category, valueMap := range constant.Definition { + for name := range valueMap { + completer.constants = append(completer.constants, category+parser.ConstantDelimiter+name) + } + } + sort.Strings(completer.constants) + completer.tokens = make([]parser.Token, 0, 20) return completer @@ -2209,6 +2220,7 @@ func (c *Completer) SearchValues(line string, origLine string, index int) readli "UNKNOWN", "NULL", ) + list = append(list, c.constants...) for _, s := range list { if strings.HasPrefix(strings.ToUpper(s), searchWord) { diff --git a/lib/terminal/completer_readline_test.go b/lib/terminal/completer_readline_test.go index 2f03d04..633b384 100644 --- a/lib/terminal/completer_readline_test.go +++ b/lib/terminal/completer_readline_test.go @@ -3713,6 +3713,18 @@ var completerSearchValuesTests = []completerTest{ {Name: []rune("@%`ENV2`")}, }, }, + { + Name: "SearchValues Constants", + Line: "i", + OrigLine: "select i", + Index: 8, + Expect: readline.CandidateList{ + {Name: []rune("INTEGER::MAX")}, + {Name: []rune("INTEGER::MIN")}, + {Name: []rune("IS"), AppendSpace: true}, + {Name: []rune("IN"), AppendSpace: true}, + }, + }, { Name: "SearchValues Keyword", Line: "c", From 8d03a3bc858242d02338113c2241fa396f987bb4 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 3 Jul 2022 03:12:25 +0900 Subject: [PATCH 09/17] Fix a bug of devision by zero. --- lib/parser/parser.go | 10 +++++----- lib/parser/parser.y | 10 +++++----- lib/parser/parser_test.go | 6 ++++++ lib/query/arithmetic.go | 19 ++++++++++++++----- lib/query/arithmetic_test.go | 29 ++++++++++++++++++++++++++++- lib/query/error.go | 11 +++++++++++ lib/query/error_code.go | 1 + lib/query/eval.go | 7 ++++++- lib/query/eval_test.go | 9 +++++++++ 9 files changed, 85 insertions(+), 17 deletions(-) diff --git a/lib/parser/parser.go b/lib/parser/parser.go index 2818b7b..d338bd5 100644 --- a/lib/parser/parser.go +++ b/lib/parser/parser.go @@ -4089,31 +4089,31 @@ yydefault: yyDollar = yyS[yypt-3 : yypt+1] //line lib/parser/parser.y:1733 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Arithmetic{BaseExpr: NewBaseExpr(yyDollar[2].token), LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 300: yyDollar = yyS[yypt-3 : yypt+1] //line lib/parser/parser.y:1737 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Arithmetic{BaseExpr: NewBaseExpr(yyDollar[2].token), LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 301: yyDollar = yyS[yypt-3 : yypt+1] //line lib/parser/parser.y:1741 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Arithmetic{BaseExpr: NewBaseExpr(yyDollar[2].token), LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 302: yyDollar = yyS[yypt-3 : yypt+1] //line lib/parser/parser.y:1745 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Arithmetic{BaseExpr: NewBaseExpr(yyDollar[2].token), LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 303: yyDollar = yyS[yypt-3 : yypt+1] //line lib/parser/parser.y:1749 { - yyVAL.queryexpr = Arithmetic{LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} + yyVAL.queryexpr = Arithmetic{BaseExpr: NewBaseExpr(yyDollar[2].token), LHS: yyDollar[1].queryexpr, Operator: yyDollar[2].token, RHS: yyDollar[3].queryexpr} } case 304: yyDollar = yyS[yypt-2 : yypt+1] diff --git a/lib/parser/parser.y b/lib/parser/parser.y index 7a1037c..bf6e3ce 100644 --- a/lib/parser/parser.y +++ b/lib/parser/parser.y @@ -1731,23 +1731,23 @@ comparison arithmetic : value '+' value { - $$ = Arithmetic{LHS: $1, Operator: $2, RHS: $3} + $$ = Arithmetic{BaseExpr: NewBaseExpr($2), LHS: $1, Operator: $2, RHS: $3} } | value '-' value { - $$ = Arithmetic{LHS: $1, Operator: $2, RHS: $3} + $$ = Arithmetic{BaseExpr: NewBaseExpr($2), LHS: $1, Operator: $2, RHS: $3} } | value '*' value { - $$ = Arithmetic{LHS: $1, Operator: $2, RHS: $3} + $$ = Arithmetic{BaseExpr: NewBaseExpr($2), LHS: $1, Operator: $2, RHS: $3} } | value '/' value { - $$ = Arithmetic{LHS: $1, Operator: $2, RHS: $3} + $$ = Arithmetic{BaseExpr: NewBaseExpr($2), LHS: $1, Operator: $2, RHS: $3} } | value '%' value { - $$ = Arithmetic{LHS: $1, Operator: $2, RHS: $3} + $$ = Arithmetic{BaseExpr: NewBaseExpr($2), LHS: $1, Operator: $2, RHS: $3} } | '-' value %prec UMINUS { diff --git a/lib/parser/parser_test.go b/lib/parser/parser_test.go index e0fe927..8d044df 100644 --- a/lib/parser/parser_test.go +++ b/lib/parser/parser_test.go @@ -2075,6 +2075,7 @@ var parseTests = []struct { BaseExpr: &BaseExpr{line: 1, char: 1}, Fields: []QueryExpression{ Field{Object: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 16}, LHS: FieldReference{BaseExpr: &BaseExpr{line: 1, char: 8}, Column: Identifier{BaseExpr: &BaseExpr{line: 1, char: 8}, Literal: "column1"}}, Operator: Token{Token: '+', Literal: "+", Line: 1, Char: 16}, RHS: NewIntegerValueFromString("1"), @@ -2094,6 +2095,7 @@ var parseTests = []struct { BaseExpr: &BaseExpr{line: 1, char: 1}, Fields: []QueryExpression{ Field{Object: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 16}, LHS: FieldReference{BaseExpr: &BaseExpr{line: 1, char: 8}, Column: Identifier{BaseExpr: &BaseExpr{line: 1, char: 8}, Literal: "column1"}}, Operator: Token{Token: '-', Literal: "-", Line: 1, Char: 16}, RHS: NewIntegerValueFromString("1"), @@ -2113,6 +2115,7 @@ var parseTests = []struct { BaseExpr: &BaseExpr{line: 1, char: 1}, Fields: []QueryExpression{ Field{Object: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 16}, LHS: FieldReference{BaseExpr: &BaseExpr{line: 1, char: 8}, Column: Identifier{BaseExpr: &BaseExpr{line: 1, char: 8}, Literal: "column1"}}, Operator: Token{Token: '*', Literal: "*", Line: 1, Char: 16}, RHS: NewIntegerValueFromString("1"), @@ -2132,6 +2135,7 @@ var parseTests = []struct { BaseExpr: &BaseExpr{line: 1, char: 1}, Fields: []QueryExpression{ Field{Object: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 16}, LHS: FieldReference{BaseExpr: &BaseExpr{line: 1, char: 8}, Column: Identifier{BaseExpr: &BaseExpr{line: 1, char: 8}, Literal: "column1"}}, Operator: Token{Token: '/', Literal: "/", Line: 1, Char: 16}, RHS: NewIntegerValueFromString("1"), @@ -2151,6 +2155,7 @@ var parseTests = []struct { BaseExpr: &BaseExpr{line: 1, char: 1}, Fields: []QueryExpression{ Field{Object: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 16}, LHS: FieldReference{BaseExpr: &BaseExpr{line: 1, char: 8}, Column: Identifier{BaseExpr: &BaseExpr{line: 1, char: 8}, Literal: "column1"}}, Operator: Token{Token: '%', Literal: "%", Line: 1, Char: 16}, RHS: NewIntegerValueFromString("1"), @@ -6356,6 +6361,7 @@ var parseTests = []struct { Object: VariableSubstitution{ Variable: Variable{BaseExpr: &BaseExpr{line: 1, char: 8}, Name: "var1"}, Value: Arithmetic{ + BaseExpr: &BaseExpr{line: 1, char: 23}, LHS: Variable{BaseExpr: &BaseExpr{line: 1, char: 17}, Name: "var2"}, Operator: Token{Token: '+', Literal: "+", Line: 1, Char: 23}, RHS: Variable{BaseExpr: &BaseExpr{line: 1, char: 25}, Name: "var3"}, diff --git a/lib/query/arithmetic.go b/lib/query/arithmetic.go index 617ea3c..f656559 100644 --- a/lib/query/arithmetic.go +++ b/lib/query/arithmetic.go @@ -1,12 +1,15 @@ package query import ( + "errors" "math" "github.com/mithrandie/csvq/lib/value" ) -func Calculate(p1 value.Primary, p2 value.Primary, operator int) value.Primary { +var errIntegerDevidedByZero = errors.New("integer devided by zero") + +func Calculate(p1 value.Primary, p2 value.Primary, operator int) (value.Primary, error) { if i1 := value.ToIntegerStrictly(p1); !value.IsNull(i1) { if i2 := value.ToIntegerStrictly(p2); !value.IsNull(i2) { val1 := i1.(*value.Integer).Raw() @@ -26,15 +29,15 @@ func Calculate(p1 value.Primary, p2 value.Primary, operator int) value.Primary { value.Discard(f1) value.Discard(f2) - return calculateFloat(val1, val2, operator) + return calculateFloat(val1, val2, operator), nil } value.Discard(f1) } - return value.NewNull() + return value.NewNull(), nil } -func calculateInteger(i1 int64, i2 int64, operator int) value.Primary { +func calculateInteger(i1 int64, i2 int64, operator int) (value.Primary, error) { var result int64 = 0 switch operator { case '+': @@ -44,12 +47,18 @@ func calculateInteger(i1 int64, i2 int64, operator int) value.Primary { case '*': result = i1 * i2 case '/': + if i2 == 0 { + return nil, errIntegerDevidedByZero + } result = i1 / i2 case '%': + if i2 == 0 { + return nil, errIntegerDevidedByZero + } result = i1 % i2 } - return value.NewInteger(result) + return value.NewInteger(result), nil } func calculateFloat(f1 float64, f2 float64, operator int) value.Primary { diff --git a/lib/query/arithmetic_test.go b/lib/query/arithmetic_test.go index 338a6dc..c96e02c 100644 --- a/lib/query/arithmetic_test.go +++ b/lib/query/arithmetic_test.go @@ -12,6 +12,7 @@ var calculateTests = []struct { RHS value.Primary Operator int Result value.Primary + Error string }{ { LHS: value.NewString("9"), @@ -79,11 +80,37 @@ var calculateTests = []struct { Operator: '%', Result: value.NewFloat(0.5), }, + { + LHS: value.NewString("8"), + RHS: value.NewString("0"), + Operator: '/', + Error: "integer devided by zero", + }, + { + LHS: value.NewString("8"), + RHS: value.NewString("0"), + Operator: '%', + Error: "integer devided by zero", + }, } func TestCalculate(t *testing.T) { for _, v := range calculateTests { - r := Calculate(v.LHS, v.RHS, v.Operator) + r, err := Calculate(v.LHS, v.RHS, v.Operator) + + if err != nil { + if len(v.Error) < 1 { + t.Errorf("unexpected error %q for (%s %s %s)", err, v.LHS, string(rune(v.Operator)), v.RHS) + } else if err.Error() != v.Error { + t.Errorf("error %q, want error %q for (%s %s %s)", err.Error(), v.Error, v.LHS, string(rune(v.Operator)), v.RHS) + } + continue + } + if 0 < len(v.Error) { + t.Errorf("no error, want error %q for (%s %s %s)", v.Error, v.LHS, string(rune(v.Operator)), v.RHS) + continue + } + if !reflect.DeepEqual(r, v.Result) { t.Errorf("result = %s, want %s for (%s %s %s)", r, v.Result, v.LHS, string(rune(v.Operator)), v.RHS) } diff --git a/lib/query/error.go b/lib/query/error.go index 003558c..caf5acf 100644 --- a/lib/query/error.go +++ b/lib/query/error.go @@ -130,6 +130,7 @@ const ( ErrMsgStatementReplaceValueNotSpecified = "replace value for %s is not specified" ErrMsgSelectIntoQueryFieldLengthNotMatch = "select into query should return exactly %s" ErrMsgSelectIntoQueryTooManyRecords = "select into query returns too many records, should return only one record" + ErrMsgIntegerDevidedByZero = "integer divided by zero" ) type Error interface { @@ -1484,6 +1485,16 @@ func NewSelectIntoQueryTooManyRecordsError(query parser.SelectQuery) error { } } +type IntegerDevidedByZeroError struct { + *BaseError +} + +func NewIntegerDevidedByZeroError(expr parser.Arithmetic) error { + return &IntegerDevidedByZeroError{ + NewBaseError(expr, ErrMsgIntegerDevidedByZero, ReturnCodeApplicationError, ErrorIntegerDevidedByZero), + } +} + func searchSelectClause(query parser.SelectQuery) parser.SelectClause { return searchSelectClauseInSelectEntity(query.SelectEntity) } diff --git a/lib/query/error_code.go b/lib/query/error_code.go index e2bb993..fda3b65 100644 --- a/lib/query/error_code.go +++ b/lib/query/error_code.go @@ -111,6 +111,7 @@ const ( ErrorReplaceKeyNotSet = 13901 ErrorSelectIntoQueryFieldLengthNotMatch = 14001 ErrorSelectIntoQueryTooManyRecords = 14002 + ErrorIntegerDevidedByZero = 30000 //Incorrect Command Usage ErrorIncorrectCommandUsage = 90020 diff --git a/lib/query/eval.go b/lib/query/eval.go index 7ab2f96..ad227e2 100644 --- a/lib/query/eval.go +++ b/lib/query/eval.go @@ -202,7 +202,12 @@ func evalArithmetic(ctx context.Context, scope *ReferenceScope, expr parser.Arit return nil, err } - return Calculate(lhs, rhs, expr.Operator.Token), nil + ret, err := Calculate(lhs, rhs, expr.Operator.Token) + if err != nil { + return nil, NewIntegerDevidedByZeroError(expr) + } + + return ret, nil } func evalUnaryArithmetic(ctx context.Context, scope *ReferenceScope, expr parser.UnaryArithmetic) (value.Primary, error) { diff --git a/lib/query/eval_test.go b/lib/query/eval_test.go index 18efd4e..1c90b27 100644 --- a/lib/query/eval_test.go +++ b/lib/query/eval_test.go @@ -282,6 +282,15 @@ var evaluateTests = []struct { }, Error: "field notexist does not exist", }, + { + Name: "Arithmetic Division by Zero Error", + Expr: parser.Arithmetic{ + LHS: parser.NewIntegerValue(1), + RHS: parser.NewIntegerValue(0), + Operator: parser.Token{Token: '/', Literal: "/"}, + }, + Error: "integer divided by zero", + }, { Name: "UnaryArithmetic Integer", Expr: parser.UnaryArithmetic{ From 1db60c7a3f2e4cd9309e94192a2889fe47e0679a Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 3 Jul 2022 03:20:44 +0900 Subject: [PATCH 10/17] Fix comments in auto generated files.. --- lib/json/query_parser.go | 72 ++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/json/query_parser.go b/lib/json/query_parser.go index fa8386b..a62878f 100644 --- a/lib/json/query_parser.go +++ b/lib/json/query_parser.go @@ -1,15 +1,15 @@ -// Code generated by goyacc -p jq -o query_parser.go -v query_parser.output query_parser.y. DO NOT EDIT. +// Code generated by goyacc -p jq -o lib/json/query_parser.go -v lib/json/query_parser.output lib/json/query_parser.y. DO NOT EDIT. -//line query_parser.y:2 +//line lib/json/query_parser.y:2 package json import __yyfmt__ "fmt" -//line query_parser.y:2 +//line lib/json/query_parser.y:2 import "strconv" -//line query_parser.y:7 +//line lib/json/query_parser.y:7 type jqSymType struct { yys int expression QueryExpression @@ -44,7 +44,7 @@ const jqEofCode = 1 const jqErrCode = 2 const jqInitialStackSize = 16 -//line query_parser.y:185 +//line lib/json/query_parser.y:185 func ParseQuery(src string) (QueryExpression, error) { l := new(QueryLexer) @@ -478,197 +478,197 @@ jqdefault: case 1: jqDollar = jqS[jqpt-0 : jqpt+1] -//line query_parser.y:33 +//line lib/json/query_parser.y:33 { jqVAL.expression = nil jqlex.(*QueryLexer).query = jqVAL.expression } case 2: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:38 +//line lib/json/query_parser.y:38 { jqVAL.expression = jqDollar[1].expression jqlex.(*QueryLexer).query = jqVAL.expression } case 3: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:45 +//line lib/json/query_parser.y:45 { jqVAL.expression = jqDollar[1].element } case 4: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:49 +//line lib/json/query_parser.y:49 { jqVAL.expression = jqDollar[1].expression } case 5: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:53 +//line lib/json/query_parser.y:53 { jqVAL.expression = jqDollar[1].expression } case 6: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:57 +//line lib/json/query_parser.y:57 { jqVAL.expression = jqDollar[1].expression } case 7: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:63 +//line lib/json/query_parser.y:63 { jqVAL.element = Element{Label: jqDollar[1].token.Literal} } case 8: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:67 +//line lib/json/query_parser.y:67 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[3].element} } case 9: jqDollar = jqS[jqpt-2 : jqpt+1] -//line query_parser.y:71 +//line lib/json/query_parser.y:71 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[2].expression} } case 10: jqDollar = jqS[jqpt-2 : jqpt+1] -//line query_parser.y:75 +//line lib/json/query_parser.y:75 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[2].expression} } case 11: jqDollar = jqS[jqpt-2 : jqpt+1] -//line query_parser.y:79 +//line lib/json/query_parser.y:79 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[2].expression} } case 12: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:85 +//line lib/json/query_parser.y:85 { jqVAL.element = Element{Label: jqDollar[1].token.Literal} } case 13: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:89 +//line lib/json/query_parser.y:89 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[3].element} } case 14: jqDollar = jqS[jqpt-2 : jqpt+1] -//line query_parser.y:93 +//line lib/json/query_parser.y:93 { jqVAL.element = Element{Label: jqDollar[1].token.Literal, Child: jqDollar[2].expression} } case 15: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:99 +//line lib/json/query_parser.y:99 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i} } case 16: jqDollar = jqS[jqpt-5 : jqpt+1] -//line query_parser.y:104 +//line lib/json/query_parser.y:104 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[5].element} } case 17: jqDollar = jqS[jqpt-4 : jqpt+1] -//line query_parser.y:109 +//line lib/json/query_parser.y:109 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[4].expression} } case 18: jqDollar = jqS[jqpt-4 : jqpt+1] -//line query_parser.y:114 +//line lib/json/query_parser.y:114 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[4].expression} } case 19: jqDollar = jqS[jqpt-4 : jqpt+1] -//line query_parser.y:119 +//line lib/json/query_parser.y:119 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[4].expression} } case 20: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:126 +//line lib/json/query_parser.y:126 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i} } case 21: jqDollar = jqS[jqpt-5 : jqpt+1] -//line query_parser.y:131 +//line lib/json/query_parser.y:131 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[5].element} } case 22: jqDollar = jqS[jqpt-4 : jqpt+1] -//line query_parser.y:136 +//line lib/json/query_parser.y:136 { i, _ := strconv.Atoi(jqDollar[2].token.Literal) jqVAL.expression = ArrayItem{Index: i, Child: jqDollar[4].expression} } case 23: jqDollar = jqS[jqpt-2 : jqpt+1] -//line query_parser.y:143 +//line lib/json/query_parser.y:143 { jqVAL.expression = RowValueExpr{} } case 24: jqDollar = jqS[jqpt-4 : jqpt+1] -//line query_parser.y:147 +//line lib/json/query_parser.y:147 { jqVAL.expression = RowValueExpr{Child: jqDollar[4].element} } case 25: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:151 +//line lib/json/query_parser.y:151 { jqVAL.expression = RowValueExpr{Child: jqDollar[3].expression} } case 26: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:157 +//line lib/json/query_parser.y:157 { jqVAL.expression = TableExpr{Fields: jqDollar[2].fields} } case 27: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:163 +//line lib/json/query_parser.y:163 { jqVAL.field = FieldExpr{Element: jqDollar[1].element} } case 28: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:167 +//line lib/json/query_parser.y:167 { jqVAL.field = FieldExpr{Element: jqDollar[1].element, Alias: jqDollar[3].token.Literal} } case 29: jqDollar = jqS[jqpt-0 : jqpt+1] -//line query_parser.y:173 +//line lib/json/query_parser.y:173 { jqVAL.fields = nil } case 30: jqDollar = jqS[jqpt-1 : jqpt+1] -//line query_parser.y:177 +//line lib/json/query_parser.y:177 { jqVAL.fields = []FieldExpr{jqDollar[1].field} } case 31: jqDollar = jqS[jqpt-3 : jqpt+1] -//line query_parser.y:181 +//line lib/json/query_parser.y:181 { jqVAL.fields = append([]FieldExpr{jqDollar[1].field}, jqDollar[3].fields...) } From 8e37b255caeeefc0280478115b53502b57d4bebf Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 3 Jul 2022 03:23:23 +0900 Subject: [PATCH 11/17] Update the version of github.com/mithrandie/go-text to v1.5.4. --- go.mod | 2 +- go.sum | 4 ++-- lib/json/conversion.go | 2 -- lib/query/encode.go | 11 +++++++++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 5be257e..e719959 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/mithrandie/csvq require ( github.com/mitchellh/go-homedir v1.0.0 github.com/mithrandie/go-file/v2 v2.1.0 - github.com/mithrandie/go-text v1.5.3 + github.com/mithrandie/go-text v1.5.4 github.com/mithrandie/readline-csvq v1.2.0 github.com/mithrandie/ternary v1.1.1 github.com/urfave/cli/v2 v2.10.3 diff --git a/go.sum b/go.sum index 023ffc3..a913515 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnG github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mithrandie/go-file/v2 v2.1.0 h1:XA5Tl+73GXMDvgwSE3Sg0uC5FkLr3hnXs8SpUas0hyg= github.com/mithrandie/go-file/v2 v2.1.0/go.mod h1:9YtTF3Xo59GqC1Pxw6KyGVcM/qubAMlxVsqI/u9r++c= -github.com/mithrandie/go-text v1.5.3 h1:A+/mtgUsr1EsoVKGb4sm8Suho/Biku9Sh2appII4Mo0= -github.com/mithrandie/go-text v1.5.3/go.mod h1:yaVYauF3TLf7LvjGrrQB/mffIkohXTXJpW9zQ206UL8= +github.com/mithrandie/go-text v1.5.4 h1:2LIASku5RuCqxa6O6eOvQwQ0k5FYWP1ID2hk9egYYGc= +github.com/mithrandie/go-text v1.5.4/go.mod h1:yaVYauF3TLf7LvjGrrQB/mffIkohXTXJpW9zQ206UL8= github.com/mithrandie/readline-csvq v1.2.0 h1:5GFbdWFP+2m57Yz+XLtKVIfyH0SjN9du51VT0x9WI40= github.com/mithrandie/readline-csvq v1.2.0/go.mod h1:6Grnfrl8PHC448fV7f8RJNlHeoM+Z3w2QlYW+J9mA2I= github.com/mithrandie/ternary v1.1.1 h1:k/joD6UGVYxHixYmSR8EGgDFNONBMqyD373xT4QRdC4= diff --git a/lib/json/conversion.go b/lib/json/conversion.go index 09c8183..600742a 100644 --- a/lib/json/conversion.go +++ b/lib/json/conversion.go @@ -18,8 +18,6 @@ func ConvertToValue(structure json.Structure) value.Primary { switch structure.(type) { case json.Number: p = value.NewFloat(structure.(json.Number).Raw()) - case json.Float: - p = value.NewFloat(structure.(json.Float).Raw()) case json.Integer: p = value.NewInteger(structure.(json.Integer).Raw()) case json.String: diff --git a/lib/query/encode.go b/lib/query/encode.go index 8a23853..38665ce 100644 --- a/lib/query/encode.go +++ b/lib/query/encode.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "errors" + "fmt" "io" "strconv" "time" @@ -229,7 +230,10 @@ func encodeJson(ctx context.Context, fp io.Writer, view *View, options cmd.Expor } }() - s := e.Encode(data) + s, err := e.Encode(data) + if err != nil { + return NewDataEncodingError(fmt.Sprintf("%s in JSON encoding", err.Error())) + } w := bufio.NewWriter(fp) if _, err = w.WriteString(s); err != nil { @@ -279,7 +283,10 @@ func encodeJsonLines(ctx context.Context, fp io.Writer, view *View, options cmd. if err != nil { return NewDataEncodingError(err.Error()) } - rowStr := e.Encode(rowStrct) + rowStr, err := e.Encode(rowStrct) + if err != nil { + return NewDataEncodingError(fmt.Sprintf("%s in JSON encoding", err.Error())) + } if _, err = w.WriteString(rowStr); err != nil { return NewSystemError(err.Error()) From a4451f58482bd539497f11d20166aad24817d546 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 3 Jul 2022 09:42:37 +0900 Subject: [PATCH 12/17] Handle Inf and NaN. --- docs/_posts/2006-01-02-cast-functions.md | 168 +++++++++++++---------- docs/_posts/2006-01-02-value.md | 106 ++++++++------ docs/sitemap.xml | 4 +- lib/query/arithmetic_test.go | 25 ++++ lib/query/function.go | 28 ++-- lib/query/function_test.go | 37 ++++- lib/query/sort_value.go | 18 +++ lib/query/sort_value_test.go | 85 ++++++++++++ lib/value/comparison.go | 5 + lib/value/comparison_test.go | 63 +++++++++ lib/value/conv.go | 12 +- lib/value/conv_test.go | 19 +++ 12 files changed, 431 insertions(+), 139 deletions(-) diff --git a/docs/_posts/2006-01-02-cast-functions.md b/docs/_posts/2006-01-02-cast-functions.md index 3955529..8424519 100644 --- a/docs/_posts/2006-01-02-cast-functions.md +++ b/docs/_posts/2006-01-02-cast-functions.md @@ -6,14 +6,14 @@ category: reference # Cast Functions -| name | description | -| :- | :- | -| [STRING](#string) | Convert a value to a string | -| [INTEGER](#integer) | Convert a value to an integer | -| [FLOAT](#float) | Convert a value to a float | +| name | description | +|:----------------------|:------------------------------| +| [STRING](#string) | Convert a value to a string | +| [INTEGER](#integer) | Convert a value to an integer | +| [FLOAT](#float) | Convert a value to a float | | [DATETIME](#datetime) | Convert a value to a datetime | -| [BOOLEAN](#boolean) | Convert a value to a boolean | -| [TERNARY](#ternary) | Convert a value to a ternary | +| [BOOLEAN](#boolean) | Convert a value to a boolean | +| [TERNARY](#ternary) | Convert a value to a ternary | ## Definitions @@ -32,14 +32,14 @@ _return_ Convert _value_ to a string. -| value type | description | -| :- | :- | -| Integer | An integer value is converted to a string representing a decimal integer. | -| Float | A float value is converted to a string representing a floating-point decimal. | -| Datetime | A datetime value is converted to a string formatted with RFC3339 with Nano Seconds. | -| Boolean | A boolean value is converted to either 'true' or 'false'. | -| Ternary | A ternaly value is converted to any one string of 'TRUE', 'FALSE' and 'UNKNOWN'. | -| Null | A null value is kept as it is. | +| Type | Value after conversion | +|:---------|:------------------------------------------------| +| Integer | String representing a decimal integer | +| Float | String representing a floating-point decimal | +| Datetime | String formatted with RFC3339 with Nano Seconds | +| Boolean | 'true' or 'false' | +| Ternary | 'TRUE', 'FALSE' and 'UNKNOWN' | +| Null | Null | ### INTEGER @@ -57,14 +57,17 @@ _return_ Convert _value_ to an integer. -| value type | description | -| :- | :- | -| String | If a string is a representation of a decimal integer or its exponential notation, then it is converted to an integer. If a string is a representation of a floating-point decimal or its exponential notation, then it is converted and rounded to an integer. Otherwise it is converted to a null. | -| Float | A float value is rounded to an integer. | -| Datetime | A datetime value is converted to an integer representing its unix time. | -| Boolean | A boolean value is converted to a null. | -| Ternary | A ternaly value is converted to a null. | -| Null | A null value is kept as it is. | +| Type | Value | Value after conversion | +|:---------|:-----------------------------------------------------------------------|:-----------------------------------------| +| String | Representation of a decimal integer | Integer represented by the string | +| | Representation of a floating-point decimal or its exponential notation | Integer with decimal places rounded down | +| | Other values | Null | +| Float | +Inf, -Inf, NaN | Null | +| | Other values | Integer with decimal places rounded down | +| Datetime | | Integer representing its unix time | +| Boolean | | Null | +| Ternary | | Null | +| Null | | Null | ### FLOAT {: #float} @@ -81,14 +84,18 @@ _return_ Convert _value_ to a float. -| value type | description | -| :- | :- | -| String | If a string is a representation of a floating-point decimal or its exponential notation, then it is converted to a float. Otherwise it is converted to a null. | -| Integer | An integer value is converted to a float. | -| Datetime | A datetime value is converted to a float representing its unix time. | -| Boolean | A boolean value is converted to a null. | -| Ternary | A ternary value is converted to a null. | -| Null | A null value is kept as it is. | +| Type | Value | Value after conversion | +|:---------|:-----------------------------------------------------------------------|:---------------------------------| +| String | Representation of a floating-point decimal or its exponential notation | Float represented by the string | +| | 'Inf', '+Inf' | +Inf | +| | '-Inf' | -Inf | +| | 'NaN' | NaN | +| | Other values | Null | +| Integer | | Float equivalent to the integer | +| Datetime | | Float representing its unix time | +| Boolean | | Null | +| Ternary | | Null | +| Null | | Null | ### DATETIME {: #datetime} @@ -113,41 +120,45 @@ _return_ Convert _value_ to a datetime. -| value type | description | -| :- | :- | -| String | If a string value is a representation of an integer, or a float value, then it is converted to a datetime represented by the number as a unix time. If a string value is formatted as a datetime, then it is convered to a datetime. Otherwise, it is converted to a null. | -| Integer | An integer value is converted to a datetime represented by the integer value as a unix time. | -| Float | A float value is converted to a datetime represented by the float value as a unix time. | -| Boolean | A boolean value is converted to a null. | -| Ternary | A ternaly value is converted to a null. | -| Null | A null value is kept as it is. | +| Type | Value | Value after conversion | +|:--------|:-----------------------------------------------------------------------|:---------------------------------------------------------| +| String | Datetime Formats | Datetime represented by the string | +| | Representation of a decimal integer | Datetime represented by the integer value as a unix time | +| | Representation of a floating-point decimal or its exponential notation | Datetime represented by the float value as a unix time | +| | Other values | Null | +| Integer | | Datetime represented by the integer value as a unix time | +| Float | +Inf, -Inf, NaN | Null | +| | Other values | Datetime represented by the float value as a unix time | +| Boolean | | Null | +| Ternary | | Null | +| Null | | Null | #### Format of string to be interpreted as datetime {: #format-of-string-as-datetime} Strings of the form passed by the [--datetime-format option]({{ '/reference/command.html#options' | relative_url }}) and defined in the [configuration files]({{ '/reference/command.html#configurations' | relative_url }}), or the following forms can be converted to datetime values. -| DateFormat | Example | -| :- | :- | +| DateFormat | Example | +|:-----------|:-----------| | YYYY-MM-DD | 2012-03-15 | | YYYY/MM/DD | 2012/03/15 | -| YYYY-M-D | 2012-3-15 | -| YYYY/M/D | 2012/3/15 | +| YYYY-M-D | 2012-3-15 | +| YYYY/M/D | 2012/3/15 |   -| DatetimeFormat | Example | -| :- | :- | -| DateFormat | 2012-03-15 | -| DateFormat hh:mm:ss(.NanoSecods) | 2012-03-15 12:03:01
    2012-03-15 12:03:01.123456789 | -| DateFormat hh:mm:ss(.NanoSecods) ±hh:mm | 2012-03-15 12:03:01 -07:00 | -| DateFormat hh:mm:ss(.NanoSecods) ±hhmm | 2012-03-15 12:03:01 -0700 | -| DateFormat hh:mm:ss(.NanoSecods) TimeZone | 2012-03-15 12:03:01 PST | -| YYYY-MM-DDThh:mm:ss(.NanoSeconds) | 2012-03-15T12:03:01 | -| RFC3339 | 2012-03-15T12:03:01-07:00 | -| RFC3339 with Nano Seconds | 2012-03-15T12:03:01.123456789-07:00 | -| RFC822 | 03 Mar 12 12:03 PST | -| RFC822 with Numeric Zone | 03 Mar 12 12:03 -0700 | +| DatetimeFormat | Example | +|:------------------------------------------|:-------------------------------------------------------| +| DateFormat | 2012-03-15 | +| DateFormat hh:mm:ss(.NanoSecods) | 2012-03-15 12:03:01
    2012-03-15 12:03:01.123456789 | +| DateFormat hh:mm:ss(.NanoSecods) ±hh:mm | 2012-03-15 12:03:01 -07:00 | +| DateFormat hh:mm:ss(.NanoSecods) ±hhmm | 2012-03-15 12:03:01 -0700 | +| DateFormat hh:mm:ss(.NanoSecods) TimeZone | 2012-03-15 12:03:01 PST | +| YYYY-MM-DDThh:mm:ss(.NanoSeconds) | 2012-03-15T12:03:01 | +| RFC3339 | 2012-03-15T12:03:01-07:00 | +| RFC3339 with Nano Seconds | 2012-03-15T12:03:01.123456789-07:00 | +| RFC822 | 03 Mar 12 12:03 PST | +| RFC822 with Numeric Zone | 03 Mar 12 12:03 -0700 | > Timezone abbreviations such as "PST" may not work properly depending on your environment, > so you should use timezone offset such as "-07:00" as possible. @@ -167,14 +178,22 @@ _boolean_ Convert _value_ to a boolean. -| value type | description | -| :- | :- | -| String | If a string value is any of '1', 't', 'T', 'TRUE', 'true' and 'True', then it is converted to true. If a string value is any of '0', 'f', 'F', 'FALSE' and 'false', then it is converted to false. Otherwise it is converted to a null. | -| Integer | If an integer value is 1, then it is converted to true. If an integer value is 0, then it is converted to false. Otherwise it is converted to a null. | -| Float | If a float value is 1, then it is converted to true. If a float value is 0, then it is converted to false. Otherwise it is converted to a null. | -| Datetime | A datetime value is converted to a null. | -| Ternary | If a ternary value is TRUE, then it is converted to true. If a ternary value is FALSE, then it is converted to false. Otherwise it is converted to a null. | -| Null | A null value is kept as it is. | +| Type | Value | Value after conversion | +|:---------|:------------------|:-----------------------| +| String | '1', 't', 'true' | true | +| String | '0', 'f', 'false' | false | +| String | Other values | Null | +| Integer | 1 | true | +| Integer | 0 | false | +| Integer | Other values | Null | +| Float | 1 | true | +| Float | 0 | false | +| Float | Other values | Null | +| Datetime | | Null | +| Ternary | TRUE | true | +| | FALSE | false | +| | UNKNOWN | Null | +| Null | | Null | ### TERNARY {: #ternary} @@ -191,11 +210,18 @@ _return_ Convert _value_ to a ternary. -| value type | description | -| :- | :- | -| String | If a string value is any of '1', 't', 'T', 'TRUE', 'true' and 'True', then it is converted to TRUE. If a string value is any of '0', 'f', 'F', 'FALSE' and 'false', then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| Integer | If an integer value is 1, then it is converted to TRUE. If an integer value is 0, then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| Float | If a float value is 1, then it is converted to TRUE. If a float value is 0, then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| Datetime | A datetime value is converted to UNKNOWN. | -| Boolean | If a boolean value is true, then it is converted to TRUE. If a boolean value is false, then it is converted to FALSE. | -| Null | A null value is converted to UNKNOWN. | +| Type | Value | Value after conversion | +|:---------|:------------------|:-----------------------| +| String | '1', 't', 'true' | TRUE | +| String | '0', 'f', 'false' | FALSE | +| String | Other values | UNKNOWN | +| Integer | 1 | TRUE | +| Integer | 0 | FALSE | +| Integer | Other values | UNKNOWN | +| Float | 1 | TRUE | +| Float | 0 | FALSE | +| Float | Other values | UNKNOWN | +| Datetime | | UNKNOWN | +| Boolean | true | TRUE | +| | false | FALSE | +| Null | | UNKNOWN | diff --git a/docs/_posts/2006-01-02-value.md b/docs/_posts/2006-01-02-value.md index d9e5b9b..cbbf406 100644 --- a/docs/_posts/2006-01-02-value.md +++ b/docs/_posts/2006-01-02-value.md @@ -238,44 +238,68 @@ For example, in arithmetic operations, both left-hand side value and right-hand If the conversion fails, then the value is converted to null. Field values are imported as strings from csv. -You can cast value types expressly by using [cast functions]({{ '/reference/cast-functions.html' | relative_url }}). -This is useful to format output such as numbers in JSON format. - -| conversion to | value type | description | -| :- | :- | :- | -| String | Integer | An integer value is converted to a string representing a decimal integer. | -| | Float | A float value is converted to a string representing a floating-point decimal. | -| | Datetime | A datetime value is converted to a null. | -| | Boolean | A boolean value is converted to a null. | -| | Ternary | A ternaly value is converted to a null. | -| | Null | A null value is kept as it is. | -| Integer | String | If a string is a representation of a decimal integer or its exponential notation, then it is converted to an integer. Otherwise it is converted to a null. | -| | Float | If a float value has no value after the decimal point, then it is converted to an integer. Otherwise it is converted to a null. | -| | Datetime | A datetime value is converted to a null. | -| | Boolean | A boolean value is converted to a null. | -| | Ternary | A ternaly value is converted to a null. | -| | Null | A null value is kept as it is. | -| Float | String | If a string is a representation of a floating-point decimal or its exponential notation, then it is converted to a float. Otherwise it is converted to a null. | -| | Integer | An integer value is converted to a float. | -| | Datetime | A datetime value is converted to a null. | -| | Boolean | A boolean value is converted to a null. | -| | Ternary | A ternary value is converted to a null. | -| | Null | A null value is kept as it is. | -| Datetime | String | If a string value is a representation of an integer, or a float value, then it is converted to a datetime represented by the number as a unix time. If a string value is [formatted as a datetime]({{ '/reference/cast-functions.html#format-of-string-as-datetime' | relative_url }}), then it is convered to a datetime. Otherwise, it is converted to a null. | -| | Integer | An integer value is converted to a null. | -| | Float | A float value is converted to a null. | -| | Boolean | A boolean value is converted to a null. | -| | Ternary | A ternaly value is converted to a null. | -| | Null | A null value is kept as it is. | -| Boolean | String | If a string value is any of '1', 't', 'T', 'TRUE', 'true' and 'True', then it is converted to true. If a string value is any of '0', 'f', 'F', 'FALSE' and 'false', then it is converted to false. Otherwise it is converted to a null. | -| | Integer | If an integer value is 1, then it is converted to true. If an integer value is 0, then it is converted to false. Otherwise it is converted to a null. | -| | Float | If a float value is 1, then it is converted to true. If a float value is 0, then it is converted to false. Otherwise it is converted to a null. | -| | Datetime | A datetime value is converted to a null. | -| | Ternary | If a ternary value is TRUE, then it is converted to true. If a ternary value is FALSE, then it is converted to false. Otherwise it is converted to a null. | -| | Null | A null value is kept as it is. | -| Ternary | String | If a string value is any of '1', 't', 'T', 'TRUE', 'true' and 'True', then it is converted to TRUE. If a string value is any of '0', 'f', 'F', 'FALSE' and 'false', then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| | Integer | If an integer value is 1, then it is converted to TRUE. If an integer value is 0, then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| | Float | If a float value is 1, then it is converted to TRUE. If a float value is 0, then it is converted to FALSE. Otherwise it is converted to UNKNOWN. | -| | Datetime | A datetime value is converted to UNKNOWN. | -| | Boolean | If a boolean value is true, then it is converted to TRUE. If a boolean value is false, then it is converted to FALSE. | -| | Null | A null value is converted to UNKNOWN. | +You can cast value types expressly by using [cast functions]({{ '/reference/cast-functions.html' | relative_url }}), and the result is slightly different from an automatic conversion. + + +| Conversion to | Type | Value | Value after conversion | +|:--------------|:---------|:-----------------------------------------------------------------------|:------------------------------------------------| +| String | Integer | | String representing the decimal integer | +| | Float | | String representing the floating-point decimal | +| | Datetime | | Null | +| | Boolean | | Null | +| | Ternary | | Null | +| | Null | | Null | +| Integer | String | Representation of a decimal integer | Integer represented by the string | +| | | Other values | Null | +| | Float | | Null | +| | Datetime | | Null | +| | Boolean | | Null | +| | Ternary | | Null | +| | Null | | Null | +| Float | String | Representation of a floating-point decimal or its exponential notation | Float represented by the string | +| | | 'Inf', '+Inf' | +Inf | +| | | '-Inf' | -Inf | +| | | 'NaN' | NaN | +| | | Other values | Null | +| | Integer | | Float equivalent to the integer | +| | Datetime | | Null | +| | Boolean | | Null | +| | Ternary | | Null | +| | Null | | Null | +| Datetime | String | Datetime Formats | Datetime represented by the string | +| | | Other values | Null | +| | Integer | | Null | +| | Float | | Null | +| | Boolean | | Null | +| | Ternary | | Null | +| | Null | | Null | +| Boolean | String | '1', 't', 'true' | true | +| | | '0', 'f', 'false' | false | +| | | Other values | Null | +| | Integer | 1 | true | +| | | 0 | false | +| | | Other values | Null | +| | Float | 1 | true | +| | | 0 | false | +| | | Other values | Null | +| | Datetime | | Null | +| | Ternary | TRUE | true | +| | | FALSE | false | +| | | UNKNOWN | Null | +| | Null | | Null | +| Ternary | String | '1', 't', 'true' | TRUE | +| | | '0', 'f', 'false' | FALSE | +| | | Other values | UNKNOWN | +| | Integer | 1 | TRUE | +| | | 0 | FALSE | +| | | Other values | UNKNOWN | +| | Float | 1 | TRUE | +| | | 0 | FALSE | +| | | Other values | UNKNOWN | +| | Datetime | | UNKNOWN | +| | Boolean | true | TRUE | +| | | false | FALSE | +| | Null | | UNKNOWN | + + +> String formats representing Datetime]({{ '/reference/cast-functions.html#format-of-string-as-datetime' | relative_url }}) \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml index e360485..4952dd2 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -26,7 +26,7 @@
    https://mithrandie.github.io/csvq/reference/value.html - 2021-03-09T09:53:17+00:00 + 2022-07-03T00:42:03+00:00 https://mithrandie.github.io/csvq/reference/select-query.html @@ -170,7 +170,7 @@ https://mithrandie.github.io/csvq/reference/cast-functions.html - 2021-03-09T09:53:17+00:00 + 2022-07-03T00:42:03+00:00 https://mithrandie.github.io/csvq/reference/system-functions.html diff --git a/lib/query/arithmetic_test.go b/lib/query/arithmetic_test.go index c96e02c..20b30a4 100644 --- a/lib/query/arithmetic_test.go +++ b/lib/query/arithmetic_test.go @@ -1,6 +1,7 @@ package query import ( + "math" "reflect" "testing" @@ -92,6 +93,24 @@ var calculateTests = []struct { Operator: '%', Error: "integer devided by zero", }, + { + LHS: value.NewFloat(math.Inf(1)), + RHS: value.NewFloat(100), + Operator: '+', + Result: value.NewFloat(math.Inf(1)), + }, + { + LHS: value.NewFloat(math.Inf(1)), + RHS: value.NewFloat(math.Inf(-1)), + Operator: '-', + Result: value.NewFloat(math.Inf(1)), + }, + { + LHS: value.NewFloat(math.Inf(1)), + RHS: value.NewFloat(math.NaN()), + Operator: '+', + Result: value.NewFloat(math.NaN()), + }, } func TestCalculate(t *testing.T) { @@ -112,6 +131,12 @@ func TestCalculate(t *testing.T) { } if !reflect.DeepEqual(r, v.Result) { + if expectF, ok := r.(*value.Float); ok && math.IsNaN(expectF.Raw()) { + if retF, ok := r.(*value.Float); ok && math.IsNaN(retF.Raw()) { + continue + } + } + t.Errorf("result = %s, want %s for (%s %s %s)", r, v.Result, v.LHS, string(rune(v.Operator)), v.RHS) } } diff --git a/lib/query/function.go b/lib/query/function.go index 4e32ec9..a3c3ae8 100644 --- a/lib/query/function.go +++ b/lib/query/function.go @@ -301,9 +301,6 @@ func execMath1Arg(fn parser.Function, args []value.Primary, mathf func(float64) result := mathf(f.(*value.Float).Raw()) value.Discard(f) - if math.IsInf(result, 0) || math.IsNaN(result) { - return value.NewNull(), nil - } return value.NewFloat(result), nil } @@ -326,9 +323,6 @@ func execMath2Args(fn parser.Function, args []value.Primary, mathf func(float64, value.Discard(f1) value.Discard(f2) - if math.IsInf(result, 0) || math.IsNaN(result) { - return value.NewNull(), nil - } return value.NewFloat(result), nil } @@ -1756,13 +1750,13 @@ func String(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prima return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } - switch args[0].(type) { + switch p := args[0].(type) { case *value.Boolean: - return value.NewString(strconv.FormatBool(args[0].(*value.Boolean).Raw())), nil + return value.NewString(strconv.FormatBool(p.Raw())), nil case *value.Ternary: - return value.NewString(args[0].(*value.Ternary).Ternary().String()), nil + return value.NewString(p.Ternary().String()), nil case *value.Datetime: - return value.NewString(args[0].(*value.Datetime).Format(time.RFC3339Nano)), nil + return value.NewString(p.Format(time.RFC3339Nano)), nil default: return value.ToString(args[0]), nil } @@ -1773,11 +1767,9 @@ func Integer(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } - switch args[0].(type) { - case *value.Float: - return value.NewInteger(int64(round(args[0].(*value.Float).Raw(), 0))), nil + switch p := args[0].(type) { case *value.Datetime: - return value.NewInteger(args[0].(*value.Datetime).Raw().Unix()), nil + return value.NewInteger(p.Raw().Unix()), nil default: return value.ToInteger(args[0]), nil } @@ -1788,9 +1780,9 @@ func Float(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } - switch args[0].(type) { + switch p := args[0].(type) { case *value.Datetime: - t := args[0].(*value.Datetime).Raw() + t := p.Raw() f := float64(t.Unix()) if t.Nanosecond() > 0 { f = f + float64(t.Nanosecond())/1e9 @@ -1832,6 +1824,10 @@ func Datetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value if f := value.ToFloat(p); !value.IsNull(f) { val := f.(*value.Float).Raw() value.Discard(f) + + if math.IsNaN(val) || math.IsInf(val, 0) { + return value.NewNull() + } return value.NewDatetime(value.Float64ToTime(val, location)) } diff --git a/lib/query/function_test.go b/lib/query/function_test.go index bfc03c8..80c3181 100644 --- a/lib/query/function_test.go +++ b/lib/query/function_test.go @@ -2,6 +2,7 @@ package query import ( "context" + "math" "reflect" "testing" "time" @@ -38,6 +39,12 @@ func testFunction(t *testing.T, f func(parser.Function, []value.Primary, *cmd.Fl continue } if !reflect.DeepEqual(result, v.Result) { + if f1, ok := v.Result.(*value.Float); ok && math.IsNaN(f1.Raw()) { + if f2, ok := result.(*value.Float); ok && math.IsNaN(f2.Raw()) { + continue + } + } + t.Errorf("%s: result = %s, want %s", v.Name, result, v.Result) } } @@ -614,14 +621,14 @@ var sqrtTests = []functionTest{ Result: value.NewFloat(2), }, { - Name: "Sqrt Cannot Calculate", + Name: "Sqrt returns NaN", Function: parser.Function{ Name: "sqrt", }, Args: []value.Primary{ value.NewFloat(-4), }, - Result: value.NewNull(), + Result: value.NewFloat(math.NaN()), }, } @@ -664,7 +671,7 @@ var powTests = []functionTest{ Result: value.NewNull(), }, { - Name: "Pow Cannot Calculate", + Name: "Pow returns NaN", Function: parser.Function{ Name: "pow", }, @@ -672,7 +679,7 @@ var powTests = []functionTest{ value.NewFloat(-2), value.NewFloat(2.4), }, - Result: value.NewNull(), + Result: value.NewFloat(math.NaN()), }, { Name: "Pow Arguments Error", @@ -3647,7 +3654,17 @@ var integerTests = []functionTest{ Args: []value.Primary{ value.NewFloat(1.7), }, - Result: value.NewInteger(2), + Result: value.NewInteger(1), + }, + { + Name: "Integer from Special Float Value", + Function: parser.Function{ + Name: "integer", + }, + Args: []value.Primary{ + value.NewFloat(math.NaN()), + }, + Result: value.NewNull(), }, { Name: "Float Null", @@ -3799,6 +3816,16 @@ var datetimeTests = []functionTest{ }, Result: value.NewDatetime(time.Date(2006, 1, 2, 6, 4, 5, 123000000, GetTestLocation())), }, + { + Name: "Datetime Invalid Float Value", + Function: parser.Function{ + Name: "datetime", + }, + Args: []value.Primary{ + value.NewFloat(math.NaN()), + }, + Result: value.NewNull(), + }, { Name: "Datetime from String", Function: parser.Function{ diff --git a/lib/query/sort_value.go b/lib/query/sort_value.go index ec04963..10a5bc1 100644 --- a/lib/query/sort_value.go +++ b/lib/query/sort_value.go @@ -2,6 +2,7 @@ package query import ( "bytes" + "math" "strings" "github.com/mithrandie/csvq/lib/cmd" @@ -177,9 +178,23 @@ func (v *SortValue) Less(compareValue *SortValue) ternary.Value { case FloatType: switch compareValue.Type { case IntegerType, FloatType: + if math.IsNaN(v.Float) || math.IsNaN(compareValue.Float) { + if math.IsNaN(v.Float) && math.IsNaN(compareValue.Float) { + return ternary.UNKNOWN + } + + if math.IsNaN(v.Float) { + return ternary.FALSE + } + + // math.IsNaN(compareValue.Float) + return ternary.TRUE + } + if v.Float == compareValue.Float { return ternary.UNKNOWN } + return ternary.ConvertFromBool(v.Float < compareValue.Float) case StringType: return ternary.ConvertFromBool(v.String < compareValue.String) @@ -219,6 +234,9 @@ func (v *SortValue) EquivalentTo(compareValue *SortValue) bool { case FloatType: switch compareValue.Type { case FloatType: + if math.IsNaN(v.Float) && math.IsNaN(compareValue.Float) { + return true + } return v.Float == compareValue.Float } case DatetimeType: diff --git a/lib/query/sort_value_test.go b/lib/query/sort_value_test.go index 875c0c3..c1c0976 100644 --- a/lib/query/sort_value_test.go +++ b/lib/query/sort_value_test.go @@ -2,6 +2,7 @@ package query import ( "bytes" + "math" "testing" "time" @@ -203,6 +204,76 @@ var sortValueLessTests = []struct { StrictEqual: true, Result: ternary.TRUE, }, + { + Name: "-Inf is less than +Inf", + SortValue: value.NewFloat(math.Inf(-1)), + CompareValue: value.NewFloat(math.Inf(+1)), + StrictEqual: false, + Result: ternary.TRUE, + }, + { + Name: "-Inf is less than +Inf even when StrictEqual is true", + SortValue: value.NewFloat(math.Inf(-1)), + CompareValue: value.NewFloat(math.Inf(+1)), + StrictEqual: true, + Result: ternary.TRUE, + }, + { + Name: "-Inf is less than any float value", + SortValue: value.NewFloat(math.Inf(-1)), + CompareValue: value.NewFloat(1), + StrictEqual: false, + Result: ternary.TRUE, + }, + { + Name: "-Inf is less than any float value even when StrictEqual is true", + SortValue: value.NewFloat(math.Inf(-1)), + CompareValue: value.NewFloat(1), + StrictEqual: true, + Result: ternary.TRUE, + }, + { + Name: "NaN has the same priority as other NaN", + SortValue: value.NewFloat(math.NaN()), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: false, + Result: ternary.UNKNOWN, + }, + { + Name: "NaN has the same priority as other NaN even when StrictEqual is true", + SortValue: value.NewFloat(math.NaN()), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: true, + Result: ternary.UNKNOWN, + }, + { + Name: "NaN has the highest priority than any float value", + SortValue: value.NewFloat(math.NaN()), + CompareValue: value.NewFloat(math.Inf(1)), + StrictEqual: false, + Result: ternary.FALSE, + }, + { + Name: "NaN has the highest priority than any float value even when StrictEqual is true", + SortValue: value.NewFloat(math.NaN()), + CompareValue: value.NewFloat(math.Inf(1)), + StrictEqual: true, + Result: ternary.FALSE, + }, + { + Name: "Any float value has a lower priority than NaN", + SortValue: value.NewFloat(math.Inf(1)), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: false, + Result: ternary.TRUE, + }, + { + Name: "Any float value has a lower priority than NaN even when StrictEqual is true", + SortValue: value.NewFloat(math.Inf(1)), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: true, + Result: ternary.TRUE, + }, } func TestSortValue_Less(t *testing.T) { @@ -326,6 +397,20 @@ var sortValueEquivalentToTests = []struct { StrictEqual: true, Result: false, }, + { + Name: "Inf and NaN are not equivanent", + SortValue: value.NewFloat(math.Inf(1)), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: false, + Result: false, + }, + { + Name: "NaN and NaN are equivanent in sorting", + SortValue: value.NewFloat(math.NaN()), + CompareValue: value.NewFloat(math.NaN()), + StrictEqual: false, + Result: true, + }, } func TestSortValue_EquivalentTo(t *testing.T) { diff --git a/lib/value/comparison.go b/lib/value/comparison.go index 67a435c..d48a69f 100644 --- a/lib/value/comparison.go +++ b/lib/value/comparison.go @@ -2,6 +2,7 @@ package value import ( "errors" + "math" "strings" "time" @@ -45,6 +46,10 @@ func compareInteger(v1 int64, v2 int64) ComparisonResult { } func compareFloat(v1 float64, v2 float64) ComparisonResult { + if math.IsNaN(v1) || math.IsNaN(v2) { + return IsNotEqual + } + if v1 == v2 { return IsEqual } diff --git a/lib/value/comparison_test.go b/lib/value/comparison_test.go index b8d5148..e5cdda7 100644 --- a/lib/value/comparison_test.go +++ b/lib/value/comparison_test.go @@ -1,6 +1,7 @@ package value import ( + "math" "testing" "time" @@ -150,6 +151,26 @@ var compareCombinedlyTests = []struct { RHS: NewString("A"), Result: IsLess, }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.Inf(1)), + Result: IsEqual, + }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.Inf(-1)), + Result: IsGreater, + }, + { + LHS: NewFloat(math.NaN()), + RHS: NewFloat(math.NaN()), + Result: IsNotEqual, + }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.NaN()), + Result: IsNotEqual, + }, } func TestCompareCombinedly(t *testing.T) { @@ -363,6 +384,48 @@ var compareTests = []struct { Op: "<>", Result: ternary.UNKNOWN, }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.Inf(1)), + Op: "=", + Result: ternary.TRUE, + }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.Inf(-1)), + Op: ">", + Result: ternary.TRUE, + }, + { + LHS: NewFloat(math.Inf(1)), + RHS: NewFloat(math.NaN()), + Op: "<", + Result: ternary.UNKNOWN, + }, + { + LHS: NewFloat(math.NaN()), + RHS: NewFloat(math.NaN()), + Op: "=", + Result: ternary.FALSE, + }, + { + LHS: NewFloat(math.NaN()), + RHS: NewFloat(math.NaN()), + Op: "==", + Result: ternary.FALSE, + }, + { + LHS: NewFloat(math.NaN()), + RHS: NewFloat(math.NaN()), + Op: "<>", + Result: ternary.TRUE, + }, + { + LHS: NewFloat(math.NaN()), + RHS: NewFloat(math.Inf(1)), + Op: "<>", + Result: ternary.TRUE, + }, } func TestCompare(t *testing.T) { diff --git a/lib/value/conv.go b/lib/value/conv.go index 6067ff7..8a3ebb0 100644 --- a/lib/value/conv.go +++ b/lib/value/conv.go @@ -2,6 +2,7 @@ package value import ( "bytes" + "math" "strconv" "strings" "sync" @@ -253,13 +254,16 @@ func Float64ToStr(f float64) string { } func ToInteger(p Primary) Primary { - switch p.(type) { + switch val := p.(type) { case *Integer: - return NewInteger(p.(*Integer).Raw()) + return NewInteger(val.Raw()) case *Float: - return NewInteger(int64(p.(*Float).Raw())) + if math.IsNaN(val.Raw()) || math.IsInf(val.Raw(), 0) { + return NewNull() + } + return NewInteger(int64(val.Raw())) case *String: - s := cmd.TrimSpace(p.(*String).Raw()) + s := cmd.TrimSpace(val.Raw()) if i, e := strconv.ParseInt(s, 10, 64); e == nil { return NewInteger(i) } diff --git a/lib/value/conv_test.go b/lib/value/conv_test.go index d86691d..1421acf 100644 --- a/lib/value/conv_test.go +++ b/lib/value/conv_test.go @@ -1,6 +1,7 @@ package value import ( + "math" "testing" "time" @@ -318,6 +319,24 @@ func TestToInteger(t *testing.T) { t.Errorf("primary type = %T, want Null for %#v", i, p) } + p = NewFloat(math.NaN()) + i = ToInteger(p) + if _, ok := i.(*Null); !ok { + t.Errorf("primary type = %T, want Null for %#v", i, p) + } + + p = NewFloat(math.Inf(1)) + i = ToInteger(p) + if _, ok := i.(*Null); !ok { + t.Errorf("primary type = %T, want Null for %#v", i, p) + } + + p = NewFloat(math.Inf(-1)) + i = ToInteger(p) + if _, ok := i.(*Null); !ok { + t.Errorf("primary type = %T, want Null for %#v", i, p) + } + p = NewString(" 1") i = ToInteger(p) if _, ok := i.(*Integer); !ok { From e258c430c0333e5548e35b19fead4dbbcab5c3fd Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Sun, 3 Jul 2022 18:54:44 +0900 Subject: [PATCH 13/17] Add some build-in functions. --- docs/_posts/2006-01-02-datetime-functions.md | 15 + docs/_posts/2006-01-02-numeric-functions.md | 444 +++++++++++++------ docs/sitemap.xml | 4 +- lib/query/function.go | 120 ++++- lib/query/function_test.go | 368 +++++++++++++-- lib/syntax/syntax.go | 156 +++++-- 6 files changed, 869 insertions(+), 238 deletions(-) diff --git a/docs/_posts/2006-01-02-datetime-functions.md b/docs/_posts/2006-01-02-datetime-functions.md index 608d98a..81602ce 100644 --- a/docs/_posts/2006-01-02-datetime-functions.md +++ b/docs/_posts/2006-01-02-datetime-functions.md @@ -46,6 +46,7 @@ category: reference | [TIME_DIFF](#time_diff) | Return the difference of time between two datetime values as seconds | | [TIME_NANO_DIFF](#time_nano_diff) | Return the difference of time between two datetime values as nanoseconds | | [UTC](#utc) | Return a datetime in UTC | +| [MILLI_TO_DATETIME](#milli_to_datetime) | Convert an integer representing Unix milliseconds to a datetime | | [NANO_TO_DATETIME](#nano_to_datetime) | Convert an integer representing Unix nano time to a datetime | ## Definitions @@ -701,6 +702,20 @@ _return_ Returns the datetime value of _datetime_ in UTC. +### MILLI_TO_DATETIME +{: #milli_to_datetime} + +``` +MILLI_TO_DATETIME(unix_milliseconds) +``` + +_unix_milliseconds_ +: [integer]({{ '/reference/value.html#integer' | relative_url }}) + +_return_ +: [datetime]({{ '/reference/value.html#datetime' | relative_url }}) + +Converts an integer representing Unix milliseconds to a datetime. ### NANO_TO_DATETIME {: #nano_to_datetime} diff --git a/docs/_posts/2006-01-02-numeric-functions.md b/docs/_posts/2006-01-02-numeric-functions.md index 4b64fd5..9748b13 100644 --- a/docs/_posts/2006-01-02-numeric-functions.md +++ b/docs/_posts/2006-01-02-numeric-functions.md @@ -6,213 +6,221 @@ category: reference # Numeric Functions -| name | description | -| :- | :- | -| [CEIL](#ceil) | Round a number up | -| [FLOOR](#floor) | Round a number down | -| [ROUND](#round) | Round a number | -| [ABS](#abs) | Return the absolute value of a number | -| [ACOS](#acos) | Return the arc cosine of a number | -| [ASIN](#asin) | Return the arc sine of a number | -| [ATAN](#atan) | Return the arc tangent of a number | -| [ATAN2](#atan2) | Return the arc tangent of two numbers | -| [COS](#cos) | Return the cosine of a number | -| [SIN](#sin) | Return the sine of a number | -| [TAN](#tan) | Return the tangent of a number | -| [EXP](#exp) | Return the value of base _e_ raised to the power of a number | -| [EXP2](#exp2) | Return the value of base _2_ raised to the power of a number | -| [EXPM1](#expm1) | Return the value of base _e_ rised to the power of a number minus 1 | -| [LOG](#log) | Return the natural logarithm of a number | -| [LOG10](#log10) | Return the decimal logarithm of a number | -| [LOG2](#log2) | Return the binary logarithm of a number | -| [LOG1P](#log1p) | Return the natural logarithm of 1 plus a number | -| [SQRT](#sqrt) | Return the square root of a number | -| [POW](#pow) | Returns the value of a number raised to the power of another number | -| [BIN_TO_DEC](#bin_to_dec) | Convert a string representing a binary number to an integer | -| [OCT_TO_DEC](#oct_to_dec) | Convert a string representing a octal number to an integer | -| [HEX_TO_DEC](#hex_to_dec) | Convert a string representing a hexadecimal number to an integer | +| name | description | +|:--------------------------------------|:------------------------------------------------------------------------------------------| +| [ABS](#abs) | Return the absolute value of a number | +| [ACOS](#acos) | Return the arc cosine of a number | +| [ACOSH](#acosh) | Return the inverse hyperbolic cosine of a number | +| [ASIN](#asin) | Return the arc sine of a number | +| [ASINH](#asinh) | Return the inverse hyperbolic sine of a number | +| [ATAN](#atan) | Return the arc tangent of a number | +| [ATAN2](#atan2) | Return the arc tangent of two numbers | +| [ATANH](#atanh) | Return the inverse hyperbolic tangent of a number | +| [CBRT](#cbrt) | Return the cube root of a number | +| [CEIL](#ceil) | Round a number up | +| [COS](#cos) | Return the cosine of a number | +| [COSH](#cosh) | Return the hyperbolic cosine of a number | +| [EXP](#exp) | Return the value of base _e_ raised to the power of a number | +| [EXP2](#exp2) | Return the value of base _2_ raised to the power of a number | +| [EXPM1](#expm1) | Return the value of base _e_ rised to the power of a number minus 1 | +| [FLOOR](#floor) | Round a number down | +| [IS_INF](#is_inf) | Return whether _number_ is an infinity | +| [IS_NAN](#is_nan) | Return whether _number_ is a NaN | +| [LOG](#log) | Return the natural logarithm of a number | +| [LOG10](#log10) | Return the decimal logarithm of a number | +| [LOG1P](#log1p) | Return the natural logarithm of 1 plus a number | +| [LOG2](#log2) | Return the binary logarithm of a number | +| [LOGB](#logb) | Return the binary exponent of a number | +| [POW](#pow) | Returns the value of a number raised to the power of another number | +| [ROUND](#round) | Round a number | +| [SIN](#sin) | Return the sine of a number | +| [SINH](#sinh) | Return the hyperbolic sine of a number | +| [SQRT](#sqrt) | Return the square root of a number | +| [TAN](#tan) | Return the tangent of a number | +| [TANH](#tanh) | Return the hyperbolic tangent of a number | +| [BIN_TO_DEC](#bin_to_dec) | Convert a string representing a binary number to an integer | +| [OCT_TO_DEC](#oct_to_dec) | Convert a string representing a octal number to an integer | +| [HEX_TO_DEC](#hex_to_dec) | Convert a string representing a hexadecimal number to an integer | | [ENOTATION_TO_DEC](#enotation_to_dec) | Convert a string representing a number with exponential notation to an integer or a float | -| [BIN](#bin) | Convert an integer to a string representing the bynary number | -| [OCT](#oct) | Convert an integer to a string representing the octal number | -| [HEX](#hex) | Convert an integer to a string representing the hexadecimal number | -| [ENOTATION](#enotation) | Convert a float to a string representing the number with exponential notation | -| [NUMBER_FORMAT](#number_format) | Convert a number to a string representing the number with separators | -| [RAND](#rand) | Return a pseudo-random number | +| [BIN](#bin) | Convert an integer to a string representing the bynary number | +| [OCT](#oct) | Convert an integer to a string representing the octal number | +| [HEX](#hex) | Convert an integer to a string representing the hexadecimal number | +| [ENOTATION](#enotation) | Convert a float to a string representing the number with exponential notation | +| [NUMBER_FORMAT](#number_format) | Convert a number to a string representing the number with separators | +| [RAND](#rand) | Return a pseudo-random number | > _e_ is the base of natural logarithms ## Definitions -### CEIL -{: #ceil} +### ABS +{: #abs} ``` -CEIL(number) +ABS(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ up to an integer value. +Returns the absolute value of _number_ + +### ACOS +{: #acos} ``` -CEIL(number, place) +ACOS(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) - -_place_ -: [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ up to _place_ decimal place. -If _place_ is a negative number, _place_ represents the place in the integer part. +Returns the arc cosine of _number_. -### FLOOR -{: #floor} +### ACOSH +{: #acosh} ``` -FLOOR(number) +ACOSH(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ down to an integer value. +Returns the inverse hyperbolic cosine of _number_. + +### ASIN +{: #asin} ``` -FLOOR(number, place) +ASIN(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) - -_place_ -: [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ down to _place_ decimal place. -If _place_ is a negative number, _place_ represents the place in the integer part. +Returns the arc sine of _number_. -### ROUND -{: #round} +### ASINH +{: #asinh} ``` -ROUND(number) +ASINH(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ to an integer value. +Returns the inverse hyperbolic sine of _number_. + +### ATAN +{: #atan} ``` -ROUND(number, place) +ATAN(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) - -_place_ -: [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Rounds _number_ to _place_ decimal place. -If _place_ is a negative number, _place_ represents the place in the integer part. +Returns the arc tangent of _number_. -### ABS -{: #abs} +### ATAN2 +{: #atan2} ``` -ABS(number) +ATAN2(number2, number1) ``` -_number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +_number2_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_number1_ +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the absolute value of _number_ +Returns the arc tangent of _number2_ / _number1_, using the signs of the two to determine the quadrant of the returns value. -### ACOS -{: #acos} +### ATANH +{: #atanh} ``` -ACOS(number) +ATANH(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the arc cosine of _number_. +Returns the inverse hyperbolic tangent of _number_. -### ASIN -{: #asin} +### CBRT +{: #cbrt} ``` -ASIN(number) +CBRT(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the arc sine of _number_. +Returns the cube root of _number_. -### ATAN -{: #atan} +### CEIL +{: #ceil} ``` -ATAN(number) +CEIL(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the arc tangent of _number_. - -### ATAN2 -{: #atan2} +Rounds _number_ up to an integer value. ``` -ATAN2(number2, number1) +CEIL(number, place) ``` -_number2_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) -_number1_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +_place_ +: [integer]({{ '/reference/value.html#integer' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the arc tangent of _number2_ / _number1_, using the signs of the two to determine the quadrant of the returns value. +Rounds _number_ up to _place_ decimal place. +If _place_ is a negative number, _place_ represents the place in the integer part. ### COS {: #cos} @@ -222,42 +230,27 @@ COS(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) Returns the cosine of _number_. -### SIN -{: #sin} +### COSH +{: #cosh} ``` -SIN(number) +COSH(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) - -_return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the sine of _number_. - -### TAN -{: #tan} - -``` -TAN(number) -``` - -_number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) - _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the tangent of _number_. +Returns the hyperbolic cosine of _number_. ### EXP {: #exp} @@ -267,7 +260,7 @@ EXP(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) @@ -282,7 +275,7 @@ EXP2(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) @@ -297,13 +290,82 @@ EXPM1(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) Returns the value of base _e_ rised to the power of _number_ minus 1. +### FLOOR +{: #floor} + +``` +FLOOR(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Rounds _number_ down to an integer value. + +``` +FLOOR(number, place) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_place_ +: [integer]({{ '/reference/value.html#integer' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Rounds _number_ down to _place_ decimal place. +If _place_ is a negative number, _place_ represents the place in the integer part. + +### IS_INF +{: #is_inf} + +``` +IS_INF(number [, sign]) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_sign_ +: [integer]({{ '/reference/value.html#integer' | relative_url }}) + + The default is _0_. + +_return_ +: [ternary]({{ '/reference/value.html#ternary' | relative_url }}) + +Returns whether _number_ is an infinity. +If _sign_ is greater than 0, then returns whether _number_ is a positive infinity. +If _sign_ is less than 0, then returns whether _number_ is a negative infinity. +If _sign_ is 0, then returns whether _number_ is either infinity. + +### IS_NAN +{: #is_nan} + +``` +IS_NAN(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [ternary]({{ '/reference/value.html#ternary' | relative_url }}) + +Returns whether _number_ is a NaN. + ### LOG {: #log} @@ -312,7 +374,7 @@ LOG(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) @@ -327,13 +389,28 @@ LOG10(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) Returns the decimal logarithm of _number_. +### LOG1P +{: #log1p} + +``` +LOG1P(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Returns the natural logarithm of 1 plus _number_. + ### LOG2 {: #log2} @@ -342,27 +419,106 @@ LOG2(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) Returns the binary logarithm of _number_. -### LOG1P -{: #log1p} +### LOGB +{: #logb} ``` -LOG1P(number) +LOGB(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the natural logarithm of 1 plus _number_. +Returns the binary exponent of _number_. + +### POW +{: #pow} + +``` +POW(base, exponent) +``` + +_base_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_exponent_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Returns the value of _base_ raised to the power of _exponent_. + +### ROUND +{: #round} + +``` +ROUND(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Rounds _number_ to an integer value. + +``` +ROUND(number, place) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_place_ +: [integer]({{ '/reference/value.html#integer' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Rounds _number_ to _place_ decimal place. +If _place_ is a negative number, _place_ represents the place in the integer part. + +### SIN +{: #sin} + +``` +SIN(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Returns the sine of _number_. + +### SINH +{: #sinh} + +``` +SINH(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Returns the hyperbolic sine of _number_. ### SQRT {: #sqrt} @@ -372,30 +528,42 @@ SQRT(number) ``` _number_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) Returns the square root of _number_. - -### POW -{: #pow} + +### TAN +{: #tan} ``` -POW(base, exponent) +TAN(number) ``` -_base_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) -_exponent_ -: [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) +_return_ +: [float]({{ '/reference/value.html#float' | relative_url }}) + +Returns the tangent of _number_. + +### TANH +{: #tanh} + +``` +TANH(number) +``` + +_number_ +: [float]({{ '/reference/value.html#float' | relative_url }}) _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) -Returns the value of _base_ raised to the power of _exponent_. +Returns the hyperbolic tangent of _number_. ### BIN_TO_DEC {: #bin_to_dec} diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 4952dd2..f3dd1c0 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -158,11 +158,11 @@ https://mithrandie.github.io/csvq/reference/numeric-functions.html - 2022-03-22T23:49:26+00:00 + 2022-07-03T09:54:15+00:00 https://mithrandie.github.io/csvq/reference/datetime-functions.html - 2019-04-29T18:46:39+00:00 + 2022-07-03T09:54:15+00:00 https://mithrandie.github.io/csvq/reference/cryptographic-hash-functions.html diff --git a/lib/query/function.go b/lib/query/function.go index a3c3ae8..e70a931 100644 --- a/lib/query/function.go +++ b/lib/query/function.go @@ -45,21 +45,31 @@ var Functions = map[string]BuiltInFunction{ "ROUND": Round, "ABS": Abs, "ACOS": Acos, + "ACOSH": Acosh, "ASIN": Asin, + "ASINH": Asinh, "ATAN": Atan, "ATAN2": Atan2, + "ATANH": Atanh, + "CBRT": Cbrt, "COS": Cos, - "SIN": Sin, - "TAN": Tan, + "COSH": Cosh, "EXP": Exp, "EXP2": Exp2, "EXPM1": Expm1, + "IS_INF": IsInf, + "IS_NAN": IsNaN, "LOG": MathLog, "LOG10": Log10, - "LOG2": Log2, "LOG1P": Log1p, - "SQRT": Sqrt, + "LOG2": Log2, + "LOGB": Logb, "POW": Pow, + "SIN": Sin, + "SINH": Sinh, + "SQRT": Sqrt, + "TAN": Tan, + "TANH": Tanh, "BIN_TO_DEC": BinToDec, "OCT_TO_DEC": OctToDec, "HEX_TO_DEC": HexToDec, @@ -142,6 +152,7 @@ var Functions = map[string]BuiltInFunction{ "TIME_DIFF": TimeDiff, "TIME_NANO_DIFF": TimeNanoDiff, "UTC": UTC, + "MILLI_TO_DATETIME": MilliToDatetime, "NANO_TO_DATETIME": NanoToDatetime, "STRING": String, "INTEGER": Integer, @@ -334,10 +345,18 @@ func Acos(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary return execMath1Arg(fn, args, math.Acos) } +func Acosh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Acosh) +} + func Asin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Asin) } +func Asinh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Asinh) +} + func Atan(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Atan) } @@ -346,16 +365,20 @@ func Atan2(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return execMath2Args(fn, args, math.Atan2) } -func Cos(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { - return execMath1Arg(fn, args, math.Cos) +func Atanh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Atanh) } -func Sin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { - return execMath1Arg(fn, args, math.Sin) +func Cbrt(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Cbrt) } -func Tan(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { - return execMath1Arg(fn, args, math.Tan) +func Cos(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Cos) +} + +func Cosh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Cosh) } func Exp(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { @@ -370,6 +393,40 @@ func Expm1(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return execMath1Arg(fn, args, math.Expm1) } +func IsInf(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + if len(args) < 1 { + return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) + } + + f1 := value.ToFloat(args[0]) + if value.IsNull(f1) { + return value.NewTernary(ternary.FALSE), nil + } + + sign := 0 + if len(args) == 2 { + f2 := value.ToIntegerStrictly(args[1]) + if !value.IsNull(f2) { + sign = int(f2.(*value.Integer).Raw()) + } + } + + return value.NewTernary(ternary.ConvertFromBool(math.IsInf(f1.(*value.Float).Raw(), sign))), nil +} + +func IsNaN(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + if len(args) != 1 { + return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) + } + + f := value.ToFloat(args[0]) + if value.IsNull(f) { + return value.NewTernary(ternary.FALSE), nil + } + + return value.NewTernary(ternary.ConvertFromBool(math.IsNaN(f.(*value.Float).Raw()))), nil +} + func MathLog(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log) } @@ -378,20 +435,40 @@ func Log10(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return execMath1Arg(fn, args, math.Log10) } +func Log1p(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Log1p) +} + func Log2(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log2) } -func Log1p(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { - return execMath1Arg(fn, args, math.Log1p) +func Logb(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Logb) +} + +func Pow(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath2Args(fn, args, math.Pow) +} + +func Sin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Sin) +} + +func Sinh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Sinh) } func Sqrt(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Sqrt) } -func Pow(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { - return execMath2Args(fn, args, math.Pow) +func Tan(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Tan) +} + +func Tanh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { + return execMath1Arg(fn, args, math.Tanh) } func execParseInt(fn parser.Function, args []value.Primary, base int) (value.Primary, error) { @@ -1730,6 +1807,21 @@ func UTC(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Prim return value.NewDatetime(t), nil } +func MilliToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { + if len(args) != 1 { + return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) + } + + p := value.ToInteger(args[0]) + if value.IsNull(p) { + return value.NewNull(), nil + } + i := p.(*value.Integer).Raw() + value.Discard(p) + + return value.NewDatetime(time.Unix(i/1000, (i%1000)*1000000).In(flags.GetTimeLocation())), nil +} + func NanoToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) diff --git a/lib/query/function_test.go b/lib/query/function_test.go index 80c3181..259c5c6 100644 --- a/lib/query/function_test.go +++ b/lib/query/function_test.go @@ -387,6 +387,23 @@ func TestAcos(t *testing.T) { testFunction(t, Acos, acosTests) } +var acoshTests = []functionTest{ + { + Name: "Acosh", + Function: parser.Function{ + Name: "acosh", + }, + Args: []value.Primary{ + value.NewInteger(1), + }, + Result: value.NewFloat(0), + }, +} + +func TestAcosh(t *testing.T) { + testFunction(t, Acosh, acoshTests) +} + var asinTests = []functionTest{ { Name: "Asin", @@ -404,6 +421,23 @@ func TestAsin(t *testing.T) { testFunction(t, Asin, asinTests) } +var asinhTests = []functionTest{ + { + Name: "Asinh", + Function: parser.Function{ + Name: "asinh", + }, + Args: []value.Primary{ + value.NewFloat(0), + }, + Result: value.NewFloat(0), + }, +} + +func TestAsinh(t *testing.T) { + testFunction(t, Asinh, asinhTests) +} + var atanTests = []functionTest{ { Name: "Atan", @@ -439,55 +473,72 @@ func TestAtan2(t *testing.T) { testFunction(t, Atan2, atan2Tests) } -var cosTests = []functionTest{ +var atanhTests = []functionTest{ { - Name: "Cos", + Name: "Atanh", Function: parser.Function{ - Name: "cos", + Name: "atanh", }, Args: []value.Primary{ - value.NewInteger(2), + value.NewInteger(0), }, - Result: value.NewFloat(-0.4161468365471424), + Result: value.NewFloat(0), }, } -func TestCos(t *testing.T) { - testFunction(t, Cos, cosTests) +func TestAtanh(t *testing.T) { + testFunction(t, Atanh, atanhTests) } -var sinTests = []functionTest{ +var cbrtTests = []functionTest{ { - Name: "Sin", + Name: "Cbrt", Function: parser.Function{ - Name: "sin", + Name: "cbrt", }, Args: []value.Primary{ - value.NewInteger(1), + value.NewInteger(8), }, - Result: value.NewFloat(0.8414709848078965), + Result: value.NewFloat(2), }, } -func TestSin(t *testing.T) { - testFunction(t, Sin, sinTests) +func TestCbrt(t *testing.T) { + testFunction(t, Cbrt, cbrtTests) } -var tanTests = []functionTest{ +var cosTests = []functionTest{ { - Name: "Tan", + Name: "Cos", Function: parser.Function{ - Name: "tan", + Name: "cos", }, Args: []value.Primary{ value.NewInteger(2), }, - Result: value.NewFloat(-2.185039863261519), + Result: value.NewFloat(-0.4161468365471424), }, } -func TestTan(t *testing.T) { - testFunction(t, Tan, tanTests) +func TestCos(t *testing.T) { + testFunction(t, Cos, cosTests) +} + +var coshTests = []functionTest{ + { + Name: "Cosh", + Function: parser.Function{ + Name: "cosh", + }, + Args: []value.Primary{ + value.NewInteger(0), + }, + Result: value.NewFloat(1), + }, +} + +func TestCosh(t *testing.T) { + testFunction(t, Cosh, coshTests) } var expTests = []functionTest{ @@ -541,6 +592,107 @@ func TestExpm1(t *testing.T) { testFunction(t, Expm1, expm1Tests) } +var isInfTests = []functionTest{ + { + Name: "IsInf", + Function: parser.Function{ + Name: "is_inf", + }, + Args: []value.Primary{ + value.NewFloat(math.Inf(1)), + }, + Result: value.NewTernary(ternary.TRUE), + }, + { + Name: "IsInf Not Inf", + Function: parser.Function{ + Name: "is_inf", + }, + Args: []value.Primary{ + value.NewFloat(-2.456), + }, + Result: value.NewTernary(ternary.FALSE), + }, + { + Name: "IsInf Not Float", + Function: parser.Function{ + Name: "is_inf", + }, + Args: []value.Primary{ + value.NewString("foo"), + }, + Result: value.NewTernary(ternary.FALSE), + }, + { + Name: "IsInf with Sign", + Function: parser.Function{ + Name: "is_inf", + }, + Args: []value.Primary{ + value.NewFloat(math.Inf(1)), + value.NewInteger(-1), + }, + Result: value.NewTernary(ternary.FALSE), + }, + { + Name: "IsInf Arguments Error", + Function: parser.Function{ + Name: "is_inf", + }, + Args: []value.Primary{}, + Error: "function is_inf takes 1 or 2 arguments", + }, +} + +func TestIsInf(t *testing.T) { + testFunction(t, IsInf, isInfTests) +} + +var isNanTests = []functionTest{ + { + Name: "IsNaN", + Function: parser.Function{ + Name: "is_nan", + }, + Args: []value.Primary{ + value.NewFloat(math.NaN()), + }, + Result: value.NewTernary(ternary.TRUE), + }, + { + Name: "IsNaN Not NaN", + Function: parser.Function{ + Name: "is_nan", + }, + Args: []value.Primary{ + value.NewFloat(-2.456), + }, + Result: value.NewTernary(ternary.FALSE), + }, + { + Name: "IsNaN Not Float", + Function: parser.Function{ + Name: "is_nan", + }, + Args: []value.Primary{ + value.NewString("foo"), + }, + Result: value.NewTernary(ternary.FALSE), + }, + { + Name: "IsNaN Arguments Error", + Function: parser.Function{ + Name: "is_nan", + }, + Args: []value.Primary{}, + Error: "function is_nan takes exactly 1 argument", + }, +} + +func TestIsNaN(t *testing.T) { + testFunction(t, IsNaN, isNanTests) +} + var mathLogTests = []functionTest{ { Name: "MathLog", @@ -575,23 +727,6 @@ func TestLog10(t *testing.T) { testFunction(t, Log10, log10Tests) } -var log2Tests = []functionTest{ - { - Name: "Log2", - Function: parser.Function{ - Name: "log2", - }, - Args: []value.Primary{ - value.NewFloat(16), - }, - Result: value.NewFloat(4), - }, -} - -func TestLog2(t *testing.T) { - testFunction(t, Log2, log2Tests) -} - var log1pTests = []functionTest{ { Name: "Log1p", @@ -609,31 +744,38 @@ func TestLog1p(t *testing.T) { testFunction(t, Log1p, log1pTests) } -var sqrtTests = []functionTest{ +var log2Tests = []functionTest{ { - Name: "Sqrt", + Name: "Log2", Function: parser.Function{ - Name: "sqrt", + Name: "log2", }, Args: []value.Primary{ - value.NewFloat(4), + value.NewFloat(16), }, - Result: value.NewFloat(2), + Result: value.NewFloat(4), }, +} + +func TestLog2(t *testing.T) { + testFunction(t, Log2, log2Tests) +} + +var logbTests = []functionTest{ { - Name: "Sqrt returns NaN", + Name: "Logb", Function: parser.Function{ - Name: "sqrt", + Name: "logb", }, Args: []value.Primary{ - value.NewFloat(-4), + value.NewInteger(2), }, - Result: value.NewFloat(math.NaN()), + Result: value.NewFloat(1), }, } -func TestSqrt(t *testing.T) { - testFunction(t, Sqrt, sqrtTests) +func TestLogb(t *testing.T) { + testFunction(t, Logb, logbTests) } var powTests = []functionTest{ @@ -695,6 +837,101 @@ func TestPow(t *testing.T) { testFunction(t, Pow, powTests) } +var sinTests = []functionTest{ + { + Name: "Sin", + Function: parser.Function{ + Name: "sin", + }, + Args: []value.Primary{ + value.NewInteger(1), + }, + Result: value.NewFloat(0.8414709848078965), + }, +} + +func TestSin(t *testing.T) { + testFunction(t, Sin, sinTests) +} + +var sinhTests = []functionTest{ + { + Name: "Sinh", + Function: parser.Function{ + Name: "sinh", + }, + Args: []value.Primary{ + value.NewInteger(0), + }, + Result: value.NewFloat(0), + }, +} + +func TestSinh(t *testing.T) { + testFunction(t, Sinh, sinhTests) +} + +var sqrtTests = []functionTest{ + { + Name: "Sqrt", + Function: parser.Function{ + Name: "sqrt", + }, + Args: []value.Primary{ + value.NewFloat(4), + }, + Result: value.NewFloat(2), + }, + { + Name: "Sqrt returns NaN", + Function: parser.Function{ + Name: "sqrt", + }, + Args: []value.Primary{ + value.NewFloat(-4), + }, + Result: value.NewFloat(math.NaN()), + }, +} + +func TestSqrt(t *testing.T) { + testFunction(t, Sqrt, sqrtTests) +} + +var tanTests = []functionTest{ + { + Name: "Tan", + Function: parser.Function{ + Name: "tan", + }, + Args: []value.Primary{ + value.NewInteger(2), + }, + Result: value.NewFloat(-2.185039863261519), + }, +} + +func TestTan(t *testing.T) { + testFunction(t, Tan, tanTests) +} + +var tanhTests = []functionTest{ + { + Name: "Tanh", + Function: parser.Function{ + Name: "tanh", + }, + Args: []value.Primary{ + value.NewInteger(0), + }, + Result: value.NewFloat(0), + }, +} + +func TestTanh(t *testing.T) { + testFunction(t, Tanh, tanhTests) +} + var binToDecTests = []functionTest{ { Name: "BinToDec", @@ -3525,6 +3762,41 @@ func TestUTC(t *testing.T) { testFunction(t, UTC, utcTests) } +var milliToDatetimeTests = []functionTest{ + { + Name: "MilliToDatetime", + Function: parser.Function{ + Name: "milli_to_datetime", + }, + Args: []value.Primary{ + value.NewInteger(1328260695001), + }, + Result: value.NewDatetime(time.Date(2012, 2, 3, 9, 18, 15, 1000000, GetTestLocation())), + }, + { + Name: "MilliToDatetime Invalid Argument", + Function: parser.Function{ + Name: "milli_to_datetime", + }, + Args: []value.Primary{ + value.NewString("abc"), + }, + Result: value.NewNull(), + }, + { + Name: "MilliToDatetime Arguments Error", + Function: parser.Function{ + Name: "milli_to_datetime", + }, + Args: []value.Primary{}, + Error: "function milli_to_datetime takes exactly 1 argument", + }, +} + +func TestMilliToDatetime(t *testing.T) { + testFunction(t, MilliToDatetime, milliToDatetimeTests) +} + var nanoToDatetimeTests = []functionTest{ { Name: "NanoToDatetime", diff --git a/lib/syntax/syntax.go b/lib/syntax/syntax.go index 17a9f95..fd01aff 100644 --- a/lib/syntax/syntax.go +++ b/lib/syntax/syntax.go @@ -1577,27 +1577,6 @@ var CsvqSyntax = []Expression{ { Label: "Numeric Functions", Grammar: []Definition{ - { - Name: "ceil", - Group: []Grammar{ - {Function{Name: "CEIL", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, - }, - Description: Description{Template: "Rounds %s up to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, - }, - { - Name: "floor", - Group: []Grammar{ - {Function{Name: "FLOOR", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, - }, - Description: Description{Template: "Rounds %s down to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, - }, - { - Name: "round", - Group: []Grammar{ - {Function{Name: "ROUND", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, - }, - Description: Description{Template: "Rounds %s to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, - }, { Name: "abs", Group: []Grammar{ @@ -1612,6 +1591,13 @@ var CsvqSyntax = []Expression{ }, Description: Description{Template: "Returns the arc cosine of %s.", Values: []Element{Float("number")}}, }, + { + Name: "acosh", + Group: []Grammar{ + {Function{Name: "ACOSH", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the inverse hyperbolic cosine of %s.", Values: []Element{Float("number")}}, + }, { Name: "asin", Group: []Grammar{ @@ -1619,6 +1605,13 @@ var CsvqSyntax = []Expression{ }, Description: Description{Template: "Returns the arc sine of %s.", Values: []Element{Float("number")}}, }, + { + Name: "asinh", + Group: []Grammar{ + {Function{Name: "ASINH", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the inverse hyperbolic sine of %s.", Values: []Element{Float("number")}}, + }, { Name: "atan", Group: []Grammar{ @@ -1634,25 +1627,39 @@ var CsvqSyntax = []Expression{ Description: Description{Template: "Returns the arc tangent of %s / %s, using the signs of the two to determine the quadrant of the return value.", Values: []Element{Float("number2"), Float("number1")}}, }, { - Name: "cos", + Name: "atanh", Group: []Grammar{ - {Function{Name: "COS", Args: []Element{Float("number")}, Return: Return("float")}}, + {Function{Name: "ATANH", Args: []Element{Float("number")}, Return: Return("float")}}, }, - Description: Description{Template: "Returns the cosine of %s.", Values: []Element{Float("number")}}, + Description: Description{Template: "Returns the inverse hyperbolic tangent of %s.", Values: []Element{Float("number")}}, }, { - Name: "sin", + Name: "cbrt", Group: []Grammar{ - {Function{Name: "SIN", Args: []Element{Float("number")}, Return: Return("float")}}, + {Function{Name: "CBRT", Args: []Element{Float("number")}, Return: Return("float")}}, }, - Description: Description{Template: "Returns the sine of %s.", Values: []Element{Float("number")}}, + Description: Description{Template: "Returns the cube root of %s.", Values: []Element{Float("number")}}, }, { - Name: "tan", + Name: "ceil", Group: []Grammar{ - {Function{Name: "TAN", Args: []Element{Float("number")}, Return: Return("float")}}, + {Function{Name: "CEIL", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, }, - Description: Description{Template: "Returns the tangent of %s.", Values: []Element{Float("number")}}, + Description: Description{Template: "Rounds %s up to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, + }, + { + Name: "cos", + Group: []Grammar{ + {Function{Name: "COS", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the cosine of %s.", Values: []Element{Float("number")}}, + }, + { + Name: "cosh", + Group: []Grammar{ + {Function{Name: "COSH", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the hyperbolic cosine of %s.", Values: []Element{Float("number")}}, }, { Name: "exp", @@ -1675,6 +1682,27 @@ var CsvqSyntax = []Expression{ }, Description: Description{Template: "Returns the value of base %s raised to the power of %s nimus %s.", Values: []Element{Italic("e"), Float("number"), Italic("1")}}, }, + { + Name: "floor", + Group: []Grammar{ + {Function{Name: "FLOOR", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, + }, + Description: Description{Template: "Rounds %s down to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, + }, + { + Name: "is_inf", + Group: []Grammar{ + {Function{Name: "IS_INF", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("sign"), Default: Integer("0")}}, Return: Return("ternary")}}, + }, + Description: Description{Template: "Returns %s is +INF or not when %s > 0, -INF or not when %s < 0, or either INF when %s = 0.", Values: []Element{Float("number"), Integer("sign"), Integer("sign"), Integer("sign")}}, + }, + { + Name: "is_nan", + Group: []Grammar{ + {Function{Name: "IS_NAN", Args: []Element{Float("number")}, Return: Return("ternary")}}, + }, + Description: Description{Template: "Returns whether %s is a NaN.", Values: []Element{Float("number")}}, + }, { Name: "log", Group: []Grammar{ @@ -1689,6 +1717,13 @@ var CsvqSyntax = []Expression{ }, Description: Description{Template: "Returns the decimal logarithm of %s.", Values: []Element{Float("number")}}, }, + { + Name: "log1p", + Group: []Grammar{ + {Function{Name: "LOG1P", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the natural logarithm of 1 plus %s.", Values: []Element{Float("number")}}, + }, { Name: "log2", Group: []Grammar{ @@ -1697,11 +1732,39 @@ var CsvqSyntax = []Expression{ Description: Description{Template: "Returns the binary logarithm of %s.", Values: []Element{Float("number")}}, }, { - Name: "log1p", + Name: "logb", Group: []Grammar{ - {Function{Name: "LOG1P", Args: []Element{Float("number")}, Return: Return("float")}}, + {Function{Name: "LOGB", Args: []Element{Float("number")}, Return: Return("float")}}, }, - Description: Description{Template: "Returns the natural logarithm of 1 plus %s.", Values: []Element{Float("number")}}, + Description: Description{Template: "Returns the binary exponent of %s.", Values: []Element{Float("number")}}, + }, + { + Name: "pow", + Group: []Grammar{ + {Function{Name: "POW", Args: []Element{Float("base"), Float("exponent")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the value of %s raised to the power of %s.", Values: []Element{Float("base"), Float("exponent")}}, + }, + { + Name: "round", + Group: []Grammar{ + {Function{Name: "ROUND", Args: []Element{Float("number"), ArgWithDefValue{Arg: Integer("place"), Default: Integer("0")}}, Return: Return("float")}}, + }, + Description: Description{Template: "Rounds %s to %s decimal place. If %s is a negative number, then %s represents the place in the integer part.", Values: []Element{Float("number"), Integer("place"), Integer("place"), Integer("place")}}, + }, + { + Name: "sin", + Group: []Grammar{ + {Function{Name: "SIN", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the sine of %s.", Values: []Element{Float("number")}}, + }, + { + Name: "sinh", + Group: []Grammar{ + {Function{Name: "SINH", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the hyperbolic sine of %s.", Values: []Element{Float("number")}}, }, { Name: "sqrt", @@ -1711,11 +1774,18 @@ var CsvqSyntax = []Expression{ Description: Description{Template: "Returns the square root of %s.", Values: []Element{Float("number")}}, }, { - Name: "pow", + Name: "tan", Group: []Grammar{ - {Function{Name: "POW", Args: []Element{Float("base"), Float("exponent")}, Return: Return("float")}}, + {Function{Name: "TAN", Args: []Element{Float("number")}, Return: Return("float")}}, }, - Description: Description{Template: "Returns the value of %s raised to the power of %s.", Values: []Element{Float("base"), Float("exponent")}}, + Description: Description{Template: "Returns the tangent of %s.", Values: []Element{Float("number")}}, + }, + { + Name: "tanh", + Group: []Grammar{ + {Function{Name: "TANH", Args: []Element{Float("number")}, Return: Return("float")}}, + }, + Description: Description{Template: "Returns the hyperbolic tangent of %s.", Values: []Element{Float("number")}}, }, { Name: "bin_to_dec", @@ -2052,6 +2122,20 @@ var CsvqSyntax = []Expression{ }, Description: Description{Template: "Returns the datetime value of %s in UTC.", Values: []Element{Datetime("datetime")}}, }, + { + Name: "milli_to_datetime", + Group: []Grammar{ + {Function{Name: "MILLI_TO_DATETIME", Args: []Element{Integer("unix_milli_time")}, Return: Return("datetime")}}, + }, + Description: Description{Template: "Returns the datetime value represented by %s.", Values: []Element{Integer("unix_milli_time")}}, + }, + { + Name: "nano_to_datetime", + Group: []Grammar{ + {Function{Name: "NANO_TO_DATETIME", Args: []Element{Integer("unix_nano_time")}, Return: Return("datetime")}}, + }, + Description: Description{Template: "Returns the datetime value represented by %s.", Values: []Element{Integer("unix_nano_time")}}, + }, }, }, { From 0af886241af2ae43b7b5f1d1c5a209233c576b46 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Mon, 4 Jul 2022 01:20:26 +0900 Subject: [PATCH 14/17] Rename the package cmd as option. --- lib/action/calc.go | 4 +- lib/action/run.go | 22 +- lib/cli/app.go | 68 ++--- lib/{cmd => option}/default_env.go | 2 +- lib/{cmd => option}/environment.go | 2 +- lib/{cmd => option}/environment_test.go | 2 +- lib/{cmd => option}/flags.go | 2 +- lib/{cmd => option}/flags_test.go | 4 +- lib/{cmd => option}/main_test.go | 2 +- lib/{cmd => option}/palette.go | 2 +- lib/{cmd => option}/static.go | 2 +- lib/{cmd => option}/static_test.go | 2 +- lib/{cmd => option}/utils.go | 2 +- lib/{cmd => option}/utils_test.go | 2 +- lib/parser/ast.go | 8 +- lib/parser/ast_test.go | 6 +- lib/parser/scanner.go | 8 +- lib/query/aggregate_function.go | 24 +- lib/query/built_in_command.go | 380 ++++++++++++------------ lib/query/built_in_command_test.go | 82 ++--- lib/query/encode.go | 62 ++-- lib/query/encode_test.go | 70 ++--- lib/query/eval.go | 6 +- lib/query/file_info.go | 112 +++---- lib/query/file_info_test.go | 72 ++--- lib/query/function.go | 280 ++++++++--------- lib/query/function_test.go | 4 +- lib/query/main_test.go | 12 +- lib/query/object_writer.go | 16 +- lib/query/object_writer_test.go | 6 +- lib/query/prepared_statement.go | 6 +- lib/query/processor.go | 8 +- lib/query/processor_test.go | 6 +- lib/query/query.go | 8 +- lib/query/query_test.go | 30 +- lib/query/reference_scope.go | 8 +- lib/query/session.go | 4 +- lib/query/sort_value.go | 10 +- lib/query/string_formatter.go | 6 +- lib/query/transaction.go | 154 +++++----- lib/query/transaction_test.go | 18 +- lib/query/utils.go | 12 +- lib/query/view.go | 60 ++-- lib/query/view_map.go | 4 +- lib/query/view_test.go | 70 ++--- lib/syntax/element.go | 18 +- lib/syntax/element_test.go | 52 ++-- lib/terminal/completer_readline.go | 80 ++--- lib/terminal/completer_readline_test.go | 10 +- lib/terminal/main_test.go | 8 +- lib/terminal/terminal.go | 6 +- lib/terminal/terminal_general.go | 4 +- lib/terminal/terminal_readline.go | 4 +- lib/value/comparison.go | 6 +- lib/value/conv.go | 10 +- lib/value/conv_test.go | 8 +- lib/value/type.go | 8 +- 57 files changed, 942 insertions(+), 942 deletions(-) rename lib/{cmd => option}/default_env.go (99%) rename lib/{cmd => option}/environment.go (99%) rename lib/{cmd => option}/environment_test.go (99%) rename lib/{cmd => option}/flags.go (99%) rename lib/{cmd => option}/flags_test.go (99%) rename lib/{cmd => option}/main_test.go (98%) rename lib/{cmd => option}/palette.go (98%) rename lib/{cmd => option}/static.go (98%) rename lib/{cmd => option}/static_test.go (98%) rename lib/{cmd => option}/utils.go (99%) rename lib/{cmd => option}/utils_test.go (99%) diff --git a/lib/action/calc.go b/lib/action/calc.go index bd4ff64..b4ce615 100644 --- a/lib/action/calc.go +++ b/lib/action/calc.go @@ -5,13 +5,13 @@ import ( "errors" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" ) func Calc(ctx context.Context, proc *query.Processor, expr string) error { - _ = proc.Tx.SetFlag(cmd.NoHeaderFlag, true) + _ = proc.Tx.SetFlag(option.NoHeaderFlag, true) q := "SELECT " + expr + " FROM STDIN" program, _, err := parser.Parse(q, "", false, proc.Tx.Flags.AnsiQuotes) diff --git a/lib/action/run.go b/lib/action/run.go index d6c9f7f..b6191c5 100644 --- a/lib/action/run.go +++ b/lib/action/run.go @@ -10,8 +10,8 @@ import ( "time" "unicode" - "github.com/mithrandie/csvq/lib/cmd" csvqfile "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/terminal" @@ -182,11 +182,11 @@ func showStats(ctx context.Context, proc *query.Processor, start time.Time) { var mem runtime.MemStats runtime.ReadMemStats(&mem) - exectime := cmd.FormatNumber(time.Since(start).Seconds(), 6, ".", ",", "") - talloc := cmd.FormatNumber(float64(mem.TotalAlloc), 0, ".", ",", "") - sys := cmd.FormatNumber(float64(mem.HeapSys), 0, ".", ",", "") - mallocs := cmd.FormatNumber(float64(mem.Mallocs), 0, ".", ",", "") - frees := cmd.FormatNumber(float64(mem.Frees), 0, ".", ",", "") + exectime := option.FormatNumber(time.Since(start).Seconds(), 6, ".", ",", "") + talloc := option.FormatNumber(float64(mem.TotalAlloc), 0, ".", ",", "") + sys := option.FormatNumber(float64(mem.HeapSys), 0, ".", ",", "") + mallocs := option.FormatNumber(float64(mem.Mallocs), 0, ".", ",", "") + frees := option.FormatNumber(float64(mem.Frees), 0, ".", ",", "") width := len(exectime) for _, v := range []string{talloc, sys, mallocs, frees} { @@ -197,23 +197,23 @@ func showStats(ctx context.Context, proc *query.Processor, start time.Time) { width = width + 1 w := query.NewObjectWriter(proc.Tx) - w.WriteColor(" TotalTime:", cmd.LableEffect) + w.WriteColor(" TotalTime:", option.LableEffect) w.WriteSpaces(width - len(exectime)) w.WriteWithoutLineBreak(exectime + " seconds") w.NewLine() - w.WriteColor("TotalAlloc:", cmd.LableEffect) + w.WriteColor("TotalAlloc:", option.LableEffect) w.WriteSpaces(width - len(talloc)) w.WriteWithoutLineBreak(talloc + " bytes") w.NewLine() - w.WriteColor(" HeapSys:", cmd.LableEffect) + w.WriteColor(" HeapSys:", option.LableEffect) w.WriteSpaces(width - len(sys)) w.WriteWithoutLineBreak(sys + " bytes") w.NewLine() - w.WriteColor(" Mallocs:", cmd.LableEffect) + w.WriteColor(" Mallocs:", option.LableEffect) w.WriteSpaces(width - len(mallocs)) w.WriteWithoutLineBreak(mallocs + " objects") w.NewLine() - w.WriteColor(" Frees:", cmd.LableEffect) + w.WriteColor(" Frees:", option.LableEffect) w.WriteSpaces(width - len(frees)) w.WriteWithoutLineBreak(frees + " objects") w.NewLine() diff --git a/lib/cli/app.go b/lib/cli/app.go index 1bef32c..7d233f2 100644 --- a/lib/cli/app.go +++ b/lib/cli/app.go @@ -7,8 +7,8 @@ import ( "os/signal" "github.com/mithrandie/csvq/lib/action" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" @@ -204,7 +204,7 @@ func Run() { &cli.IntFlag{ Name: "cpu", Aliases: []string{"p"}, - Value: cmd.GetDefaultNumberOfCPU(), + Value: option.GetDefaultNumberOfCPU(), Usage: "hint for the number of cpu cores to be used", }, &cli.BoolFlag{ @@ -371,67 +371,67 @@ func commandAction(fn func(ctx context.Context, c *cli.Context, proc *query.Proc func overwriteFlags(c *cli.Context, tx *query.Transaction) error { if c.IsSet("repository") { - if err := tx.SetFlag(cmd.RepositoryFlag, c.String("repository")); err != nil { + if err := tx.SetFlag(option.RepositoryFlag, c.String("repository")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("timezone") { - if err := tx.SetFlag(cmd.TimezoneFlag, c.String("timezone")); err != nil { + if err := tx.SetFlag(option.TimezoneFlag, c.String("timezone")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("datetime-format") { - _ = tx.SetFlag(cmd.DatetimeFormatFlag, c.String("datetime-format")) + _ = tx.SetFlag(option.DatetimeFormatFlag, c.String("datetime-format")) } if c.IsSet("ansi-quotes") { - _ = tx.SetFlag(cmd.AnsiQuotesFlag, c.Bool("ansi-quotes")) + _ = tx.SetFlag(option.AnsiQuotesFlag, c.Bool("ansi-quotes")) } if c.IsSet("strict-equal") { - _ = tx.SetFlag(cmd.StrictEqualFlag, c.Bool("strict-equal")) + _ = tx.SetFlag(option.StrictEqualFlag, c.Bool("strict-equal")) } if c.IsSet("wait-timeout") { - _ = tx.SetFlag(cmd.WaitTimeoutFlag, c.Float64("wait-timeout")) + _ = tx.SetFlag(option.WaitTimeoutFlag, c.Float64("wait-timeout")) } if c.IsSet("color") { - _ = tx.SetFlag(cmd.ColorFlag, c.Bool("color")) + _ = tx.SetFlag(option.ColorFlag, c.Bool("color")) } if c.IsSet("import-format") { - if err := tx.SetFlag(cmd.ImportFormatFlag, c.String("import-format")); err != nil { + if err := tx.SetFlag(option.ImportFormatFlag, c.String("import-format")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("delimiter") { - if err := tx.SetFlag(cmd.DelimiterFlag, c.String("delimiter")); err != nil { + if err := tx.SetFlag(option.DelimiterFlag, c.String("delimiter")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("allow-uneven-fields") { - _ = tx.SetFlag(cmd.AllowUnevenFieldsFlag, c.Bool("allow-uneven-fields")) + _ = tx.SetFlag(option.AllowUnevenFieldsFlag, c.Bool("allow-uneven-fields")) } if c.IsSet("delimiter-positions") { - if err := tx.SetFlag(cmd.DelimiterPositionsFlag, c.String("delimiter-positions")); err != nil { + if err := tx.SetFlag(option.DelimiterPositionsFlag, c.String("delimiter-positions")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("json-query") { - _ = tx.SetFlag(cmd.JsonQueryFlag, c.String("json-query")) + _ = tx.SetFlag(option.JsonQueryFlag, c.String("json-query")) } if c.IsSet("encoding") { - if err := tx.SetFlag(cmd.EncodingFlag, c.String("encoding")); err != nil { + if err := tx.SetFlag(option.EncodingFlag, c.String("encoding")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("no-header") { - _ = tx.SetFlag(cmd.NoHeaderFlag, c.Bool("no-header")) + _ = tx.SetFlag(option.NoHeaderFlag, c.Bool("no-header")) } if c.IsSet("without-null") { - _ = tx.SetFlag(cmd.WithoutNullFlag, c.Bool("without-null")) + _ = tx.SetFlag(option.WithoutNullFlag, c.Bool("without-null")) } if c.IsSet("strip-ending-line-break") { - _ = tx.SetFlag(cmd.StripEndingLineBreakFlag, c.Bool("strip-ending-line-break")) + _ = tx.SetFlag(option.StripEndingLineBreakFlag, c.Bool("strip-ending-line-break")) } if err := tx.SetFormatFlag(c.String("format"), c.String("out")); err != nil { @@ -439,68 +439,68 @@ func overwriteFlags(c *cli.Context, tx *query.Transaction) error { } if c.IsSet("write-encoding") { - if err := tx.SetFlag(cmd.ExportEncodingFlag, c.String("write-encoding")); err != nil { + if err := tx.SetFlag(option.ExportEncodingFlag, c.String("write-encoding")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("write-delimiter") { - if err := tx.SetFlag(cmd.ExportDelimiterFlag, c.String("write-delimiter")); err != nil { + if err := tx.SetFlag(option.ExportDelimiterFlag, c.String("write-delimiter")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("write-delimiter-positions") { - if err := tx.SetFlag(cmd.ExportDelimiterPositionsFlag, c.String("write-delimiter-positions")); err != nil { + if err := tx.SetFlag(option.ExportDelimiterPositionsFlag, c.String("write-delimiter-positions")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("without-header") { - _ = tx.SetFlag(cmd.WithoutHeaderFlag, c.Bool("without-header")) + _ = tx.SetFlag(option.WithoutHeaderFlag, c.Bool("without-header")) } if c.IsSet("line-break") { - if err := tx.SetFlag(cmd.LineBreakFlag, c.String("line-break")); err != nil { + if err := tx.SetFlag(option.LineBreakFlag, c.String("line-break")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("enclose-all") { - _ = tx.SetFlag(cmd.EncloseAllFlag, c.Bool("enclose-all")) + _ = tx.SetFlag(option.EncloseAllFlag, c.Bool("enclose-all")) } if c.IsSet("json-escape") { - if err := tx.SetFlag(cmd.JsonEscapeFlag, c.String("json-escape")); err != nil { + if err := tx.SetFlag(option.JsonEscapeFlag, c.String("json-escape")); err != nil { return query.NewIncorrectCommandUsageError(err.Error()) } } if c.IsSet("pretty-print") { - _ = tx.SetFlag(cmd.PrettyPrintFlag, c.Bool("pretty-print")) + _ = tx.SetFlag(option.PrettyPrintFlag, c.Bool("pretty-print")) } if c.IsSet("east-asian-encoding") { - _ = tx.SetFlag(cmd.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) + _ = tx.SetFlag(option.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) } if c.IsSet("count-diacritical-sign") { - _ = tx.SetFlag(cmd.CountDiacriticalSignFlag, c.Bool("count-diacritical-sign")) + _ = tx.SetFlag(option.CountDiacriticalSignFlag, c.Bool("count-diacritical-sign")) } if c.IsSet("count-format-code") { - _ = tx.SetFlag(cmd.CountFormatCodeFlag, c.Bool("count-format-code")) + _ = tx.SetFlag(option.CountFormatCodeFlag, c.Bool("count-format-code")) } if c.IsSet("quiet") { - _ = tx.SetFlag(cmd.QuietFlag, c.Bool("quiet")) + _ = tx.SetFlag(option.QuietFlag, c.Bool("quiet")) } if c.IsSet("limit-recursion") { - _ = tx.SetFlag(cmd.LimitRecursion, c.Int64("limit-recursion")) + _ = tx.SetFlag(option.LimitRecursion, c.Int64("limit-recursion")) } if c.IsSet("cpu") { - _ = tx.SetFlag(cmd.CPUFlag, c.Int64("cpu")) + _ = tx.SetFlag(option.CPUFlag, c.Int64("cpu")) } if c.IsSet("stats") { - _ = tx.SetFlag(cmd.StatsFlag, c.Bool("stats")) + _ = tx.SetFlag(option.StatsFlag, c.Bool("stats")) } return nil } func runPreloadCommands(ctx context.Context, proc *query.Processor) (err error) { - files := cmd.GetSpecialFilePath(cmd.PreloadCommandFileName) + files := option.GetSpecialFilePath(option.PreloadCommandFileName) for _, fpath := range files { if !file.Exists(fpath) { continue diff --git a/lib/cmd/default_env.go b/lib/option/default_env.go similarity index 99% rename from lib/cmd/default_env.go rename to lib/option/default_env.go index 9ad868a..b4560b7 100644 --- a/lib/cmd/default_env.go +++ b/lib/option/default_env.go @@ -1,4 +1,4 @@ -package cmd +package option const DefaultEnvJson = ` { diff --git a/lib/cmd/environment.go b/lib/option/environment.go similarity index 99% rename from lib/cmd/environment.go rename to lib/option/environment.go index b6b6dc5..d181c08 100644 --- a/lib/cmd/environment.go +++ b/lib/option/environment.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "bytes" diff --git a/lib/cmd/environment_test.go b/lib/option/environment_test.go similarity index 99% rename from lib/cmd/environment_test.go rename to lib/option/environment_test.go index af72b8f..eb5a767 100644 --- a/lib/cmd/environment_test.go +++ b/lib/option/environment_test.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "os" diff --git a/lib/cmd/flags.go b/lib/option/flags.go similarity index 99% rename from lib/cmd/flags.go rename to lib/option/flags.go index e090a63..472f89e 100644 --- a/lib/cmd/flags.go +++ b/lib/option/flags.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "encoding/json" diff --git a/lib/cmd/flags_test.go b/lib/option/flags_test.go similarity index 99% rename from lib/cmd/flags_test.go rename to lib/option/flags_test.go index 2cf26a3..998fa7d 100644 --- a/lib/cmd/flags_test.go +++ b/lib/option/flags_test.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "path/filepath" @@ -62,7 +62,7 @@ func TestFlags_SetRepository(t *testing.T) { t.Errorf("repository = %s, expect to set %q for %q", flags.Repository, "", "") } - dir := filepath.Join("..", "..", "lib", "cmd") + dir := filepath.Join("..", "..", "lib", "option") absdir, _ := filepath.Abs(dir) _ = flags.SetRepository(dir) if flags.Repository != absdir { diff --git a/lib/cmd/main_test.go b/lib/option/main_test.go similarity index 98% rename from lib/cmd/main_test.go rename to lib/option/main_test.go index dd2936e..783dd49 100644 --- a/lib/cmd/main_test.go +++ b/lib/option/main_test.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "io" diff --git a/lib/cmd/palette.go b/lib/option/palette.go similarity index 98% rename from lib/cmd/palette.go rename to lib/option/palette.go index b6562b5..94ed13a 100644 --- a/lib/cmd/palette.go +++ b/lib/option/palette.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "errors" diff --git a/lib/cmd/static.go b/lib/option/static.go similarity index 98% rename from lib/cmd/static.go rename to lib/option/static.go index 22990a6..c7d33ae 100644 --- a/lib/cmd/static.go +++ b/lib/option/static.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "fmt" diff --git a/lib/cmd/static_test.go b/lib/option/static_test.go similarity index 98% rename from lib/cmd/static_test.go rename to lib/option/static_test.go index 1dd7332..49b68ad 100644 --- a/lib/cmd/static_test.go +++ b/lib/option/static_test.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "testing" diff --git a/lib/cmd/utils.go b/lib/option/utils.go similarity index 99% rename from lib/cmd/utils.go rename to lib/option/utils.go index 55bed8f..9986e03 100644 --- a/lib/cmd/utils.go +++ b/lib/option/utils.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "bytes" diff --git a/lib/cmd/utils_test.go b/lib/option/utils_test.go similarity index 99% rename from lib/cmd/utils_test.go rename to lib/option/utils_test.go index 73da940..4206345 100644 --- a/lib/cmd/utils_test.go +++ b/lib/option/utils_test.go @@ -1,4 +1,4 @@ -package cmd +package option import ( "reflect" diff --git a/lib/parser/ast.go b/lib/parser/ast.go index 2b49b4e..e71a6c2 100644 --- a/lib/parser/ast.go +++ b/lib/parser/ast.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/ternary" @@ -145,7 +145,7 @@ func (e PrimitiveType) String() string { if 0 < len(e.Literal) { switch e.Value.(type) { case *value.String, *value.Datetime: - return cmd.QuoteString(e.Literal) + return option.QuoteString(e.Literal) default: return e.Literal } @@ -180,7 +180,7 @@ type Identifier struct { func (i Identifier) String() string { if i.Quoted { - return cmd.QuoteIdentifier(i.Literal) + return option.QuoteIdentifier(i.Literal) } return i.Literal } @@ -1195,7 +1195,7 @@ type EnvironmentVariable struct { func (e EnvironmentVariable) String() string { name := e.Name if e.Quoted { - name = cmd.QuoteIdentifier(name) + name = option.QuoteIdentifier(name) } return string(VariableSign) + string(EnvironmentVariableSign) + name diff --git a/lib/parser/ast_test.go b/lib/parser/ast_test.go index 3618fa2..855ac48 100644 --- a/lib/parser/ast_test.go +++ b/lib/parser/ast_test.go @@ -7,7 +7,7 @@ import ( "github.com/mithrandie/ternary" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" ) @@ -139,8 +139,8 @@ func TestIdentifier_String(t *testing.T) { s = "abcde" e = Identifier{Literal: s, Quoted: true} - if e.String() != cmd.QuoteIdentifier(s) { - t.Errorf("string = %q, want %q for %#v", e.String(), cmd.QuoteIdentifier(s), e) + if e.String() != option.QuoteIdentifier(s) { + t.Errorf("string = %q, want %q for %#v", e.String(), option.QuoteIdentifier(s), e) } } diff --git a/lib/parser/scanner.go b/lib/parser/scanner.go index de73e9f..e346b72 100644 --- a/lib/parser/scanner.go +++ b/lib/parser/scanner.go @@ -8,7 +8,7 @@ import ( "strings" "unicode" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/ternary" ) @@ -286,7 +286,7 @@ func (s *Scanner) Scan() (Token, error) { if token == ENVIRONMENT_VARIABLE && s.peek() == '`' { err = s.scanString(s.next()) - literal = cmd.UnescapeIdentifier(s.literal.String(), '`') + literal = option.UnescapeIdentifier(s.literal.String(), '`') quoted = true } else { if s.isIdentRune(s.peek()) { @@ -313,11 +313,11 @@ func (s *Scanner) Scan() (Token, error) { default: if ch == '\'' || (!s.ansiQuotes && ch == '"') { err = s.scanString(ch) - literal = cmd.UnescapeString(s.literal.String(), ch) + literal = option.UnescapeString(s.literal.String(), ch) token = STRING } else if ch == '`' || (s.ansiQuotes && ch == '"') { err = s.scanString(ch) - literal = cmd.UnescapeIdentifier(s.literal.String(), ch) + literal = option.UnescapeIdentifier(s.literal.String(), ch) token = IDENTIFIER quoted = true } diff --git a/lib/query/aggregate_function.go b/lib/query/aggregate_function.go index f0d8ed0..37eb826 100644 --- a/lib/query/aggregate_function.go +++ b/lib/query/aggregate_function.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/json" "github.com/mithrandie/csvq/lib/value" @@ -14,7 +14,7 @@ import ( "github.com/mithrandie/ternary" ) -type AggregateFunction func([]value.Primary, *cmd.Flags) value.Primary +type AggregateFunction func([]value.Primary, *option.Flags) value.Primary var AggregateFunctions = map[string]AggregateFunction{ "COUNT": Count, @@ -29,7 +29,7 @@ var AggregateFunctions = map[string]AggregateFunction{ "MEDIAN": Median, } -func Count(list []value.Primary, _ *cmd.Flags) value.Primary { +func Count(list []value.Primary, _ *option.Flags) value.Primary { var count int64 for _, v := range list { if !value.IsNull(v) { @@ -40,7 +40,7 @@ func Count(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewInteger(count) } -func Max(list []value.Primary, flags *cmd.Flags) value.Primary { +func Max(list []value.Primary, flags *option.Flags) value.Primary { var result value.Primary result = value.NewNull() @@ -62,7 +62,7 @@ func Max(list []value.Primary, flags *cmd.Flags) value.Primary { return result } -func Min(list []value.Primary, flags *cmd.Flags) value.Primary { +func Min(list []value.Primary, flags *option.Flags) value.Primary { var result value.Primary result = value.NewNull() @@ -84,7 +84,7 @@ func Min(list []value.Primary, flags *cmd.Flags) value.Primary { return result } -func Sum(list []value.Primary, _ *cmd.Flags) value.Primary { +func Sum(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 1 { return value.NewNull() @@ -92,7 +92,7 @@ func Sum(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewFloat(sum(values)) } -func Avg(list []value.Primary, _ *cmd.Flags) value.Primary { +func Avg(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 1 { return value.NewNull() @@ -100,7 +100,7 @@ func Avg(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewFloat(average(values)) } -func StdEV(list []value.Primary, _ *cmd.Flags) value.Primary { +func StdEV(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 2 { return value.NewNull() @@ -108,7 +108,7 @@ func StdEV(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewFloat(standardDeviation(values, false)) } -func StdEVP(list []value.Primary, _ *cmd.Flags) value.Primary { +func StdEVP(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 1 { return value.NewNull() @@ -116,7 +116,7 @@ func StdEVP(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewFloat(standardDeviation(values, true)) } -func Var(list []value.Primary, _ *cmd.Flags) value.Primary { +func Var(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 2 { return value.NewNull() @@ -124,7 +124,7 @@ func Var(list []value.Primary, _ *cmd.Flags) value.Primary { return value.NewFloat(variance(values, false)) } -func VarP(list []value.Primary, _ *cmd.Flags) value.Primary { +func VarP(list []value.Primary, _ *option.Flags) value.Primary { values := floatList(list) if len(values) < 1 { return value.NewNull() @@ -184,7 +184,7 @@ func standardDeviation(list []float64, isP bool) float64 { return math.Sqrt(variance(list, isP)) } -func Median(list []value.Primary, flags *cmd.Flags) value.Primary { +func Median(list []value.Primary, flags *option.Flags) value.Primary { var values []float64 for _, v := range list { diff --git a/lib/query/built_in_command.go b/lib/query/built_in_command.go index 1809e9c..73f5e4e 100644 --- a/lib/query/built_in_command.go +++ b/lib/query/built_in_command.go @@ -9,8 +9,8 @@ import ( "strconv" "strings" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/syntax" "github.com/mithrandie/csvq/lib/value" @@ -214,32 +214,32 @@ func SetFlag(ctx context.Context, scope *ReferenceScope, expr parser.SetFlag) er } switch strings.ToUpper(expr.Flag.Name) { - case cmd.RepositoryFlag, cmd.TimezoneFlag, cmd.DatetimeFormatFlag, - cmd.ImportFormatFlag, cmd.DelimiterFlag, cmd.DelimiterPositionsFlag, cmd.JsonQueryFlag, cmd.EncodingFlag, - cmd.ExportEncodingFlag, cmd.FormatFlag, cmd.ExportDelimiterFlag, cmd.ExportDelimiterPositionsFlag, - cmd.LineBreakFlag, cmd.JsonEscapeFlag: + case option.RepositoryFlag, option.TimezoneFlag, option.DatetimeFormatFlag, + option.ImportFormatFlag, option.DelimiterFlag, option.DelimiterPositionsFlag, option.JsonQueryFlag, option.EncodingFlag, + option.ExportEncodingFlag, option.FormatFlag, option.ExportDelimiterFlag, option.ExportDelimiterPositionsFlag, + option.LineBreakFlag, option.JsonEscapeFlag: p = value.ToString(v) if value.IsNull(p) { return NewFlagValueNotAllowedFormatError(expr) } val = p.(*value.String).Raw() - case cmd.AnsiQuotesFlag, cmd.StrictEqualFlag, cmd.AllowUnevenFieldsFlag, - cmd.NoHeaderFlag, cmd.WithoutNullFlag, cmd.WithoutHeaderFlag, cmd.EncloseAllFlag, - cmd.PrettyPrintFlag, cmd.StripEndingLineBreakFlag, - cmd.EastAsianEncodingFlag, cmd.CountDiacriticalSignFlag, cmd.CountFormatCodeFlag, cmd.ColorFlag, - cmd.QuietFlag, cmd.StatsFlag: + case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, + option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, option.EncloseAllFlag, + option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, + option.QuietFlag, option.StatsFlag: p = value.ToBoolean(v) if value.IsNull(p) { return NewFlagValueNotAllowedFormatError(expr) } val = p.(*value.Boolean).Raw() - case cmd.WaitTimeoutFlag: + case option.WaitTimeoutFlag: p = value.ToFloat(v) if value.IsNull(p) { return NewFlagValueNotAllowedFormatError(expr) } val = p.(*value.Float).Raw() - case cmd.LimitRecursion, cmd.CPUFlag: + case option.LimitRecursion, option.CPUFlag: p = value.ToInteger(v) if value.IsNull(p) { return NewFlagValueNotAllowedFormatError(expr) @@ -259,23 +259,23 @@ func SetFlag(ctx context.Context, scope *ReferenceScope, expr parser.SetFlag) er func AddFlagElement(ctx context.Context, scope *ReferenceScope, expr parser.AddFlagElement) error { switch strings.ToUpper(expr.Flag.Name) { - case cmd.DatetimeFormatFlag: + case option.DatetimeFormatFlag: e := parser.SetFlag{ BaseExpr: expr.GetBaseExpr(), Flag: expr.Flag, Value: expr.Value, } return SetFlag(ctx, scope, e) - case cmd.RepositoryFlag, cmd.TimezoneFlag, cmd.AnsiQuotesFlag, cmd.StrictEqualFlag, - cmd.ImportFormatFlag, cmd.DelimiterFlag, cmd.AllowUnevenFieldsFlag, cmd.DelimiterPositionsFlag, - cmd.JsonQueryFlag, cmd.EncodingFlag, - cmd.ExportEncodingFlag, cmd.FormatFlag, cmd.ExportDelimiterFlag, cmd.ExportDelimiterPositionsFlag, - cmd.LineBreakFlag, cmd.JsonEscapeFlag, cmd.NoHeaderFlag, cmd.WithoutNullFlag, cmd.WithoutHeaderFlag, - cmd.EncloseAllFlag, cmd.PrettyPrintFlag, cmd.StripEndingLineBreakFlag, - cmd.EastAsianEncodingFlag, cmd.CountDiacriticalSignFlag, cmd.CountFormatCodeFlag, cmd.ColorFlag, - cmd.QuietFlag, cmd.StatsFlag, - cmd.WaitTimeoutFlag, - cmd.LimitRecursion, cmd.CPUFlag: + case option.RepositoryFlag, option.TimezoneFlag, option.AnsiQuotesFlag, option.StrictEqualFlag, + option.ImportFormatFlag, option.DelimiterFlag, option.AllowUnevenFieldsFlag, option.DelimiterPositionsFlag, + option.JsonQueryFlag, option.EncodingFlag, + option.ExportEncodingFlag, option.FormatFlag, option.ExportDelimiterFlag, option.ExportDelimiterPositionsFlag, + option.LineBreakFlag, option.JsonEscapeFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, + option.EncloseAllFlag, option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, + option.QuietFlag, option.StatsFlag, + option.WaitTimeoutFlag, + option.LimitRecursion, option.CPUFlag: return NewAddFlagNotSupportedNameError(expr) default: @@ -293,7 +293,7 @@ func RemoveFlagElement(ctx context.Context, scope *ReferenceScope, expr parser.R defer scope.Tx.operationMutex.Unlock() switch strings.ToUpper(expr.Flag.Name) { - case cmd.DatetimeFormatFlag: + case option.DatetimeFormatFlag: if i := value.ToInteger(p); !value.IsNull(i) { idx := int(i.(*value.Integer).Raw()) value.Discard(i) @@ -315,16 +315,16 @@ func RemoveFlagElement(ctx context.Context, scope *ReferenceScope, expr parser.R } else { return NewInvalidFlagValueToBeRemovedError(expr) } - case cmd.RepositoryFlag, cmd.TimezoneFlag, cmd.AnsiQuotesFlag, cmd.StrictEqualFlag, - cmd.ImportFormatFlag, cmd.DelimiterFlag, cmd.AllowUnevenFieldsFlag, cmd.DelimiterPositionsFlag, - cmd.JsonQueryFlag, cmd.EncodingFlag, - cmd.ExportEncodingFlag, cmd.FormatFlag, cmd.ExportDelimiterFlag, cmd.ExportDelimiterPositionsFlag, - cmd.LineBreakFlag, cmd.JsonEscapeFlag, cmd.NoHeaderFlag, cmd.WithoutNullFlag, cmd.WithoutHeaderFlag, - cmd.EncloseAllFlag, cmd.PrettyPrintFlag, cmd.StripEndingLineBreakFlag, - cmd.EastAsianEncodingFlag, cmd.CountDiacriticalSignFlag, cmd.CountFormatCodeFlag, cmd.ColorFlag, - cmd.QuietFlag, cmd.StatsFlag, - cmd.WaitTimeoutFlag, - cmd.LimitRecursion, cmd.CPUFlag: + case option.RepositoryFlag, option.TimezoneFlag, option.AnsiQuotesFlag, option.StrictEqualFlag, + option.ImportFormatFlag, option.DelimiterFlag, option.AllowUnevenFieldsFlag, option.DelimiterPositionsFlag, + option.JsonQueryFlag, option.EncodingFlag, + option.ExportEncodingFlag, option.FormatFlag, option.ExportDelimiterFlag, option.ExportDelimiterPositionsFlag, + option.LineBreakFlag, option.JsonEscapeFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, + option.EncloseAllFlag, option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, + option.QuietFlag, option.StatsFlag, + option.WaitTimeoutFlag, + option.LimitRecursion, option.CPUFlag: return NewRemoveFlagNotSupportedNameError(expr) default: @@ -340,7 +340,7 @@ func ShowFlag(tx *Transaction, expr parser.ShowFlag) (string, error) { return s, NewInvalidFlagNameError(expr.Flag) } - return tx.Palette.Render(cmd.LableEffect, cmd.FlagSymbol(strings.ToUpper(expr.Flag.Name))+":") + " " + s, nil + return tx.Palette.Render(option.LableEffect, option.FlagSymbol(strings.ToUpper(expr.Flag.Name))+":") + " " + s, nil } func showFlag(tx *Transaction, flagName string) (string, bool) { @@ -352,113 +352,113 @@ func showFlag(tx *Transaction, flagName string) (string, bool) { var s string switch strings.ToUpper(flagName) { - case cmd.RepositoryFlag: + case option.RepositoryFlag: p := val.(*value.String) if len(p.Raw()) < 1 { wd, _ := os.Getwd() - s = tx.Palette.Render(cmd.NullEffect, fmt.Sprintf("(current dir: %s)", wd)) + s = tx.Palette.Render(option.NullEffect, fmt.Sprintf("(current dir: %s)", wd)) } else { - s = tx.Palette.Render(cmd.StringEffect, p.Raw()) + s = tx.Palette.Render(option.StringEffect, p.Raw()) } - case cmd.DatetimeFormatFlag: + case option.DatetimeFormatFlag: p := val.(*value.String) if len(p.Raw()) < 1 { - s = tx.Palette.Render(cmd.NullEffect, "(not set)") + s = tx.Palette.Render(option.NullEffect, "(not set)") } else { - s = tx.Palette.Render(cmd.StringEffect, p.Raw()) + s = tx.Palette.Render(option.StringEffect, p.Raw()) } - case cmd.JsonQueryFlag: + case option.JsonQueryFlag: p := val.(*value.String) if len(p.Raw()) < 1 { - s = tx.Palette.Render(cmd.NullEffect, "(empty)") + s = tx.Palette.Render(option.NullEffect, "(empty)") } else { - s = tx.Palette.Render(cmd.StringEffect, p.Raw()) + s = tx.Palette.Render(option.StringEffect, p.Raw()) } - case cmd.ExportEncodingFlag: + case option.ExportEncodingFlag: switch tx.Flags.ExportOptions.Format { - case cmd.JSON, cmd.JSONL: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) + case option.JSON, option.JSONL: + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) default: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).Raw()) + s = tx.Palette.Render(option.StringEffect, val.(*value.String).Raw()) } - case cmd.ExportDelimiterFlag: + case option.ExportDelimiterFlag: switch tx.Flags.ExportOptions.Format { - case cmd.CSV: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).String()) + case option.CSV: + s = tx.Palette.Render(option.StringEffect, val.(*value.String).String()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.String).String()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.String).String()) } - case cmd.ExportDelimiterPositionsFlag: + case option.ExportDelimiterPositionsFlag: switch tx.Flags.ExportOptions.Format { - case cmd.FIXED: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).Raw()) + case option.FIXED: + s = tx.Palette.Render(option.StringEffect, val.(*value.String).Raw()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) } - case cmd.WithoutHeaderFlag: + case option.WithoutHeaderFlag: switch tx.Flags.ExportOptions.Format { - case cmd.CSV, cmd.TSV, cmd.FIXED, cmd.GFM, cmd.ORG: - if tx.Flags.ExportOptions.Format == cmd.FIXED && tx.Flags.ExportOptions.SingleLine { - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) + case option.CSV, option.TSV, option.FIXED, option.GFM, option.ORG: + if tx.Flags.ExportOptions.Format == option.FIXED && tx.Flags.ExportOptions.SingleLine { + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) } else { - s = tx.Palette.Render(cmd.BooleanEffect, val.(*value.Boolean).String()) + s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) } default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) } - case cmd.LineBreakFlag: - if tx.Flags.ExportOptions.Format == cmd.FIXED && tx.Flags.ExportOptions.SingleLine { - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) + case option.LineBreakFlag: + if tx.Flags.ExportOptions.Format == option.FIXED && tx.Flags.ExportOptions.SingleLine { + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) } else { - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).Raw()) + s = tx.Palette.Render(option.StringEffect, val.(*value.String).Raw()) } - case cmd.EncloseAllFlag: + case option.EncloseAllFlag: switch tx.Flags.ExportOptions.Format { - case cmd.CSV, cmd.TSV: - s = tx.Palette.Render(cmd.BooleanEffect, val.(*value.Boolean).String()) + case option.CSV, option.TSV: + s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) } - case cmd.JsonEscapeFlag: + case option.JsonEscapeFlag: switch tx.Flags.ExportOptions.Format { - case cmd.JSON, cmd.JSONL: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).Raw()) + case option.JSON, option.JSONL: + s = tx.Palette.Render(option.StringEffect, val.(*value.String).Raw()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.String).Raw()) } - case cmd.PrettyPrintFlag: + case option.PrettyPrintFlag: switch tx.Flags.ExportOptions.Format { - case cmd.JSON, cmd.JSONL: - s = tx.Palette.Render(cmd.BooleanEffect, val.(*value.Boolean).String()) + case option.JSON, option.JSONL: + s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) } - case cmd.EastAsianEncodingFlag, cmd.CountDiacriticalSignFlag, cmd.CountFormatCodeFlag: + case option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag: switch tx.Flags.ExportOptions.Format { - case cmd.GFM, cmd.ORG, cmd.BOX, cmd.TEXT: - s = tx.Palette.Render(cmd.BooleanEffect, val.(*value.Boolean).String()) + case option.GFM, option.ORG, option.BOX, option.TEXT: + s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) default: - s = tx.Palette.Render(cmd.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) + s = tx.Palette.Render(option.NullEffect, IgnoredFlagPrefix+val.(*value.Boolean).String()) } - case cmd.DelimiterFlag: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).String()) - case cmd.TimezoneFlag, cmd.ImportFormatFlag, cmd.DelimiterPositionsFlag, cmd.EncodingFlag, cmd.FormatFlag: - s = tx.Palette.Render(cmd.StringEffect, val.(*value.String).Raw()) - case cmd.LimitRecursion: + case option.DelimiterFlag: + s = tx.Palette.Render(option.StringEffect, val.(*value.String).String()) + case option.TimezoneFlag, option.ImportFormatFlag, option.DelimiterPositionsFlag, option.EncodingFlag, option.FormatFlag: + s = tx.Palette.Render(option.StringEffect, val.(*value.String).Raw()) + case option.LimitRecursion: p := val.(*value.Integer) if p.Raw() < 0 { - s = tx.Palette.Render(cmd.NullEffect, "(no limit)") + s = tx.Palette.Render(option.NullEffect, "(no limit)") } else { - s = tx.Palette.Render(cmd.NumberEffect, p.String()) + s = tx.Palette.Render(option.NumberEffect, p.String()) } - case cmd.CPUFlag: - s = tx.Palette.Render(cmd.NumberEffect, val.(*value.Integer).String()) - case cmd.WaitTimeoutFlag: - s = tx.Palette.Render(cmd.NumberEffect, val.(*value.Float).String()) - case cmd.AnsiQuotesFlag, cmd.StrictEqualFlag, cmd.AllowUnevenFieldsFlag, - cmd.NoHeaderFlag, cmd.WithoutNullFlag, cmd.StripEndingLineBreakFlag, - cmd.ColorFlag, cmd.QuietFlag, cmd.StatsFlag: - s = tx.Palette.Render(cmd.BooleanEffect, val.(*value.Boolean).String()) + case option.CPUFlag: + s = tx.Palette.Render(option.NumberEffect, val.(*value.Integer).String()) + case option.WaitTimeoutFlag: + s = tx.Palette.Render(option.NumberEffect, val.(*value.Float).String()) + case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, + option.NoHeaderFlag, option.WithoutNullFlag, option.StripEndingLineBreakFlag, + option.ColorFlag, option.QuietFlag, option.StatsFlag: + s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) } return s, true @@ -485,11 +485,11 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) ufpath := strings.ToUpper(info.Path) if _, ok := createdFiles[ufpath]; ok { - w.WriteColor("*Created* ", cmd.EmphasisEffect) + w.WriteColor("*Created* ", option.EmphasisEffect) } else if _, ok := updatedFiles[ufpath]; ok { - w.WriteColor("*Updated* ", cmd.EmphasisEffect) + w.WriteColor("*Updated* ", option.EmphasisEffect) } - w.WriteColorWithoutLineBreak(info.Path, cmd.ObjectEffect) + w.WriteColorWithoutLineBreak(info.Path, option.ObjectEffect) writeFields(w, fields) w.NewLine() @@ -504,7 +504,7 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) w.Title1 = "Loaded Tables" if 0 < uncommitted { w.Title2 = fmt.Sprintf("(Uncommitted: %s)", FormatCount(uncommitted, "Table")) - w.Title2Effect = cmd.EmphasisEffect + w.Title2Effect = option.EmphasisEffect } s = "\n" + w.String() + "\n" } @@ -525,9 +525,9 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) ufpath := strings.ToUpper(info.Path) if _, ok := updatedViews[ufpath]; ok { - w.WriteColor("*Updated* ", cmd.EmphasisEffect) + w.WriteColor("*Updated* ", option.EmphasisEffect) } - w.WriteColorWithoutLineBreak(info.Path, cmd.ObjectEffect) + w.WriteColorWithoutLineBreak(info.Path, option.ObjectEffect) writeFields(w, fields) w.ClearBlock() w.NewLine() @@ -539,7 +539,7 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) w.Title1 = "Views" if 0 < uncommitted { w.Title2 = fmt.Sprintf("(Uncommitted: %s)", FormatCount(uncommitted, "View")) - w.Title2Effect = cmd.EmphasisEffect + w.Title2Effect = option.EmphasisEffect } s = "\n" + w.String() + "\n" } @@ -554,42 +554,42 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) if cur, ok := cursors.Load(key); ok { isOpen := cur.IsOpen() - w.WriteColor(cur.Name, cmd.ObjectEffect) + w.WriteColor(cur.Name, option.ObjectEffect) w.BeginBlock() w.NewLine() - w.WriteColorWithoutLineBreak("Status: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Status: ", option.LableEffect) if isOpen == ternary.TRUE { nor, _ := cur.Count() inRange, _ := cur.IsInRange() position, _ := cur.Pointer() - norStr := cmd.FormatInt(nor, ",") + norStr := option.FormatInt(nor, ",") - w.WriteColorWithoutLineBreak("Open", cmd.TernaryEffect) - w.WriteColorWithoutLineBreak(" Number of Rows: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak(norStr, cmd.NumberEffect) + w.WriteColorWithoutLineBreak("Open", option.TernaryEffect) + w.WriteColorWithoutLineBreak(" Number of Rows: ", option.LableEffect) + w.WriteColorWithoutLineBreak(norStr, option.NumberEffect) w.WriteSpaces(10 - len(norStr)) - w.WriteColorWithoutLineBreak("Pointer: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Pointer: ", option.LableEffect) switch inRange { case ternary.FALSE: - w.WriteColorWithoutLineBreak("Out of Range", cmd.TernaryEffect) + w.WriteColorWithoutLineBreak("Out of Range", option.TernaryEffect) case ternary.UNKNOWN: - w.WriteColorWithoutLineBreak(inRange.String(), cmd.TernaryEffect) + w.WriteColorWithoutLineBreak(inRange.String(), option.TernaryEffect) default: - w.WriteColorWithoutLineBreak(cmd.FormatInt(position, ","), cmd.NumberEffect) + w.WriteColorWithoutLineBreak(option.FormatInt(position, ","), option.NumberEffect) } } else { - w.WriteColorWithoutLineBreak("Closed", cmd.TernaryEffect) + w.WriteColorWithoutLineBreak("Closed", option.TernaryEffect) } w.NewLine() if cur.query.SelectEntity != nil { - w.WriteColor("Query:", cmd.LableEffect) + w.WriteColor("Query:", option.LableEffect) writeQuery(w, cur.query.String()) } else { - w.WriteColorWithoutLineBreak("Statement: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak(cur.statement.String(), cmd.IdentifierEffect) + w.WriteColorWithoutLineBreak("Statement: ", option.LableEffect) + w.WriteColorWithoutLineBreak(cur.statement.String(), option.IdentifierEffect) } w.ClearBlock() @@ -627,14 +627,14 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) for _, key := range keys { if stmt, ok := scope.Tx.PreparedStatements.Load(key); ok { - w.WriteColor(stmt.Name, cmd.ObjectEffect) + w.WriteColor(stmt.Name, option.ObjectEffect) w.BeginBlock() w.NewLine() - w.WriteColorWithoutLineBreak("Placeholder Number: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak(strconv.Itoa(stmt.HolderNumber), cmd.NumberEffect) + w.WriteColorWithoutLineBreak("Placeholder Number: ", option.LableEffect) + w.WriteColorWithoutLineBreak(strconv.Itoa(stmt.HolderNumber), option.NumberEffect) w.NewLine() - w.WriteColorWithoutLineBreak("Statement:", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Statement:", option.LableEffect) writeQuery(w, stmt.StatementString) w.ClearBlock() @@ -646,12 +646,12 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) } case ShowFlags: - for _, flag := range cmd.FlagList { - symbol := cmd.FlagSymbol(flag) + for _, flag := range option.FlagList { + symbol := option.FlagSymbol(flag) s, _ := showFlag(scope.Tx, flag) w.WriteSpaces(27 - len(symbol)) - w.WriteColorWithoutLineBreak(symbol, cmd.LableEffect) - w.WriteColorWithoutLineBreak(":", cmd.LableEffect) + w.WriteColorWithoutLineBreak(symbol, option.LableEffect) + w.WriteColorWithoutLineBreak(":", option.LableEffect) w.WriteSpaces(1) w.WriteWithoutLineBreak(s) w.NewLine() @@ -681,8 +681,8 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) for i, name := range names { w.WriteSpaces(nameWidth - len(name)) - w.WriteColorWithoutLineBreak(name, cmd.LableEffect) - w.WriteColorWithoutLineBreak(":", cmd.LableEffect) + w.WriteColorWithoutLineBreak(name, option.LableEffect) + w.WriteColorWithoutLineBreak(":", option.LableEffect) w.WriteSpaces(1) w.WriteWithoutLineBreak(vars[i]) w.NewLine() @@ -695,16 +695,16 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) p, _ := GetRuntimeInformation(scope.Tx, parser.RuntimeInformation{Name: ri}) w.WriteSpaces(19 - len(label)) - w.WriteColorWithoutLineBreak(label, cmd.LableEffect) - w.WriteColorWithoutLineBreak(":", cmd.LableEffect) + w.WriteColorWithoutLineBreak(label, option.LableEffect) + w.WriteColorWithoutLineBreak(":", option.LableEffect) w.WriteSpaces(1) switch ri { case WorkingDirectory, VersionInformation: - w.WriteColorWithoutLineBreak(p.(*value.String).Raw(), cmd.StringEffect) + w.WriteColorWithoutLineBreak(p.(*value.String).Raw(), option.StringEffect) case UncommittedInformation: - w.WriteColorWithoutLineBreak(p.(*value.Boolean).String(), cmd.BooleanEffect) + w.WriteColorWithoutLineBreak(p.(*value.Boolean).String(), option.BooleanEffect) default: - w.WriteColorWithoutLineBreak(p.(*value.Integer).String(), cmd.NumberEffect) + w.WriteColorWithoutLineBreak(p.(*value.Integer).String(), option.NumberEffect) } w.NewLine() } @@ -717,31 +717,31 @@ func ShowObjects(scope *ReferenceScope, expr parser.ShowObjects) (string, error) return s, nil } -func writeTableAttribute(w *ObjectWriter, flags *cmd.Flags, info *FileInfo) { - encWidth := cmd.TextWidth(info.Encoding.String(), flags) +func writeTableAttribute(w *ObjectWriter, flags *option.Flags, info *FileInfo) { + encWidth := option.TextWidth(info.Encoding.String(), flags) - w.WriteColor("Format: ", cmd.LableEffect) + w.WriteColor("Format: ", option.LableEffect) w.WriteWithoutLineBreak(info.Format.String()) - w.WriteSpaces(encWidth + 4 - cmd.TextWidth(info.Format.String(), flags)) + w.WriteSpaces(encWidth + 4 - option.TextWidth(info.Format.String(), flags)) switch info.Format { - case cmd.CSV: - w.WriteColorWithoutLineBreak("Delimiter: ", cmd.LableEffect) - w.WriteWithoutLineBreak("'" + cmd.EscapeString(string(info.Delimiter)) + "'") - case cmd.TSV: - w.WriteColorWithoutLineBreak("Delimiter: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak("'\\t'", cmd.NullEffect) - case cmd.FIXED: + case option.CSV: + w.WriteColorWithoutLineBreak("Delimiter: ", option.LableEffect) + w.WriteWithoutLineBreak("'" + option.EscapeString(string(info.Delimiter)) + "'") + case option.TSV: + w.WriteColorWithoutLineBreak("Delimiter: ", option.LableEffect) + w.WriteColorWithoutLineBreak("'\\t'", option.NullEffect) + case option.FIXED: dp := info.DelimiterPositions.String() if info.SingleLine { dp = "S" + dp } - w.WriteColorWithoutLineBreak("Delimiter Positions: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Delimiter Positions: ", option.LableEffect) w.WriteWithoutLineBreak(dp) - case cmd.JSON, cmd.JSONL: - escapeStr := cmd.JsonEscapeTypeToString(info.JsonEscape) - w.WriteColorWithoutLineBreak("Escape: ", cmd.LableEffect) + case option.JSON, option.JSONL: + escapeStr := option.JsonEscapeTypeToString(info.JsonEscape) + w.WriteColorWithoutLineBreak("Escape: ", option.LableEffect) w.WriteWithoutLineBreak(escapeStr) spaces := 9 - len(escapeStr) @@ -750,46 +750,46 @@ func writeTableAttribute(w *ObjectWriter, flags *cmd.Flags, info *FileInfo) { } w.WriteSpaces(spaces) - w.WriteColorWithoutLineBreak("Query: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Query: ", option.LableEffect) if len(info.JsonQuery) < 1 { - w.WriteColorWithoutLineBreak("(empty)", cmd.NullEffect) + w.WriteColorWithoutLineBreak("(empty)", option.NullEffect) } else { - w.WriteColorWithoutLineBreak(info.JsonQuery, cmd.NullEffect) + w.WriteColorWithoutLineBreak(info.JsonQuery, option.NullEffect) } } switch info.Format { - case cmd.CSV, cmd.TSV: - w.WriteSpaces(4 - (cmd.TextWidth(cmd.EscapeString(string(info.Delimiter)), flags))) - w.WriteColorWithoutLineBreak("Enclose All: ", cmd.LableEffect) + case option.CSV, option.TSV: + w.WriteSpaces(4 - (option.TextWidth(option.EscapeString(string(info.Delimiter)), flags))) + w.WriteColorWithoutLineBreak("Enclose All: ", option.LableEffect) w.WriteWithoutLineBreak(strconv.FormatBool(info.EncloseAll)) } w.NewLine() - w.WriteColor("Encoding: ", cmd.LableEffect) + w.WriteColor("Encoding: ", option.LableEffect) switch info.Format { - case cmd.JSON, cmd.JSONL: - w.WriteColorWithoutLineBreak(text.UTF8.String(), cmd.NullEffect) + case option.JSON, option.JSONL: + w.WriteColorWithoutLineBreak(text.UTF8.String(), option.NullEffect) default: w.WriteWithoutLineBreak(info.Encoding.String()) } - if !(info.Format == cmd.FIXED && info.SingleLine) { - w.WriteSpaces(encWidth + 2 - (cmd.TextWidth(info.Encoding.String(), flags))) - w.WriteColorWithoutLineBreak("LineBreak: ", cmd.LableEffect) + if !(info.Format == option.FIXED && info.SingleLine) { + w.WriteSpaces(encWidth + 2 - (option.TextWidth(info.Encoding.String(), flags))) + w.WriteColorWithoutLineBreak("LineBreak: ", option.LableEffect) w.WriteWithoutLineBreak(info.LineBreak.String()) } switch info.Format { - case cmd.JSON, cmd.JSONL: - w.WriteSpaces(6 - (cmd.TextWidth(info.LineBreak.String(), flags))) - w.WriteColorWithoutLineBreak("Pretty Print: ", cmd.LableEffect) + case option.JSON, option.JSONL: + w.WriteSpaces(6 - (option.TextWidth(info.LineBreak.String(), flags))) + w.WriteColorWithoutLineBreak("Pretty Print: ", option.LableEffect) w.WriteWithoutLineBreak(strconv.FormatBool(info.PrettyPrint)) - case cmd.CSV, cmd.TSV, cmd.FIXED, cmd.GFM, cmd.ORG: - if !(info.Format == cmd.FIXED && info.SingleLine) { - w.WriteSpaces(6 - (cmd.TextWidth(info.LineBreak.String(), flags))) - w.WriteColorWithoutLineBreak("Header: ", cmd.LableEffect) + case option.CSV, option.TSV, option.FIXED, option.GFM, option.ORG: + if !(info.Format == option.FIXED && info.SingleLine) { + w.WriteSpaces(6 - (option.TextWidth(info.LineBreak.String(), flags))) + w.WriteColorWithoutLineBreak("Header: ", option.LableEffect) w.WriteWithoutLineBreak(strconv.FormatBool(!info.NoHeader)) } } @@ -798,15 +798,15 @@ func writeTableAttribute(w *ObjectWriter, flags *cmd.Flags, info *FileInfo) { func writeFields(w *ObjectWriter, fields []string) { w.BeginBlock() w.NewLine() - w.WriteColor("Fields: ", cmd.LableEffect) + w.WriteColor("Fields: ", option.LableEffect) w.BeginSubBlock() lastIdx := len(fields) - 1 for i, f := range fields { - escaped := cmd.EscapeIdentifier(f) + escaped := option.EscapeIdentifier(f) if i < lastIdx && !w.FitInLine(escaped+", ") { w.NewLine() } - w.WriteColor(escaped, cmd.AttributeEffect) + w.WriteColor(escaped, option.AttributeEffect) if i < lastIdx { w.WriteWithoutLineBreak(", ") } @@ -819,11 +819,11 @@ func writeFunctions(w *ObjectWriter, funcs UserDefinedFunctionMap) { for _, key := range keys { if fn, ok := funcs.Load(key); ok { - w.WriteColor(fn.Name.String(), cmd.ObjectEffect) + w.WriteColor(fn.Name.String(), option.ObjectEffect) w.WriteWithoutLineBreak(" (") if fn.IsAggregate { - w.WriteColorWithoutLineBreak(fn.Cursor.String(), cmd.IdentifierEffect) + w.WriteColorWithoutLineBreak(fn.Cursor.String(), option.IdentifierEffect) if 0 < len(fn.Parameters) { w.WriteWithoutLineBreak(", ") } @@ -834,11 +834,11 @@ func writeFunctions(w *ObjectWriter, funcs UserDefinedFunctionMap) { w.WriteWithoutLineBreak(", ") } if def, ok := fn.Defaults[p.Name]; ok { - w.WriteColorWithoutLineBreak(p.String(), cmd.AttributeEffect) + w.WriteColorWithoutLineBreak(p.String(), option.AttributeEffect) w.WriteWithoutLineBreak(" = ") - w.WriteColorWithoutLineBreak(def.String(), cmd.ValueEffect) + w.WriteColorWithoutLineBreak(def.String(), option.ValueEffect) } else { - w.WriteColorWithoutLineBreak(p.String(), cmd.AttributeEffect) + w.WriteColorWithoutLineBreak(p.String(), option.AttributeEffect) } } @@ -892,25 +892,25 @@ func ShowFields(ctx context.Context, scope *ReferenceScope, expr parser.ShowFiel } w := NewObjectWriter(scope.Tx) - w.WriteColorWithoutLineBreak("Type: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Type: ", option.LableEffect) if !view.FileInfo.IsFile() { w.WriteWithoutLineBreak("View") } else { w.WriteWithoutLineBreak("Table") w.NewLine() - w.WriteColorWithoutLineBreak("Path: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak(view.FileInfo.Path, cmd.ObjectEffect) + w.WriteColorWithoutLineBreak("Path: ", option.LableEffect) + w.WriteColorWithoutLineBreak(view.FileInfo.Path, option.ObjectEffect) w.NewLine() writeTableAttribute(w, scope.Tx.Flags, view.FileInfo) } w.NewLine() - w.WriteColorWithoutLineBreak("Status: ", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Status: ", option.LableEffect) switch status { case ObjectCreated: - w.WriteColorWithoutLineBreak("Created", cmd.EmphasisEffect) + w.WriteColorWithoutLineBreak("Created", option.EmphasisEffect) case ObjectUpdated: - w.WriteColorWithoutLineBreak("Updated", cmd.EmphasisEffect) + w.WriteColorWithoutLineBreak("Updated", option.EmphasisEffect) default: w.WriteWithoutLineBreak("Fixed") } @@ -924,7 +924,7 @@ func ShowFields(ctx context.Context, scope *ReferenceScope, expr parser.ShowFiel } else { w.Title2 = tableName(expr.Table) } - w.Title2Effect = cmd.IdentifierEffect + w.Title2Effect = option.IdentifierEffect return "\n" + w.String() + "\n", nil } @@ -937,15 +937,15 @@ func writeFieldList(w *ObjectWriter, fields []string) { fieldNumbers = append(fieldNumbers, strings.Repeat(" ", digits-len(idxstr))+idxstr) } - w.WriteColorWithoutLineBreak("Fields:", cmd.LableEffect) + w.WriteColorWithoutLineBreak("Fields:", option.LableEffect) w.NewLine() w.WriteSpaces(2) w.BeginSubBlock() for i := 0; i < l; i++ { - w.WriteColor(fieldNumbers[i], cmd.NumberEffect) + w.WriteColor(fieldNumbers[i], option.NumberEffect) w.Write(".") w.WriteSpaces(1) - w.WriteColorWithoutLineBreak(fields[i], cmd.AttributeEffect) + w.WriteColorWithoutLineBreak(fields[i], option.AttributeEffect) w.NewLine() } } @@ -1032,7 +1032,7 @@ func Reload(ctx context.Context, tx *Transaction, expr parser.Reload) error { } for _, v := range tx.Environment.DatetimeFormat { - tx.Flags.DatetimeFormat = cmd.AppendStrIfNotExist(tx.Flags.DatetimeFormat, v) + tx.Flags.DatetimeFormat = option.AppendStrIfNotExist(tx.Flags.DatetimeFormat, v) } palette, err := color.GeneratePalette(tx.Environment.Palette) @@ -1071,9 +1071,9 @@ func Syntax(ctx context.Context, scope *ReferenceScope, expr parser.Syntax) (str } if 0 < len(keystr) { - words := strings.Split(cmd.TrimSpace(keystr), " ") + words := strings.Split(option.TrimSpace(keystr), " ") for _, w := range words { - w = cmd.TrimSpace(w) + w = option.TrimSpace(w) if 0 < len(w) { keys = append(keys, w) } @@ -1087,7 +1087,7 @@ func Syntax(ctx context.Context, scope *ReferenceScope, expr parser.Syntax) (str w := NewObjectWriter(scope.Tx) for _, exp := range exps { - w.WriteColor(exp.Label, cmd.LableEffect) + w.WriteColor(exp.Label, option.LableEffect) w.NewLine() if len(exps) < 4 { w.BeginBlock() @@ -1131,7 +1131,7 @@ func Syntax(ctx context.Context, scope *ReferenceScope, expr parser.Syntax) (str if 0 < len(exp.Children) && (len(keys) < 1 || strings.EqualFold(exp.Label, strings.Join(keys, " "))) { w.BeginBlock() for _, child := range exp.Children { - w.WriteColor(child.Label, cmd.LableEffect) + w.WriteColor(child.Label, option.LableEffect) w.NewLine() } } diff --git a/lib/query/built_in_command_test.go b/lib/query/built_in_command_test.go index 65b9dd2..9323f53 100644 --- a/lib/query/built_in_command_test.go +++ b/lib/query/built_in_command_test.go @@ -13,7 +13,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/syntax" "github.com/mithrandie/csvq/lib/value" @@ -676,8 +676,8 @@ func TestSetFlag(t *testing.T) { var addFlagElementTests = []struct { Name string Expr parser.AddFlagElement - Init func(*cmd.Flags) - Expect func() *cmd.Flags + Init func(*option.Flags) + Expect func() *option.Flags Error string }{ { @@ -686,11 +686,11 @@ var addFlagElementTests = []struct { Flag: parser.Flag{Name: "datetime_format"}, Value: parser.NewStringValue("%Y%m%d"), }, - Init: func(flags *cmd.Flags) { + Init: func(flags *option.Flags) { flags.DatetimeFormat = []string{"%Y:%m:%d"} }, - Expect: func() *cmd.Flags { - expect := new(cmd.Flags) + Expect: func() *option.Flags { + expect := new(option.Flags) initFlag(expect) expect.DatetimeFormat = []string{"%Y:%m:%d", "%Y%m%d"} return expect @@ -702,7 +702,7 @@ var addFlagElementTests = []struct { Flag: parser.Flag{Name: "format"}, Value: parser.NewStringValue("%Y%m%d"), }, - Init: func(flags *cmd.Flags) { + Init: func(flags *option.Flags) { flags.DatetimeFormat = []string{"%Y:%m:%d"} }, Error: "add flag element syntax does not support @@FORMAT", @@ -713,7 +713,7 @@ var addFlagElementTests = []struct { Flag: parser.Flag{Name: "invalid"}, Value: parser.NewStringValue("%Y%m%d"), }, - Init: func(flags *cmd.Flags) { + Init: func(flags *option.Flags) { flags.DatetimeFormat = []string{"%Y:%m:%d"} }, Error: "@@INVALID is an unknown flag", @@ -754,8 +754,8 @@ func TestAddFlagElement(t *testing.T) { var removeFlagElementTests = []struct { Name string Expr parser.RemoveFlagElement - Init func(*cmd.Flags) - Expect func() *cmd.Flags + Init func(*option.Flags) + Expect func() *option.Flags Error string }{ { @@ -764,11 +764,11 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "datetime_format"}, Value: parser.NewStringValue("%Y%m%d"), }, - Init: func(flags *cmd.Flags) { + Init: func(flags *option.Flags) { flags.DatetimeFormat = []string{"%Y%m%d", "%Y:%m:%d"} }, - Expect: func() *cmd.Flags { - expect := new(cmd.Flags) + Expect: func() *option.Flags { + expect := new(option.Flags) initFlag(expect) expect.DatetimeFormat = []string{"%Y:%m:%d"} return expect @@ -780,11 +780,11 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "datetime_format"}, Value: parser.NewIntegerValue(1), }, - Init: func(flags *cmd.Flags) { + Init: func(flags *option.Flags) { flags.DatetimeFormat = []string{"%Y%m%d", "%Y:%m:%d"} }, - Expect: func() *cmd.Flags { - expect := new(cmd.Flags) + Expect: func() *option.Flags { + expect := new(option.Flags) initFlag(expect) expect.DatetimeFormat = []string{"%Y%m%d"} return expect @@ -796,7 +796,7 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "datetime_format"}, Value: parser.NewNullValue(), }, - Init: func(flags *cmd.Flags) {}, + Init: func(flags *option.Flags) {}, Error: "NULL is an invalid value for @@DATETIME_FORMAT to specify the element", }, { @@ -805,7 +805,7 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "format"}, Value: parser.FieldReference{Column: parser.Identifier{Literal: "err"}}, }, - Init: func(flags *cmd.Flags) {}, + Init: func(flags *option.Flags) {}, Error: "field err does not exist", }, { @@ -814,7 +814,7 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "format"}, Value: parser.NewIntegerValue(1), }, - Init: func(flags *cmd.Flags) {}, + Init: func(flags *option.Flags) {}, Error: "remove flag element syntax does not support @@FORMAT", }, { @@ -823,7 +823,7 @@ var removeFlagElementTests = []struct { Flag: parser.Flag{Name: "invalid"}, Value: parser.NewIntegerValue(1), }, - Init: func(flags *cmd.Flags) {}, + Init: func(flags *option.Flags) {}, Error: "@@INVALID is an unknown flag", }, } @@ -1646,14 +1646,14 @@ var showObjectsTests = []struct { Expr parser.ShowObjects Scope *ReferenceScope PreparedStatements PreparedStatementMap - ImportFormat cmd.Format + ImportFormat option.Format Delimiter rune AllowUnevenFields bool DelimiterPositions fixedlen.DelimiterPositions SingleLine bool JsonQuery string Repository string - Format cmd.Format + Format option.Format WriteDelimiter rune WriteDelimiterPositions fixedlen.DelimiterPositions WriteAsSingleLine bool @@ -1671,7 +1671,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.csv", Delimiter: '\t', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.CRLF, NoHeader: true, @@ -1682,7 +1682,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1693,7 +1693,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.json", JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: false, @@ -1704,7 +1704,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table2.json", JsonQuery: "", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.HexDigits, @@ -1716,7 +1716,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.jsonl", JsonQuery: "{}", - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: false, @@ -1727,7 +1727,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table2.jsonl", JsonQuery: "", - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.HexDigits, @@ -1739,7 +1739,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.txt", DelimiterPositions: []int{3, 12}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1751,7 +1751,7 @@ var showObjectsTests = []struct { Path: "table2.txt", DelimiterPositions: []int{3, 12}, SingleLine: true, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1804,7 +1804,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.csv", Delimiter: '\t', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.CRLF, NoHeader: true, @@ -1815,7 +1815,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1826,7 +1826,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.json", JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: false, @@ -1837,7 +1837,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.jsonl", JsonQuery: "{}", - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: false, @@ -1848,7 +1848,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table2.json", JsonQuery: "", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: false, @@ -1859,7 +1859,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.txt", DelimiterPositions: []int{3, 12}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1870,7 +1870,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table2.txt", DelimiterPositions: []int{3, 12}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -1929,7 +1929,7 @@ var showObjectsTests = []struct { FileInfo: &FileInfo{ Path: "table1.csv", Delimiter: '\t', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.CRLF, NoHeader: true, @@ -2488,7 +2488,7 @@ var showFieldsTests = []struct { FileInfo: &FileInfo{ Path: GetTestFilePath("show_fields_create.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -2527,7 +2527,7 @@ var showFieldsTests = []struct { FileInfo: &FileInfo{ Path: GetTestFilePath("show_fields_create.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, @@ -2566,7 +2566,7 @@ var showFieldsTests = []struct { FileInfo: &FileInfo{ Path: GetTestFilePath("show_fields_update.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: false, diff --git a/lib/query/encode.go b/lib/query/encode.go index 38665ce..10e2ed5 100644 --- a/lib/query/encode.go +++ b/lib/query/encode.go @@ -10,8 +10,8 @@ import ( "strconv" "time" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/json" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/go-text" @@ -27,27 +27,27 @@ import ( var EmptyResultSetError = errors.New("empty result set") var DataEmpty = errors.New("data empty") -func EncodeView(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions, palette *color.Palette) (string, error) { +func EncodeView(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions, palette *color.Palette) (string, error) { switch options.Format { - case cmd.FIXED: + case option.FIXED: return "", encodeFixedLengthFormat(ctx, fp, view, options) - case cmd.JSON: + case option.JSON: return "", encodeJson(ctx, fp, view, options, palette) - case cmd.JSONL: + case option.JSONL: return "", encodeJsonLines(ctx, fp, view, options, palette) - case cmd.LTSV: + case option.LTSV: return "", encodeLTSV(ctx, fp, view, options) - case cmd.GFM, cmd.ORG, cmd.BOX, cmd.TEXT: + case option.GFM, option.ORG, option.BOX, option.TEXT: return encodeText(ctx, fp, view, options, palette) - case cmd.TSV: + case option.TSV: options.Delimiter = '\t' fallthrough - default: // cmd.CSV + default: // option.CSV return "", encodeCSV(ctx, fp, view, options) } } -func encodeCSV(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions) error { +func encodeCSV(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions) error { w, err := csv.NewWriter(fp, options.LineBreak, options.Encoding) if err != nil { return NewDataEncodingError(err.Error()) @@ -76,7 +76,7 @@ func encodeCSV(ctx context.Context, fp io.Writer, view *View, options cmd.Export for j := range view.RecordSet[i] { str, effect, _ := ConvertFieldContents(view.RecordSet[i][j][0], false) quote := false - if options.EncloseAll && (effect == cmd.StringEffect || effect == cmd.DatetimeEffect) { + if options.EncloseAll && (effect == option.StringEffect || effect == option.DatetimeEffect) { quote = true } fields[j] = csv.NewField(str, quote) @@ -91,7 +91,7 @@ func encodeCSV(ctx context.Context, fp io.Writer, view *View, options cmd.Export return nil } -func encodeFixedLengthFormat(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions) error { +func encodeFixedLengthFormat(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions) error { if options.DelimiterPositions == nil { m := fixedlen.NewMeasure() m.Encoding = options.Encoding @@ -192,7 +192,7 @@ func encodeFixedLengthFormat(ctx context.Context, fp io.Writer, view *View, opti return nil } -func encodeJson(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions, palette *color.Palette) error { +func encodeJson(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions, palette *color.Palette) error { header := view.Header.TableColumnNames() records := make([][]value.Primary, view.RecordLen()) for i := range view.RecordSet { @@ -245,7 +245,7 @@ func encodeJson(ctx context.Context, fp io.Writer, view *View, options cmd.Expor return nil } -func encodeJsonLines(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions, palette *color.Palette) error { +func encodeJsonLines(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions, palette *color.Palette) error { fields := view.Header.TableColumnNames() pathes, err := json.ParsePathes(fields) if err != nil { @@ -302,17 +302,17 @@ func encodeJsonLines(ctx context.Context, fp io.Writer, view *View, options cmd. return nil } -func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions, palette *color.Palette) (string, error) { +func encodeText(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions, palette *color.Palette) (string, error) { isPlainTable := false var tableFormat = table.PlainTable switch options.Format { - case cmd.GFM: + case option.GFM: tableFormat = table.GFMTable - case cmd.ORG: + case option.ORG: tableFormat = table.OrgTable default: - if options.Format == cmd.BOX { + if options.Format == option.BOX { tableFormat = table.BoxTable } if view.FieldLen() < 1 { @@ -334,7 +334,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.Expor fieldLen := view.FieldLen() - if !options.WithoutHeader || (options.Format != cmd.GFM && options.Format != cmd.ORG) { + if !options.WithoutHeader || (options.Format != option.GFM && options.Format != option.ORG) { hfields := make([]table.Field, fieldLen) for i := range view.Header { hfields[i] = table.NewField(view.Header[i].Column, text.Centering) @@ -356,7 +356,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.Expor rfields := make([]table.Field, fieldLen) for j := range view.RecordSet[i] { str, effect, align := ConvertFieldContents(view.RecordSet[i][j][0], isPlainTable) - if options.Format == cmd.TEXT || options.Format == cmd.BOX { + if options.Format == option.TEXT || options.Format == option.BOX { textStrBuf.Reset() textLineBuf.Reset() @@ -400,7 +400,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.Expor e.AppendRecord(rfields) } - if options.Format == cmd.GFM { + if options.Format == option.GFM { e.SetFieldAlignments(aligns) } @@ -418,7 +418,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options cmd.Expor return "", nil } -func encodeLTSV(ctx context.Context, fp io.Writer, view *View, options cmd.ExportOptions) error { +func encodeLTSV(ctx context.Context, fp io.Writer, view *View, options option.ExportOptions) error { if view.RecordLen() < 1 { return DataEmpty } @@ -454,43 +454,43 @@ func encodeLTSV(ctx context.Context, fp io.Writer, view *View, options cmd.Expor func ConvertFieldContents(val value.Primary, forTextTable bool) (string, string, text.FieldAlignment) { var s string - var effect = cmd.NoEffect + var effect = option.NoEffect var align = text.NotAligned switch val.(type) { case *value.String: s = val.(*value.String).Raw() - effect = cmd.StringEffect + effect = option.StringEffect case *value.Integer: s = val.(*value.Integer).String() - effect = cmd.NumberEffect + effect = option.NumberEffect align = text.RightAligned case *value.Float: s = val.(*value.Float).String() - effect = cmd.NumberEffect + effect = option.NumberEffect align = text.RightAligned case *value.Boolean: s = val.(*value.Boolean).String() - effect = cmd.BooleanEffect + effect = option.BooleanEffect align = text.Centering case *value.Ternary: t := val.(*value.Ternary) if forTextTable { s = t.Ternary().String() - effect = cmd.TernaryEffect + effect = option.TernaryEffect align = text.Centering } else if t.Ternary() != ternary.UNKNOWN { s = strconv.FormatBool(t.Ternary().ParseBool()) - effect = cmd.BooleanEffect + effect = option.BooleanEffect align = text.Centering } case *value.Datetime: s = val.(*value.Datetime).Format(time.RFC3339Nano) - effect = cmd.DatetimeEffect + effect = option.DatetimeEffect case *value.Null: if forTextTable { s = "NULL" - effect = cmd.NullEffect + effect = option.NullEffect align = text.Centering } } diff --git a/lib/query/encode_test.go b/lib/query/encode_test.go index 53d9a3d..bd96250 100644 --- a/lib/query/encode_test.go +++ b/lib/query/encode_test.go @@ -5,7 +5,7 @@ import ( "context" "testing" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/go-text" @@ -17,7 +17,7 @@ import ( var encodeViewTests = []struct { Name string View *View - Format cmd.Format + Format option.Format LineBreak text.LineBreak WriteEncoding text.Encoding WriteDelimiter rune @@ -37,7 +37,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), RecordSet: []Record{}, }, - Format: cmd.TEXT, + Format: option.TEXT, Error: "empty result set", }, { @@ -48,7 +48,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{}), }, }, - Format: cmd.TEXT, + Format: option.TEXT, Error: "empty result set", }, { @@ -61,7 +61,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.TEXT, + Format: option.TEXT, Result: "+----------+-------------------------------------+--------+\n" + "| c1 | c2 | c3 |\n" + "| | second line | |\n" + @@ -83,7 +83,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.TEXT, + Format: option.TEXT, WithoutHeader: true, Result: "+----------+-------------------------------------+--------+\n" + "| c1 | c2 | c3 |\n" + @@ -105,7 +105,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewString("abcdef\r\nghijkl")}), }, }, - Format: cmd.TEXT, + Format: option.TEXT, UseColor: true, Result: "" + "+--------+--------+\n" + @@ -126,7 +126,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.BOX, + Format: option.BOX, Result: "┌──────────┬─────────────────────────────────────┬────────┐\n" + "│ c1 │ c2 │ c3 │\n" + "│ │ second line │ │\n" + @@ -148,7 +148,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.BOX, + Format: option.BOX, WithoutHeader: true, Result: "┌──────────┬─────────────────────────────────────┬────────┐\n" + "│ c1 │ c2 │ c3 │\n" + @@ -170,7 +170,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewString("abcdef\r\nghijkl")}), }, }, - Format: cmd.BOX, + Format: option.BOX, UseColor: true, Result: "" + "┌────────┬────────┐\n" + @@ -190,7 +190,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: []int{10, 42, 50}, Result: "" + "c1 c2 c3 \n" + @@ -206,7 +206,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: []int{10, 42, 50}, WriteAsSingleLine: true, Result: "" + @@ -222,7 +222,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: nil, Result: "" + "c1 c2 c3 \n" + @@ -235,7 +235,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2", "c3"}), RecordSet: []Record{}, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: []int{10, 42, 50}, WithoutHeader: true, Error: "data empty", @@ -246,7 +246,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2", "c3"}), RecordSet: []Record{}, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: nil, WithoutHeader: true, Error: "data empty", @@ -260,7 +260,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" ab|cdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.GFM, + Format: option.GFM, LineBreak: text.CRLF, Result: "" + "| c1 | c2
    second line | c3 |\r\n" + @@ -274,7 +274,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), RecordSet: []Record{}, }, - Format: cmd.GFM, + Format: option.GFM, WithoutHeader: true, Error: "data empty", }, @@ -287,7 +287,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" ab|cdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk日本語あアアA(\n"), value.NewNull()}), }, }, - Format: cmd.ORG, + Format: option.ORG, LineBreak: text.LF, Result: "" + "| c1 | c2
    second line | c3 |\n" + @@ -301,7 +301,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), RecordSet: []Record{}, }, - Format: cmd.ORG, + Format: option.ORG, WithoutHeader: true, Error: "data empty", }, @@ -315,7 +315,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.TSV, + Format: option.TSV, WriteDelimiter: '\t', EncloseAll: true, Result: "\"c1\"\t\"c2\nsecond line\"\t\"c3\"\n" + @@ -329,7 +329,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2\nsecond line", "c3"}), RecordSet: []Record{}, }, - Format: cmd.TSV, + Format: option.TSV, WriteDelimiter: '\t', WithoutHeader: true, Error: "data empty", @@ -344,7 +344,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.CSV, + Format: option.CSV, WithoutHeader: true, EncloseAll: true, Result: "-1,,true\n" + @@ -361,7 +361,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abcdefghijklmnopqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.CSV, + Format: option.CSV, LineBreak: text.CRLF, EncloseAll: true, Result: "\"c1\",\"c2\nsecond line\",\"c3\"\r\n" + @@ -380,7 +380,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abc\\defghi/jk\rlmn\topqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.JSON, + Format: option.JSON, Result: "[" + "{" + "\"c1\":-1," + @@ -414,7 +414,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewString("abc\\def")}), }, }, - Format: cmd.JSON, + Format: option.JSON, JsonEscape: json.HexDigits, Result: "[" + "{" + @@ -438,7 +438,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewString("abc\\def")}), }, }, - Format: cmd.JSON, + Format: option.JSON, JsonEscape: json.AllWithHexDigits, Result: "[" + "{" + @@ -462,7 +462,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewString("abc\\def")}), }, }, - Format: cmd.JSON, + Format: option.JSON, JsonEscape: json.HexDigits, PrettyPrint: true, Result: "[\n" + @@ -488,7 +488,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" abc\\defghi/jk\rlmn\topqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.JSONL, + Format: option.JSONL, Result: "{" + "\"c1\":-1," + "\"c2\\nsecond line\":null," + @@ -519,7 +519,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.LTSV, + Format: option.LTSV, Result: "c1:-1\tc2:false\tc3:true\n" + "c1:2.0123\tc2:2016-02-01T16:00:00.123456-07:00\tc3:abcdef", }, @@ -529,7 +529,7 @@ var encodeViewTests = []struct { Header: NewHeader("test", []string{"c1", "c2", "c3"}), RecordSet: []Record{}, }, - Format: cmd.LTSV, + Format: option.LTSV, Error: "data empty", }, { @@ -541,7 +541,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.FIXED, + Format: option.FIXED, WriteDelimiterPositions: []int{10, 42, -1}, Error: "data encode error: invalid delimiter position: [10, 42, -1]", }, @@ -555,7 +555,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewString("abc\\def")}), }, }, - Format: cmd.JSON, + Format: option.JSON, JsonEscape: json.HexDigits, Error: "data encode error: unexpected token \".\" at column 4 in \"c1..\"", }, @@ -568,7 +568,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abcdef")}), }, }, - Format: cmd.LTSV, + Format: option.LTSV, Error: "data encode error: unpermitted character in label: U+003A", }, { @@ -580,7 +580,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewFloat(2.0123), value.NewDatetimeFromString("2016-02-01T16:00:00.123456-07:00", nil, GetTestLocation()), value.NewString("abc\tdef")}), }, }, - Format: cmd.LTSV, + Format: option.LTSV, Error: "data encode error: unpermitted character in field-value: U+0009", }, { @@ -594,7 +594,7 @@ var encodeViewTests = []struct { NewRecord([]value.Primary{value.NewInteger(34567890), value.NewString(" 日本語ghijklmnopqrstuvwxyzabcdefg\nhi\"jk\n"), value.NewNull()}), }, }, - Format: cmd.CSV, + Format: option.CSV, WriteEncoding: text.SJIS, EncloseAll: true, Result: "\"c1\",\"c2\nsecond line\",\"c3\"\n" + diff --git a/lib/query/eval.go b/lib/query/eval.go index ad227e2..ec41fcb 100644 --- a/lib/query/eval.go +++ b/lib/query/eval.go @@ -6,10 +6,10 @@ import ( "os" "strings" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/constant" "github.com/mithrandie/csvq/lib/excmd" "github.com/mithrandie/csvq/lib/json" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -592,7 +592,7 @@ func evalFunction(ctx context.Context, scope *ReferenceScope, expr parser.Functi } func evalAggregateFunction(ctx context.Context, scope *ReferenceScope, expr parser.AggregateFunction) (value.Primary, error) { - var aggfn func([]value.Primary, *cmd.Flags) value.Primary + var aggfn func([]value.Primary, *option.Flags) value.Primary var udfn *UserDefinedFunction var err error @@ -1181,7 +1181,7 @@ func EvaluateEmbeddedString(ctx context.Context, scope *ReferenceScope, embedded for scanner.Scan() { switch scanner.ElementType() { case excmd.FixedString: - buf.WriteString(cmd.UnescapeString(scanner.Text(), enclosure)) + buf.WriteString(option.UnescapeString(scanner.Text(), enclosure)) case excmd.Variable: if err = writeEmbeddedExpression(ctx, scope, buf, parser.Variable{Name: scanner.Text()}); err != nil { return buf.String(), err diff --git a/lib/query/file_info.go b/lib/query/file_info.go index f9cf177..c3d6902 100644 --- a/lib/query/file_info.go +++ b/lib/query/file_info.go @@ -8,8 +8,8 @@ import ( "reflect" "strings" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/go-text" @@ -68,7 +68,7 @@ func (e TableAttributeUnchangedError) Error() string { type FileInfo struct { Path string - Format cmd.Format + Format option.Format Delimiter rune DelimiterPositions fixedlen.DelimiterPositions JsonQuery string @@ -93,8 +93,8 @@ type FileInfo struct { func NewFileInfo( filename parser.Identifier, repository string, - options cmd.ImportOptions, - defaultFormat cmd.Format, + options option.ImportOptions, + defaultFormat option.Format, ) (*FileInfo, error) { fpath, format, err := SearchFilePath(filename, repository, options, defaultFormat) if err != nil { @@ -104,9 +104,9 @@ func NewFileInfo( delimiter := options.Delimiter encoding := options.Encoding switch format { - case cmd.TSV: + case option.TSV: delimiter = '\t' - case cmd.JSON, cmd.JSONL: + case option.JSON, option.JSONL: encoding = text.UTF8 } @@ -119,16 +119,16 @@ func NewFileInfo( } func (f *FileInfo) SetDelimiter(s string) error { - delimiter, err := cmd.ParseDelimiter(s) + delimiter, err := option.ParseDelimiter(s) if err != nil { return err } - var format cmd.Format + var format option.Format if delimiter == '\t' { - format = cmd.TSV + format = option.TSV } else { - format = cmd.CSV + format = option.CSV } if f.Delimiter == delimiter && f.Format == format { @@ -141,12 +141,12 @@ func (f *FileInfo) SetDelimiter(s string) error { } func (f *FileInfo) SetDelimiterPositions(s string) error { - pos, singleLine, err := cmd.ParseDelimiterPositions(s) + pos, singleLine, err := option.ParseDelimiterPositions(s) if err != nil { return err } delimiterPositions := fixedlen.DelimiterPositions(pos) - format := cmd.FIXED + format := option.FIXED if reflect.DeepEqual(f.DelimiterPositions, delimiterPositions) && f.SingleLine == singleLine && @@ -162,7 +162,7 @@ func (f *FileInfo) SetDelimiterPositions(s string) error { } func (f *FileInfo) SetFormat(s string) error { - format, escapeType, err := cmd.ParseFormat(s, f.JsonEscape) + format, escapeType, err := option.ParseFormat(s, f.JsonEscape) if err != nil { return err } @@ -176,9 +176,9 @@ func (f *FileInfo) SetFormat(s string) error { encoding := f.Encoding switch format { - case cmd.TSV: + case option.TSV: delimiter = '\t' - case cmd.JSON, cmd.JSONL: + case option.JSON, option.JSONL: encoding = text.UTF8 } @@ -190,13 +190,13 @@ func (f *FileInfo) SetFormat(s string) error { } func (f *FileInfo) SetEncoding(s string) error { - encoding, err := cmd.ParseEncoding(s) + encoding, err := option.ParseEncoding(s) if err != nil || encoding == text.AUTO { return errors.New("encoding must be one of UTF8|UTF8M|UTF16|UTF16BE|UTF16LE|UTF16BEM|UTF16LEM|SJIS") } switch f.Format { - case cmd.JSON, cmd.JSONL: + case option.JSON, option.JSONL: if encoding != text.UTF8 { return errors.New("json format is supported only UTF8") } @@ -211,7 +211,7 @@ func (f *FileInfo) SetEncoding(s string) error { } func (f *FileInfo) SetLineBreak(s string) error { - lb, err := cmd.ParseLineBreak(s) + lb, err := option.ParseLineBreak(s) if err != nil { return err } @@ -241,7 +241,7 @@ func (f *FileInfo) SetEncloseAll(b bool) error { } func (f *FileInfo) SetJsonEscape(s string) error { - escape, err := cmd.ParseJsonEscapeType(s) + escape, err := option.ParseJsonEscapeType(s) if err != nil { return err } @@ -274,7 +274,7 @@ func (f *FileInfo) IsStdin() bool { return f.ViewType == ViewTypeStdin } -func (f *FileInfo) ExportOptions(tx *Transaction) cmd.ExportOptions { +func (f *FileInfo) ExportOptions(tx *Transaction) option.ExportOptions { ops := tx.Flags.ExportOptions.Copy() ops.Format = f.Format ops.Delimiter = f.Delimiter @@ -289,36 +289,36 @@ func (f *FileInfo) ExportOptions(tx *Transaction) cmd.ExportOptions { return ops } -func SearchFilePath(filename parser.Identifier, repository string, options cmd.ImportOptions, defaultFormat cmd.Format) (string, cmd.Format, error) { +func SearchFilePath(filename parser.Identifier, repository string, options option.ImportOptions, defaultFormat option.Format) (string, option.Format, error) { var fpath string var err error format := options.Format switch format { - case cmd.CSV, cmd.TSV: + case option.CSV, option.TSV: fpath, err = SearchCSVFilePath(filename, repository) - case cmd.JSON: + case option.JSON: fpath, err = SearchJsonFilePath(filename, repository) - case cmd.JSONL: + case option.JSONL: fpath, err = SearchJsonlFilePath(filename, repository) - case cmd.FIXED: + case option.FIXED: fpath, err = SearchFixedLengthFilePath(filename, repository) - case cmd.LTSV: + case option.LTSV: fpath, err = SearchLTSVFilePath(filename, repository) default: // AutoSelect if fpath, err = SearchFilePathFromAllTypes(filename, repository); err == nil { switch strings.ToLower(filepath.Ext(fpath)) { - case cmd.CsvExt: - format = cmd.CSV - case cmd.TsvExt: - format = cmd.TSV - case cmd.JsonExt: - format = cmd.JSON - case cmd.JsonlExt: - format = cmd.JSONL - case cmd.LtsvExt: - format = cmd.LTSV + case option.CsvExt: + format = option.CSV + case option.TsvExt: + format = option.TSV + case option.JsonExt: + format = option.JSON + case option.JsonlExt: + format = option.JSONL + case option.LtsvExt: + format = option.LTSV default: format = defaultFormat } @@ -329,27 +329,27 @@ func SearchFilePath(filename parser.Identifier, repository string, options cmd.I } func SearchCSVFilePath(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.CsvExt, cmd.TsvExt, cmd.TextExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.CsvExt, option.TsvExt, option.TextExt}) } func SearchJsonFilePath(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.JsonExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.JsonExt}) } func SearchJsonlFilePath(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.JsonlExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.JsonlExt}) } func SearchFixedLengthFilePath(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.TextExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.TextExt}) } func SearchLTSVFilePath(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.LtsvExt, cmd.TextExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.LtsvExt, option.TextExt}) } func SearchFilePathFromAllTypes(filename parser.Identifier, repository string) (string, error) { - return SearchFilePathWithExtType(filename, repository, []string{cmd.CsvExt, cmd.TsvExt, cmd.JsonExt, cmd.JsonlExt, cmd.LtsvExt, cmd.TextExt}) + return SearchFilePathWithExtType(filename, repository, []string{option.CsvExt, option.TsvExt, option.JsonExt, option.JsonlExt, option.LtsvExt, option.TextExt}) } func SearchFilePathWithExtType(filename parser.Identifier, repository string, extTypes []string) (string, error) { @@ -401,25 +401,25 @@ func NewFileInfoForCreate(filename parser.Identifier, repository string, delimit return nil, NewIOError(filename, err.Error()) } - var format cmd.Format + var format option.Format switch strings.ToLower(filepath.Ext(fpath)) { - case cmd.TsvExt: + case option.TsvExt: delimiter = '\t' - format = cmd.TSV - case cmd.JsonExt: + format = option.TSV + case option.JsonExt: encoding = text.UTF8 - format = cmd.JSON - case cmd.JsonlExt: + format = option.JSON + case option.JsonlExt: encoding = text.UTF8 - format = cmd.JSONL - case cmd.LtsvExt: - format = cmd.LTSV - case cmd.GfmExt: - format = cmd.GFM - case cmd.OrgExt: - format = cmd.ORG + format = option.JSONL + case option.LtsvExt: + format = option.LTSV + case option.GfmExt: + format = option.GFM + case option.OrgExt: + format = option.ORG default: - format = cmd.CSV + format = option.CSV } return &FileInfo{ diff --git a/lib/query/file_info_test.go b/lib/query/file_info_test.go index db19ae0..dad02cc 100644 --- a/lib/query/file_info_test.go +++ b/lib/query/file_info_test.go @@ -6,7 +6,7 @@ import ( "path/filepath" "testing" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/go-text" @@ -16,7 +16,7 @@ var fileInfoTests = []struct { Name string FilePath parser.Identifier Repository string - Format cmd.Format + Format option.Format Delimiter rune Encoding text.Encoding Result *FileInfo @@ -26,13 +26,13 @@ var fileInfoTests = []struct { Name: "CSV", FilePath: parser.Identifier{Literal: "table1"}, Repository: TestDir, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table1.csv", Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, }, }, @@ -40,13 +40,13 @@ var fileInfoTests = []struct { Name: "CSV with AutoSelect", FilePath: parser.Identifier{Literal: "table1"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table1.csv", Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, }, }, @@ -54,13 +54,13 @@ var fileInfoTests = []struct { Name: "TSV", FilePath: parser.Identifier{Literal: "table3"}, Repository: TestDir, - Format: cmd.TSV, + Format: option.TSV, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table3.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, }, }, @@ -68,13 +68,13 @@ var fileInfoTests = []struct { Name: "TSV with AutoSelect", FilePath: parser.Identifier{Literal: "table3"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table3.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, }, }, @@ -82,13 +82,13 @@ var fileInfoTests = []struct { Name: "JSON", FilePath: parser.Identifier{Literal: "table"}, Repository: TestDir, - Format: cmd.JSON, + Format: option.JSON, Delimiter: ',', Encoding: text.UTF16, Result: &FileInfo{ Path: "table.json", Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, }, }, @@ -96,13 +96,13 @@ var fileInfoTests = []struct { Name: "JSON with AutoSelect", FilePath: parser.Identifier{Literal: "table"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF16, Result: &FileInfo{ Path: "table.json", Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, }, }, @@ -110,13 +110,13 @@ var fileInfoTests = []struct { Name: "JSONL", FilePath: parser.Identifier{Literal: "table7"}, Repository: TestDir, - Format: cmd.JSONL, + Format: option.JSONL, Delimiter: ',', Encoding: text.UTF16, Result: &FileInfo{ Path: "table7.jsonl", Delimiter: ',', - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, }, }, @@ -124,13 +124,13 @@ var fileInfoTests = []struct { Name: "JSONL with AutoSelect", FilePath: parser.Identifier{Literal: "table7"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF16, Result: &FileInfo{ Path: "table7.jsonl", Delimiter: ',', - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, }, }, @@ -138,13 +138,13 @@ var fileInfoTests = []struct { Name: "LTSV", FilePath: parser.Identifier{Literal: "table6"}, Repository: TestDir, - Format: cmd.LTSV, + Format: option.LTSV, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table6.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8, }, }, @@ -152,13 +152,13 @@ var fileInfoTests = []struct { Name: "LTSV with AutoSelect", FilePath: parser.Identifier{Literal: "table6"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "table6.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8, }, }, @@ -166,13 +166,13 @@ var fileInfoTests = []struct { Name: "Fixed-Length", FilePath: parser.Identifier{Literal: "fixed_length.txt"}, Repository: TestDir, - Format: cmd.FIXED, + Format: option.FIXED, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "fixed_length.txt", Delimiter: ',', - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, }, }, @@ -180,13 +180,13 @@ var fileInfoTests = []struct { Name: "Import Format", FilePath: parser.Identifier{Literal: "autoselect"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF8, Result: &FileInfo{ Path: "autoselect", Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, }, }, @@ -194,7 +194,7 @@ var fileInfoTests = []struct { Name: "Not Exist Error", FilePath: parser.Identifier{Literal: "notexist"}, Repository: TestDir, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', Encoding: text.UTF8, Error: "file notexist does not exist", @@ -203,7 +203,7 @@ var fileInfoTests = []struct { Name: "File Read Error", FilePath: parser.Identifier{Literal: TestDir}, Repository: TestDir, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', Encoding: text.UTF8, Error: fmt.Sprintf("file %s is unable to be read", TestDir), @@ -212,7 +212,7 @@ var fileInfoTests = []struct { Name: "Filenames Ambiguous", FilePath: parser.Identifier{Literal: "dup_name"}, Repository: TestDir, - Format: cmd.AutoSelect, + Format: option.AutoSelect, Delimiter: ',', Encoding: text.UTF8, Error: fmt.Sprintf("filename dup_name is ambiguous"), @@ -270,7 +270,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.csv", Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, }, }, @@ -282,7 +282,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, }, }, @@ -294,7 +294,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.json", Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, }, }, @@ -306,7 +306,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.jsonl", Delimiter: ',', - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, }, }, @@ -318,7 +318,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8, }, }, @@ -330,7 +330,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.md", Delimiter: ',', - Format: cmd.GFM, + Format: option.GFM, Encoding: text.UTF8, }, }, @@ -342,7 +342,7 @@ var fileInfoForCreateTests = []struct { Result: &FileInfo{ Path: "table1.org", Delimiter: ',', - Format: cmd.ORG, + Format: option.ORG, Encoding: text.UTF8, }, }, diff --git a/lib/query/function.go b/lib/query/function.go index e70a931..016c192 100644 --- a/lib/query/function.go +++ b/lib/query/function.go @@ -24,8 +24,8 @@ import ( "unicode" "unicode/utf8" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/json" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -33,7 +33,7 @@ import ( "github.com/mithrandie/ternary" ) -type BuiltInFunction func(parser.Function, []value.Primary, *cmd.Flags) (value.Primary, error) +type BuiltInFunction func(parser.Function, []value.Primary, *option.Flags) (value.Primary, error) var Functions = map[string]BuiltInFunction{ "COALESCE": Coalesce, @@ -177,7 +177,7 @@ const ( PaddingWidth PaddingType = "WIDTH" ) -func Coalesce(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Coalesce(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 1 { return nil, NewFunctionArgumentLengthErrorWithCustomArgs(fn, fn.Name, "at least 1 argument") } @@ -190,7 +190,7 @@ func Coalesce(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Pri return value.NewNull(), nil } -func If(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func If(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 3 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{3}) } @@ -201,7 +201,7 @@ func If(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, return args[2], nil } -func Ifnull(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Ifnull(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -212,7 +212,7 @@ func Ifnull(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prima return args[0], nil } -func Nullif(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Nullif(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -249,7 +249,7 @@ func roundParams(args []value.Primary) (number float64, place float64, isnull bo return } -func Ceil(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Ceil(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { number, place, isnull, argsErr := roundParams(args) if argsErr { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) @@ -263,7 +263,7 @@ func Ceil(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary return value.NewFloat(r), nil } -func Floor(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Floor(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { number, place, isnull, argsErr := roundParams(args) if argsErr { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) @@ -288,7 +288,7 @@ func round(f float64, place float64) float64 { return r } -func Round(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Round(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { number, place, isnull, argsErr := roundParams(args) if argsErr { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) @@ -337,63 +337,63 @@ func execMath2Args(fn parser.Function, args []value.Primary, mathf func(float64, return value.NewFloat(result), nil } -func Abs(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Abs(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Abs) } -func Acos(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Acos(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Acos) } -func Acosh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Acosh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Acosh) } -func Asin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Asin(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Asin) } -func Asinh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Asinh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Asinh) } -func Atan(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Atan(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Atan) } -func Atan2(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Atan2(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath2Args(fn, args, math.Atan2) } -func Atanh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Atanh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Atanh) } -func Cbrt(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Cbrt(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Cbrt) } -func Cos(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Cos(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Cos) } -func Cosh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Cosh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Cosh) } -func Exp(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Exp(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Exp) } -func Exp2(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Exp2(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Exp2) } -func Expm1(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Expm1(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Expm1) } -func IsInf(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func IsInf(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) } @@ -414,7 +414,7 @@ func IsInf(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return value.NewTernary(ternary.ConvertFromBool(math.IsInf(f1.(*value.Float).Raw(), sign))), nil } -func IsNaN(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func IsNaN(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -427,47 +427,47 @@ func IsNaN(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return value.NewTernary(ternary.ConvertFromBool(math.IsNaN(f.(*value.Float).Raw()))), nil } -func MathLog(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func MathLog(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log) } -func Log10(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Log10(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log10) } -func Log1p(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Log1p(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log1p) } -func Log2(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Log2(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Log2) } -func Logb(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Logb(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Logb) } -func Pow(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Pow(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath2Args(fn, args, math.Pow) } -func Sin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sin(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Sin) } -func Sinh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sinh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Sinh) } -func Sqrt(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sqrt(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Sqrt) } -func Tan(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Tan(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Tan) } -func Tanh(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Tanh(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execMath1Arg(fn, args, math.Tanh) } @@ -510,19 +510,19 @@ func execFormatInt(fn parser.Function, args []value.Primary, base int) (value.Pr return value.NewString(s), nil } -func BinToDec(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func BinToDec(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execParseInt(fn, args, 2) } -func OctToDec(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func OctToDec(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execParseInt(fn, args, 8) } -func HexToDec(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func HexToDec(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execParseInt(fn, args, 16) } -func EnotationToDec(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func EnotationToDec(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -541,19 +541,19 @@ func EnotationToDec(fn parser.Function, args []value.Primary, _ *cmd.Flags) (val return value.NewFloat(f), nil } -func Bin(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Bin(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execFormatInt(fn, args, 2) } -func Oct(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Oct(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execFormatInt(fn, args, 8) } -func Hex(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Hex(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execFormatInt(fn, args, 16) } -func Enotation(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Enotation(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -568,7 +568,7 @@ func Enotation(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Pr return value.NewString(s), nil } -func NumberFormat(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func NumberFormat(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 1 || 5 < len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2, 3, 4, 5}) } @@ -612,18 +612,18 @@ func NumberFormat(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value } } - s := cmd.FormatNumber(p.(*value.Float).Raw(), precision, decimalPoint, thousandsSeparator, decimalSeparator) + s := option.FormatNumber(p.(*value.Float).Raw(), precision, decimalPoint, thousandsSeparator, decimalSeparator) value.Discard(p) return value.NewString(s), nil } -func Rand(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Rand(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if 0 < len(args) && len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{0, 2}) } - r := cmd.GetRand() + r := option.GetRand() if len(args) == 0 { return value.NewFloat(r.Float64()), nil @@ -747,7 +747,7 @@ func execStringsLen(fn parser.Function, args []value.Primary, stringsf func(stri return value.NewInteger(int64(result)), nil } -func execStringsPadding(fn parser.Function, args []value.Primary, direction Direction, flags *cmd.Flags) (value.Primary, error) { +func execStringsPadding(fn parser.Function, args []value.Primary, direction Direction, flags *option.Flags) (value.Primary, error) { if len(args) < 3 || 5 < len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{3, 4, 5}) } @@ -795,7 +795,7 @@ func execStringsPadding(fn parser.Function, args []value.Primary, direction Dire if 4 < len(args) { encs := value.ToString(args[4]) if !value.IsNull(encs) { - e, err := cmd.ParseEncoding(encs.(*value.String).Raw()) + e, err := option.ParseEncoding(encs.(*value.String).Raw()) value.Discard(encs) if err != nil || e == text.AUTO { @@ -815,8 +815,8 @@ func execStringsPadding(fn parser.Function, args []value.Primary, direction Dire strLen = text.ByteSize(str, enc) padstrLen = text.ByteSize(padstr, enc) case PaddingWidth: - strLen = cmd.TextWidth(str, flags) - padstrLen = cmd.TextWidth(padstr, flags) + strLen = option.TextWidth(str, flags) + padstrLen = option.TextWidth(padstr, flags) } if length <= strLen { @@ -838,7 +838,7 @@ func execStringsPadding(fn parser.Function, args []value.Primary, direction Dire case PaddingByteCount: w = text.RuneByteSize(r, enc) default: - w = cmd.RuneWidth(r, flags) + w = option.RuneWidth(r, flags) } l = l + w buf = append(buf, r) @@ -904,47 +904,47 @@ func execCryptoHMAC(fn parser.Function, args []value.Primary, cryptof func() has return value.NewString(r), nil } -func Trim(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Trim(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStringsTrim(fn, args, trim) } -func Ltrim(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Ltrim(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStringsTrim(fn, args, ltrim) } -func Rtrim(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Rtrim(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStringsTrim(fn, args, rtrim) } -func Upper(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Upper(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, strings.ToUpper) } -func Lower(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Lower(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, strings.ToLower) } -func Base64Encode(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Base64Encode(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, base64Encode) } -func Base64Decode(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Base64Decode(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, base64Decode) } -func HexEncode(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func HexEncode(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, hexEncode) } -func HexDecode(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func HexDecode(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStrings1Arg(fn, args, hexDecode) } -func Len(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Len(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execStringsLen(fn, args, utf8.RuneCountInString) } -func ByteLen(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func ByteLen(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 1 || 2 < len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1, 2}) } @@ -958,7 +958,7 @@ func ByteLen(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim if 1 < len(args) { encs := value.ToString(args[1]) if !value.IsNull(encs) { - e, err := cmd.ParseEncoding(encs.(*value.String).Raw()) + e, err := option.ParseEncoding(encs.(*value.String).Raw()) value.Discard(encs) if err != nil || e == text.AUTO { @@ -975,7 +975,7 @@ func ByteLen(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim return value.NewInteger(i), nil } -func Width(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Width(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -984,17 +984,17 @@ func Width(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Pr if value.IsNull(s) { return value.NewNull(), nil } - result := cmd.TextWidth(s.(*value.String).Raw(), flags) + result := option.TextWidth(s.(*value.String).Raw(), flags) value.Discard(s) return value.NewInteger(int64(result)), nil } -func Lpad(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Lpad(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execStringsPadding(fn, args, LeftDirection, flags) } -func Rpad(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Rpad(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execStringsPadding(fn, args, RightDirection, flags) } @@ -1051,15 +1051,15 @@ func substr(fn parser.Function, args []value.Primary, zeroBasedIndex bool) (valu return value.NewString(string(runes[start:end])), nil } -func Substring(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Substring(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return substr(fn, args, false) } -func Substr(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Substr(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return substr(fn, args, true) } -func Instr(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Instr(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 2 || 2 < len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1085,7 +1085,7 @@ func Instr(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar return value.NewInteger(int64(index)), nil } -func ListElem(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func ListElem(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 3 || 3 < len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{3}) } @@ -1123,7 +1123,7 @@ func ListElem(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Pri return value.NewString(list[index]), nil } -func ReplaceFn(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func ReplaceFn(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if 3 != len(args) { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{3}) } @@ -1228,7 +1228,7 @@ func prepareRegExpReplace(fn parser.Function, args []value.Primary) (string, *re return s, regExp, replStr, err } -func RegExpMatch(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func RegExpMatch(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { s, regExp, err := prepareRegExpMatch(fn, args) if err != nil { if err == regExpStrIsNull { @@ -1240,7 +1240,7 @@ func RegExpMatch(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value. return value.NewTernary(ternary.ConvertFromBool(regExp.MatchString(s))), nil } -func RegExpFind(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func RegExpFind(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { s, regExp, err := prepareRegExpMatch(fn, args) if err != nil { if err == regExpStrIsNull { @@ -1261,7 +1261,7 @@ func RegExpFind(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.P } } -func RegExpFindSubMatches(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func RegExpFindSubMatches(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { s, regExp, err := prepareRegExpMatch(fn, args) if err != nil { if err == regExpStrIsNull { @@ -1280,7 +1280,7 @@ func RegExpFindSubMatches(fn parser.Function, args []value.Primary, _ *cmd.Flags return value.NewString(string(b)), err } -func RegExpFindAll(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func RegExpFindAll(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { s, regExp, err := prepareRegExpMatch(fn, args) if err != nil { if err == regExpStrIsNull { @@ -1299,7 +1299,7 @@ func RegExpFindAll(fn parser.Function, args []value.Primary, _ *cmd.Flags) (valu return value.NewString(string(b)), err } -func RegExpReplace(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func RegExpReplace(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { s, regExp, replStr, err := prepareRegExpReplace(fn, args) if err != nil { if err == regExpStrIsNull { @@ -1311,7 +1311,7 @@ func RegExpReplace(fn parser.Function, args []value.Primary, _ *cmd.Flags) (valu return value.NewString(regExp.ReplaceAllString(s, replStr)), nil } -func TitleCase(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func TitleCase(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1325,7 +1325,7 @@ func TitleCase(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Pr return value.NewString(c.String(format.(*value.String).Raw())), nil } -func Format(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Format(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) < 1 { return nil, NewFunctionArgumentLengthErrorWithCustomArgs(fn, fn.Name, "at least 1 argument") } @@ -1343,7 +1343,7 @@ func Format(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prima return value.NewString(str), nil } -func JsonValue(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func JsonValue(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1369,39 +1369,39 @@ func JsonValue(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Pr return v, nil } -func Md5(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Md5(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCrypto(fn, args, md5.New) } -func Sha1(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha1(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCrypto(fn, args, sha1.New) } -func Sha256(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha256(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCrypto(fn, args, sha256.New) } -func Sha512(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha512(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCrypto(fn, args, sha512.New) } -func Md5Hmac(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Md5Hmac(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCryptoHMAC(fn, args, md5.New) } -func Sha1Hmac(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha1Hmac(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCryptoHMAC(fn, args, sha1.New) } -func Sha256Hmac(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha256Hmac(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCryptoHMAC(fn, args, sha256.New) } -func Sha512Hmac(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Sha512Hmac(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { return execCryptoHMAC(fn, args, sha512.New) } -func DatetimeFormat(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func DatetimeFormat(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1424,7 +1424,7 @@ func DatetimeFormat(fn parser.Function, args []value.Primary, flags *cmd.Flags) return value.NewString(str), nil } -func execDatetimeToInt(fn parser.Function, args []value.Primary, timef func(time.Time) int64, flags *cmd.Flags) (value.Primary, error) { +func execDatetimeToInt(fn parser.Function, args []value.Primary, timef func(time.Time) int64, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1439,7 +1439,7 @@ func execDatetimeToInt(fn parser.Function, args []value.Primary, timef func(time return value.NewInteger(result), nil } -func execDatetimeAdd(fn parser.Function, args []value.Primary, timef func(time.Time, int) time.Time, flags *cmd.Flags) (value.Primary, error) { +func execDatetimeAdd(fn parser.Function, args []value.Primary, timef func(time.Time, int) time.Time, flags *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1561,99 +1561,99 @@ func addNano(t time.Time, duration int) time.Time { return t.Add(dur * time.Nanosecond) } -func Year(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Year(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, year, flags) } -func Month(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Month(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, month, flags) } -func Day(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Day(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, day, flags) } -func Hour(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Hour(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, hour, flags) } -func Minute(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Minute(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, minute, flags) } -func Second(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Second(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, second, flags) } -func Millisecond(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Millisecond(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, millisecond, flags) } -func Microsecond(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Microsecond(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, microsecond, flags) } -func Nanosecond(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Nanosecond(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, nanosecond, flags) } -func Weekday(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Weekday(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, weekday, flags) } -func UnixTime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func UnixTime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, unixTime, flags) } -func UnixNanoTime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func UnixNanoTime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, unixNanoTime, flags) } -func DayOfYear(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func DayOfYear(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, dayOfYear, flags) } -func WeekOfYear(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func WeekOfYear(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeToInt(fn, args, weekOfYear, flags) } -func AddYear(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddYear(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addYear, flags) } -func AddMonth(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddMonth(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addMonth, flags) } -func AddDay(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddDay(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addDay, flags) } -func AddHour(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddHour(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addHour, flags) } -func AddMinute(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddMinute(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addMinute, flags) } -func AddSecond(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddSecond(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addSecond, flags) } -func AddMilli(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddMilli(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addMilli, flags) } -func AddMicro(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddMicro(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addMicro, flags) } -func AddNano(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func AddNano(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return execDatetimeAdd(fn, args, addNano, flags) } -func truncateDate(fn parser.Function, args []value.Primary, place int8, flags *cmd.Flags) (value.Primary, error) { +func truncateDate(fn parser.Function, args []value.Primary, place int8, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1676,19 +1676,19 @@ func truncateDate(fn parser.Function, args []value.Primary, place int8, flags *c return value.NewDatetime(time.Date(y, m, d, 0, 0, 0, 0, t.Location())), nil } -func TruncMonth(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncMonth(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDate(fn, args, 2, flags) } -func TruncDay(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncDay(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDate(fn, args, 1, flags) } -func TruncTime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncTime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDate(fn, args, 0, flags) } -func truncateDuration(fn parser.Function, args []value.Primary, dur time.Duration, flags *cmd.Flags) (value.Primary, error) { +func truncateDuration(fn parser.Function, args []value.Primary, dur time.Duration, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1703,27 +1703,27 @@ func truncateDuration(fn parser.Function, args []value.Primary, dur time.Duratio return value.NewDatetime(t), nil } -func TruncMinute(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncMinute(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDuration(fn, args, time.Hour, flags) } -func TruncSecond(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncSecond(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDuration(fn, args, time.Minute, flags) } -func TruncMilli(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncMilli(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDuration(fn, args, time.Second, flags) } -func TruncMicro(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncMicro(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDuration(fn, args, time.Millisecond, flags) } -func TruncNano(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TruncNano(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return truncateDuration(fn, args, time.Microsecond, flags) } -func DateDiff(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func DateDiff(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1751,7 +1751,7 @@ func DateDiff(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value return value.NewInteger(int64(dur.Hours() / 24)), nil } -func timeDiff(fn parser.Function, args []value.Primary, durf func(time.Duration) value.Primary, flags *cmd.Flags) (value.Primary, error) { +func timeDiff(fn parser.Function, args []value.Primary, durf func(time.Duration) value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 2 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{2}) } @@ -1784,15 +1784,15 @@ func durationNanoseconds(dur time.Duration) value.Primary { return value.NewInteger(dur.Nanoseconds()) } -func TimeDiff(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TimeDiff(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return timeDiff(fn, args, durationSeconds, flags) } -func TimeNanoDiff(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func TimeNanoDiff(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { return timeDiff(fn, args, durationNanoseconds, flags) } -func UTC(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func UTC(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1807,7 +1807,7 @@ func UTC(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Prim return value.NewDatetime(t), nil } -func MilliToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func MilliToDatetime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1822,7 +1822,7 @@ func MilliToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) return value.NewDatetime(time.Unix(i/1000, (i%1000)*1000000).In(flags.GetTimeLocation())), nil } -func NanoToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func NanoToDatetime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1837,7 +1837,7 @@ func NanoToDatetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) return value.NewDatetime(time.Unix(0, i).In(flags.GetTimeLocation())), nil } -func String(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func String(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1854,7 +1854,7 @@ func String(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prima } } -func Integer(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Integer(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1867,7 +1867,7 @@ func Integer(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim } } -func Float(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Float(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1885,7 +1885,7 @@ func Float(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primar } } -func Boolean(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Boolean(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1893,7 +1893,7 @@ func Boolean(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim return value.ToBoolean(args[0]), nil } -func Ternary(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Primary, error) { +func Ternary(fn parser.Function, args []value.Primary, _ *option.Flags) (value.Primary, error) { if len(args) != 1 { return nil, NewFunctionArgumentLengthError(fn, fn.Name, []int{1}) } @@ -1901,7 +1901,7 @@ func Ternary(fn parser.Function, args []value.Primary, _ *cmd.Flags) (value.Prim return value.NewTernary(args[0].Ternary()), nil } -func Datetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value.Primary, error) { +func Datetime(fn parser.Function, args []value.Primary, flags *option.Flags) (value.Primary, error) { conv := func(p value.Primary, location *time.Location) value.Primary { if dt := value.ToDatetime(p, flags.DatetimeFormat, location); !value.IsNull(dt) { return dt @@ -1937,7 +1937,7 @@ func Datetime(fn parser.Function, args []value.Primary, flags *cmd.Flags) (value return nil, NewFunctionInvalidArgumentError(fn, fn.Name, fmt.Sprintf("failed to load time zone %s", args[1].String())) } - l, err := cmd.GetLocation(s.(*value.String).Raw()) + l, err := option.GetLocation(s.(*value.String).Raw()) if err != nil { return nil, NewFunctionInvalidArgumentError(fn, fn.Name, fmt.Sprintf("failed to load time zone %s", args[1].String())) } diff --git a/lib/query/function_test.go b/lib/query/function_test.go index 259c5c6..30aed54 100644 --- a/lib/query/function_test.go +++ b/lib/query/function_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -23,7 +23,7 @@ type functionTest struct { Error string } -func testFunction(t *testing.T, f func(parser.Function, []value.Primary, *cmd.Flags) (value.Primary, error), tests []functionTest) { +func testFunction(t *testing.T, f func(parser.Function, []value.Primary, *option.Flags) (value.Primary, error), tests []functionTest) { for _, v := range tests { result, err := f(v.Function, v.Args, TestTx.Flags) if err != nil { diff --git a/lib/query/main_test.go b/lib/query/main_test.go index 54f9b30..762462c 100644 --- a/lib/query/main_test.go +++ b/lib/query/main_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" ) @@ -116,7 +116,7 @@ func setup() { _ = os.Mkdir(TestDir, 0755) } - cmd.TestTime = NowForTest + option.TestTime = NowForTest TestDataDir = filepath.Join(GetWD(), "..", "..", "testdata", "csv") @@ -189,7 +189,7 @@ func teardown() { } } -func initFlag(flags *cmd.Flags) { +func initFlag(flags *option.Flags) { cpu := runtime.NumCPU() / 2 if cpu < 1 { cpu = 1 @@ -200,8 +200,8 @@ func initFlag(flags *cmd.Flags) { flags.AnsiQuotes = false flags.StrictEqual = false flags.WaitTimeout = 15 - flags.ImportOptions = cmd.NewImportOptions() - flags.ExportOptions = cmd.NewExportOptions() + flags.ImportOptions = option.NewImportOptions() + flags.ExportOptions = option.NewExportOptions() flags.Quiet = false flags.LimitRecursion = 5 flags.CPU = cpu @@ -331,7 +331,7 @@ var ( func randomStr(length int) string { s := make([]rune, length) for i := 0; i < length; i++ { - s[i] = testLetterRunes[cmd.GetRand().Intn(len(testLetterRunes))] + s[i] = testLetterRunes[option.GetRand().Intn(len(testLetterRunes))] } return string(s) } diff --git a/lib/query/object_writer.go b/lib/query/object_writer.go index 0bc7e79..49d356f 100644 --- a/lib/query/object_writer.go +++ b/lib/query/object_writer.go @@ -5,7 +5,7 @@ import ( "bytes" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/go-text/color" "golang.org/x/crypto/ssh/terminal" @@ -17,7 +17,7 @@ const ( ) type ObjectWriter struct { - Flags *cmd.Flags + Flags *option.Flags Palette *color.Palette MaxWidth int @@ -99,7 +99,7 @@ func (w *ObjectWriter) write(s string, effect string, withoutLineBreak bool) { } else { w.writeToBuf(w.Palette.Render(effect, s)) } - w.Column = w.Column + cmd.TextWidth(s, w.Flags) + w.Column = w.Column + option.TextWidth(s, w.Flags) } } @@ -112,18 +112,18 @@ func (w *ObjectWriter) LeadingSpacesWidth() int { } func (w *ObjectWriter) FitInLine(s string) bool { - if w.MaxWidth-(w.Padding*2)-1 < w.Column+cmd.TextWidth(s, w.Flags) { + if w.MaxWidth-(w.Padding*2)-1 < w.Column+option.TextWidth(s, w.Flags) { return false } return true } func (w *ObjectWriter) WriteWithoutLineBreak(s string) { - w.WriteColorWithoutLineBreak(s, cmd.NoEffect) + w.WriteColorWithoutLineBreak(s, option.NoEffect) } func (w *ObjectWriter) Write(s string) { - w.WriteColor(s, cmd.NoEffect) + w.WriteColor(s, option.NoEffect) } func (w *ObjectWriter) WriteWithAutoLineBreak(s string) { @@ -151,7 +151,7 @@ func (w *ObjectWriter) writeWithAutoLineBreak(s string, useContinueMark bool, us } line := scanner.Text() - if useBlock && cmd.TrimSpace(line) == "```" { + if useBlock && option.TrimSpace(line) == "```" { preformatted = !preformatted continue } else { @@ -234,7 +234,7 @@ func (w *ObjectWriter) ClearBlock() { func (w *ObjectWriter) String() string { var header bytes.Buffer if 0 < len(w.Title1) || 0 < len(w.Title2) { - tw := cmd.TextWidth(w.Title1, w.Flags) + cmd.TextWidth(w.Title2, w.Flags) + tw := option.TextWidth(w.Title1, w.Flags) + option.TextWidth(w.Title2, w.Flags) if 0 < len(w.Title1) && 0 < len(w.Title2) { tw++ } diff --git a/lib/query/object_writer_test.go b/lib/query/object_writer_test.go index c74cb0a..7539084 100644 --- a/lib/query/object_writer_test.go +++ b/lib/query/object_writer_test.go @@ -3,7 +3,7 @@ package query import ( "testing" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" ) func TestObjectWriter_String(t *testing.T) { @@ -136,12 +136,12 @@ func TestObjectWriter_String(t *testing.T) { w.Title1 = "title1" w.Title2 = "title2" - w.Title2Effect = cmd.IdentifierEffect + w.Title2Effect = option.IdentifierEffect w.Write("aaa") w.BeginBlock() w.NewLine() - w.WriteColor("bbbbbbbbbb", cmd.StringEffect) + w.WriteColor("bbbbbbbbbb", option.StringEffect) w.Write(", ") w.Write("bbbbbbbbbb") diff --git a/lib/query/prepared_statement.go b/lib/query/prepared_statement.go index 83322f4..bb74637 100644 --- a/lib/query/prepared_statement.go +++ b/lib/query/prepared_statement.go @@ -3,7 +3,7 @@ package query import ( "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" ) @@ -40,7 +40,7 @@ func (m PreparedStatementMap) Exists(name string) bool { return m.exists(strings.ToUpper(name)) } -func (m PreparedStatementMap) Prepare(flags *cmd.Flags, expr parser.StatementPreparation) error { +func (m PreparedStatementMap) Prepare(flags *option.Flags, expr parser.StatementPreparation) error { stmt, err := NewPreparedStatement(flags, expr) if err != nil { return err @@ -75,7 +75,7 @@ type PreparedStatement struct { HolderNumber int } -func NewPreparedStatement(flags *cmd.Flags, expr parser.StatementPreparation) (*PreparedStatement, error) { +func NewPreparedStatement(flags *option.Flags, expr parser.StatementPreparation) (*PreparedStatement, error) { statements, holderNum, err := parser.Parse(expr.Statement.Raw(), expr.Name.Literal, true, flags.AnsiQuotes) if err != nil { return nil, NewPreparedStatementSyntaxError(err.(*parser.SyntaxError)) diff --git a/lib/query/processor.go b/lib/query/processor.go index c8b3495..6adc100 100644 --- a/lib/query/processor.go +++ b/lib/query/processor.go @@ -8,8 +8,8 @@ import ( "strings" "time" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/excmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -216,7 +216,7 @@ func (proc *Processor) ExecuteStatement(ctx context.Context, stmt parser.Stateme err = e } } else if !proc.Tx.Flags.ExportOptions.StripEndingLineBreak && - !(proc.Tx.Session.OutFile() != nil && exportOptions.Format == cmd.FIXED && exportOptions.SingleLine) { + !(proc.Tx.Session.OutFile() != nil && exportOptions.Format == option.FIXED && exportOptions.SingleLine) { _, err = writer.Write([]byte(proc.Tx.Flags.ExportOptions.LineBreak.Value())) } } @@ -722,8 +722,8 @@ func (proc *Processor) showExecutionTime(ctx context.Context) { return } - exectime := cmd.FormatNumber(time.Since(proc.measurementStart).Seconds(), 6, ".", ",", "") - stats := fmt.Sprintf(proc.Tx.Palette.Render(cmd.LableEffect, "Query Execution Time: ")+"%s seconds", exectime) + exectime := option.FormatNumber(time.Since(proc.measurementStart).Seconds(), 6, ".", ",", "") + stats := fmt.Sprintf(proc.Tx.Palette.Render(option.LableEffect, "Query Execution Time: ")+"%s seconds", exectime) proc.Log(stats, false) } diff --git a/lib/query/processor_test.go b/lib/query/processor_test.go index 863506b..6808370 100644 --- a/lib/query/processor_test.go +++ b/lib/query/processor_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -946,7 +946,7 @@ var processorExecuteStatementTests = []struct { NoHeader: false, Encoding: text.UTF8, LineBreak: text.LF, - Format: cmd.TSV, + Format: option.TSV, ForUpdate: true, }, }, @@ -1094,7 +1094,7 @@ func TestProcessor_ExecuteStatement(t *testing.T) { }() TestTx.Flags.Repository = TestDir - TestTx.Flags.ExportOptions.Format = cmd.CSV + TestTx.Flags.ExportOptions.Format = option.CSV tx := TestTx proc := NewProcessor(tx) diff --git a/lib/query/query.go b/lib/query/query.go index 4f14ed4..31cc079 100644 --- a/lib/query/query.go +++ b/lib/query/query.go @@ -5,8 +5,8 @@ import ( "strings" "sync/atomic" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" ) @@ -1017,8 +1017,8 @@ func SetTableAttribute(ctx context.Context, scope *ReferenceScope, query parser. } w := NewObjectWriter(scope.Tx) - w.WriteColorWithoutLineBreak("Path: ", cmd.LableEffect) - w.WriteColorWithoutLineBreak(fileInfo.Path, cmd.ObjectEffect) + w.WriteColorWithoutLineBreak("Path: ", option.LableEffect) + w.WriteColorWithoutLineBreak(fileInfo.Path, option.ObjectEffect) w.NewLine() writeTableAttribute(w, scope.Tx.Flags, fileInfo) w.NewLine() @@ -1031,7 +1031,7 @@ func SetTableAttribute(ctx context.Context, scope *ReferenceScope, query parser. w.Title2 = pi.Literal } } - w.Title2Effect = cmd.IdentifierEffect + w.Title2Effect = option.IdentifierEffect log = "\n" + w.String() + "\n" scope.Tx.CachedViews.Set(view) diff --git a/lib/query/query_test.go b/lib/query/query_test.go index bb7844f..f5dc149 100644 --- a/lib/query/query_test.go +++ b/lib/query/query_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -4239,7 +4239,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4259,7 +4259,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4275,7 +4275,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ';', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4310,7 +4310,7 @@ var setTableAttributeTests = []struct { Path: GetTestFilePath("table1.csv"), Delimiter: ',', DelimiterPositions: []int{2, 5, 10}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, SingleLine: true, LineBreak: text.LF, @@ -4336,7 +4336,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.TEXT, + Format: option.TEXT, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4352,7 +4352,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4368,7 +4368,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, ForUpdate: true, @@ -4393,7 +4393,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.LF, ForUpdate: true, @@ -4409,7 +4409,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.LF, ForUpdate: true, @@ -4443,7 +4443,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.CRLF, ForUpdate: true, @@ -4468,7 +4468,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, NoHeader: true, @@ -4494,7 +4494,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table1.csv"), Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.UTF8, LineBreak: text.LF, EncloseAll: true, @@ -4511,7 +4511,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table.json"), Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.HexDigits, @@ -4538,7 +4538,7 @@ var setTableAttributeTests = []struct { Expect: &FileInfo{ Path: GetTestFilePath("table.json"), Delimiter: ',', - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, PrettyPrint: true, diff --git a/lib/query/reference_scope.go b/lib/query/reference_scope.go index 530a904..40af7b2 100644 --- a/lib/query/reference_scope.go +++ b/lib/query/reference_scope.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -260,7 +260,7 @@ func (rs *ReferenceScope) CreateNode() *ReferenceScope { node.cachedFilePath = make(map[string]string) } if node.now.IsZero() { - node.now = cmd.Now(rs.Tx.Flags.GetTimeLocation()) + node.now = option.Now(rs.Tx.Flags.GetTimeLocation()) } return node @@ -312,7 +312,7 @@ func (rs *ReferenceScope) LoadFilePath(identifier string) (string, bool) { func (rs *ReferenceScope) Now() time.Time { if rs.now.IsZero() { - return cmd.Now(rs.Tx.Flags.GetTimeLocation()) + return option.Now(rs.Tx.Flags.GetTimeLocation()) } return rs.now } @@ -398,7 +398,7 @@ func (rs *ReferenceScope) GetTemporaryTable(name parser.Identifier) (*View, erro return nil, NewUndeclaredTemporaryTableError(name) } -func (rs *ReferenceScope) GetTemporaryTableWithInternalId(ctx context.Context, name parser.Identifier, flags *cmd.Flags) (view *View, err error) { +func (rs *ReferenceScope) GetTemporaryTableWithInternalId(ctx context.Context, name parser.Identifier, flags *option.Flags) (view *View, err error) { for i := range rs.Blocks { if view, err = rs.Blocks[i].TemporaryTables.GetWithInternalId(ctx, name, flags); err == nil { return diff --git a/lib/query/session.go b/lib/query/session.go index 2112f67..0499d3f 100644 --- a/lib/query/session.go +++ b/lib/query/session.go @@ -10,8 +10,8 @@ import ( "sync" "time" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" ) @@ -277,7 +277,7 @@ func (sess *Session) SetTerminal(t VirtualTerminal) { sess.mtx.Unlock() } -func (sess *Session) GetStdinView(ctx context.Context, flags *cmd.Flags, fileInfo *FileInfo, expr parser.Stdin) (*View, error) { +func (sess *Session) GetStdinView(ctx context.Context, flags *option.Flags, fileInfo *FileInfo, expr parser.Stdin) (*View, error) { if !sess.stdinViewMap.Exists(expr.String()) { if !sess.CanReadStdin { return nil, NewStdinEmptyError(expr) diff --git a/lib/query/sort_value.go b/lib/query/sort_value.go index 10a5bc1..a1a26c3 100644 --- a/lib/query/sort_value.go +++ b/lib/query/sort_value.go @@ -5,7 +5,7 @@ import ( "math" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -104,7 +104,7 @@ type SortValue struct { String string } -func NewSortValue(val value.Primary, flags *cmd.Flags) *SortValue { +func NewSortValue(val value.Primary, flags *option.Flags) *SortValue { sortValue := &SortValue{} if value.IsNull(val) { @@ -114,14 +114,14 @@ func NewSortValue(val value.Primary, flags *cmd.Flags) *SortValue { sortValue.Type = IntegerType sortValue.Integer = i.(*value.Integer).Raw() sortValue.Float = float64(sortValue.Integer) - sortValue.String = strings.ToUpper(cmd.TrimSpace(s.(*value.String).Raw())) + sortValue.String = strings.ToUpper(option.TrimSpace(s.(*value.String).Raw())) value.Discard(i) value.Discard(s) } else if f := value.ToFloat(val); !value.IsNull(f) { s := value.ToString(val) sortValue.Type = FloatType sortValue.Float = f.(*value.Float).Raw() - sortValue.String = strings.ToUpper(cmd.TrimSpace(s.(*value.String).Raw())) + sortValue.String = strings.ToUpper(option.TrimSpace(s.(*value.String).Raw())) value.Discard(f) value.Discard(s) } else if dt := value.ToDatetime(val, flags.DatetimeFormat, flags.GetTimeLocation()); !value.IsNull(dt) { @@ -138,7 +138,7 @@ func NewSortValue(val value.Primary, flags *cmd.Flags) *SortValue { } } else if s, ok := val.(*value.String); ok { sortValue.Type = StringType - sortValue.String = strings.ToUpper(cmd.TrimSpace(s.Raw())) + sortValue.String = strings.ToUpper(option.TrimSpace(s.Raw())) } else { sortValue.Type = NullType } diff --git a/lib/query/string_formatter.go b/lib/query/string_formatter.go index 884ad44..9352e7f 100644 --- a/lib/query/string_formatter.go +++ b/lib/query/string_formatter.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" ) @@ -171,9 +171,9 @@ func (f *StringFormatter) Format(format string, values []value.Primary) (string, switch ch { case 'q': - s = cmd.QuoteString(s) + s = option.QuoteString(s) case 'i': - s = cmd.QuoteIdentifier(s) + s = option.QuoteIdentifier(s) } s = fmt.Sprintf(placeholder.String(), s) diff --git a/lib/query/transaction.go b/lib/query/transaction.go index 0e90ecf..ac527e3 100644 --- a/lib/query/transaction.go +++ b/lib/query/transaction.go @@ -10,8 +10,8 @@ import ( "sync" "time" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -22,9 +22,9 @@ import ( type Transaction struct { Session *Session - Environment *cmd.Environment + Environment *option.Environment Palette *color.Palette - Flags *cmd.Flags + Flags *option.Flags WaitTimeout time.Duration RetryDelay time.Duration @@ -48,17 +48,17 @@ type Transaction struct { } func NewTransaction(ctx context.Context, defaultWaitTimeout time.Duration, retryDelay time.Duration, session *Session) (*Transaction, error) { - environment, err := cmd.NewEnvironment(ctx, defaultWaitTimeout, retryDelay) + environment, err := option.NewEnvironment(ctx, defaultWaitTimeout, retryDelay) if err != nil { return nil, ConvertLoadConfigurationError(err) } - flags, err := cmd.NewFlags(environment) + flags, err := option.NewFlags(environment) if err != nil { return nil, ConvertLoadConfigurationError(err) } - palette, err := cmd.NewPalette(environment) + palette, err := option.NewPalette(environment) if err != nil { return nil, ConvertLoadConfigurationError(err) } @@ -131,7 +131,7 @@ func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr p return NewCommitError(expr, err.Error()) } - if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileinfo.Format == cmd.FIXED && fileinfo.SingleLine) { + if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileinfo.Format == option.FIXED && fileinfo.SingleLine) { if _, err := fp.Write([]byte(tx.Flags.ExportOptions.LineBreak.Value())); err != nil { return NewCommitError(expr, err.Error()) } @@ -157,7 +157,7 @@ func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr p return NewCommitError(expr, err.Error()) } - if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileinfo.Format == cmd.FIXED && fileinfo.SingleLine) { + if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileinfo.Format == option.FIXED && fileinfo.SingleLine) { if _, err := fp.Write([]byte(tx.Flags.ExportOptions.LineBreak.Value())); err != nil { return NewCommitError(expr, err.Error()) } @@ -284,21 +284,21 @@ func (tx *Transaction) RUnlockStdin() { func (tx *Transaction) Error(s string) string { if tx.Palette != nil { - return tx.Palette.Render(cmd.ErrorEffect, s) + return tx.Palette.Render(option.ErrorEffect, s) } return s } func (tx *Transaction) Warn(s string) string { if tx.Palette != nil { - return tx.Palette.Render(cmd.WarnEffect, s) + return tx.Palette.Render(option.WarnEffect, s) } return s } func (tx *Transaction) Notice(s string) string { if tx.Palette != nil { - return tx.Palette.Render(cmd.NoticeEffect, s) + return tx.Palette.Render(option.NoticeEffect, s) } return s } @@ -337,7 +337,7 @@ var errNotAllowdFlagFormat = errors.New("not allowed flag format") var errInvalidFlagName = errors.New("invalid flag name") func (tx *Transaction) SetFormatFlag(value interface{}, outFile string) error { - return tx.setFlag(cmd.FormatFlag, value, outFile) + return tx.setFlag(option.FormatFlag, value, outFile) } func (tx *Transaction) SetFlag(key string, value interface{}) error { @@ -351,193 +351,193 @@ func (tx *Transaction) setFlag(key string, value interface{}, outFile string) er var err error switch strings.ToUpper(key) { - case cmd.RepositoryFlag: + case option.RepositoryFlag: if s, ok := value.(string); ok { err = tx.Flags.SetRepository(s) } else { err = errNotAllowdFlagFormat } - case cmd.TimezoneFlag: + case option.TimezoneFlag: if s, ok := value.(string); ok { err = tx.Flags.SetLocation(s) } else { err = errNotAllowdFlagFormat } - case cmd.DatetimeFormatFlag: + case option.DatetimeFormatFlag: if s, ok := value.(string); ok { tx.Flags.SetDatetimeFormat(s) } else { err = errNotAllowdFlagFormat } - case cmd.AnsiQuotesFlag: + case option.AnsiQuotesFlag: if b, ok := value.(bool); ok { tx.Flags.SetAnsiQuotes(b) } else { err = errNotAllowdFlagFormat } - case cmd.StrictEqualFlag: + case option.StrictEqualFlag: if b, ok := value.(bool); ok { tx.Flags.SetStrictEqual(b) } else { err = errNotAllowdFlagFormat } - case cmd.WaitTimeoutFlag: + case option.WaitTimeoutFlag: if f, ok := value.(float64); ok { tx.UpdateWaitTimeout(f, file.DefaultRetryDelay) } else { err = errNotAllowdFlagFormat } - case cmd.ImportFormatFlag: + case option.ImportFormatFlag: if s, ok := value.(string); ok { err = tx.Flags.SetImportFormat(s) } else { err = errNotAllowdFlagFormat } - case cmd.DelimiterFlag: + case option.DelimiterFlag: if s, ok := value.(string); ok { err = tx.Flags.SetDelimiter(s) } else { err = errNotAllowdFlagFormat } - case cmd.AllowUnevenFieldsFlag: + case option.AllowUnevenFieldsFlag: if b, ok := value.(bool); ok { tx.Flags.SetAllowUnevenFields(b) } else { err = errNotAllowdFlagFormat } - case cmd.DelimiterPositionsFlag: + case option.DelimiterPositionsFlag: if s, ok := value.(string); ok { err = tx.Flags.SetDelimiterPositions(s) } else { err = errNotAllowdFlagFormat } - case cmd.JsonQueryFlag: + case option.JsonQueryFlag: if s, ok := value.(string); ok { tx.Flags.SetJsonQuery(s) } else { err = errNotAllowdFlagFormat } - case cmd.EncodingFlag: + case option.EncodingFlag: if s, ok := value.(string); ok { err = tx.Flags.SetEncoding(s) } else { err = errNotAllowdFlagFormat } - case cmd.NoHeaderFlag: + case option.NoHeaderFlag: if b, ok := value.(bool); ok { tx.Flags.SetNoHeader(b) } else { err = errNotAllowdFlagFormat } - case cmd.WithoutNullFlag: + case option.WithoutNullFlag: if b, ok := value.(bool); ok { tx.Flags.SetWithoutNull(b) } else { err = errNotAllowdFlagFormat } - case cmd.FormatFlag: + case option.FormatFlag: if s, ok := value.(string); ok { err = tx.Flags.SetFormat(s, outFile, tx.Session.CanOutputToPipe) } else { err = errNotAllowdFlagFormat } - case cmd.ExportEncodingFlag: + case option.ExportEncodingFlag: if s, ok := value.(string); ok { err = tx.Flags.SetWriteEncoding(s) } else { err = errNotAllowdFlagFormat } - case cmd.ExportDelimiterFlag: + case option.ExportDelimiterFlag: if s, ok := value.(string); ok { err = tx.Flags.SetWriteDelimiter(s) } else { err = errNotAllowdFlagFormat } - case cmd.ExportDelimiterPositionsFlag: + case option.ExportDelimiterPositionsFlag: if s, ok := value.(string); ok { err = tx.Flags.SetWriteDelimiterPositions(s) } else { err = errNotAllowdFlagFormat } - case cmd.WithoutHeaderFlag: + case option.WithoutHeaderFlag: if b, ok := value.(bool); ok { tx.Flags.SetWithoutHeader(b) } else { err = errNotAllowdFlagFormat } - case cmd.LineBreakFlag: + case option.LineBreakFlag: if s, ok := value.(string); ok { err = tx.Flags.SetLineBreak(s) } else { err = errNotAllowdFlagFormat } - case cmd.EncloseAllFlag: + case option.EncloseAllFlag: if b, ok := value.(bool); ok { tx.Flags.SetEncloseAll(b) } else { err = errNotAllowdFlagFormat } - case cmd.JsonEscapeFlag: + case option.JsonEscapeFlag: if s, ok := value.(string); ok { err = tx.Flags.SetJsonEscape(s) } else { err = errNotAllowdFlagFormat } - case cmd.PrettyPrintFlag: + case option.PrettyPrintFlag: if b, ok := value.(bool); ok { tx.Flags.SetPrettyPrint(b) } else { err = errNotAllowdFlagFormat } - case cmd.StripEndingLineBreakFlag: + case option.StripEndingLineBreakFlag: if b, ok := value.(bool); ok { tx.Flags.SetStripEndingLineBreak(b) } else { err = errNotAllowdFlagFormat } - case cmd.EastAsianEncodingFlag: + case option.EastAsianEncodingFlag: if b, ok := value.(bool); ok { tx.Flags.SetEastAsianEncoding(b) } else { err = errNotAllowdFlagFormat } - case cmd.CountDiacriticalSignFlag: + case option.CountDiacriticalSignFlag: if b, ok := value.(bool); ok { tx.Flags.SetCountDiacriticalSign(b) } else { err = errNotAllowdFlagFormat } - case cmd.CountFormatCodeFlag: + case option.CountFormatCodeFlag: if b, ok := value.(bool); ok { tx.Flags.SetCountFormatCode(b) } else { err = errNotAllowdFlagFormat } - case cmd.ColorFlag: + case option.ColorFlag: if b, ok := value.(bool); ok { tx.UseColor(b) } else { err = errNotAllowdFlagFormat } - case cmd.QuietFlag: + case option.QuietFlag: if b, ok := value.(bool); ok { tx.Flags.SetQuiet(b) } else { err = errNotAllowdFlagFormat } - case cmd.LimitRecursion: + case option.LimitRecursion: if i, ok := value.(int64); ok { tx.Flags.SetLimitRecursion(i) } else { err = errNotAllowdFlagFormat } - case cmd.CPUFlag: + case option.CPUFlag: if i, ok := value.(int64); ok { tx.Flags.SetCPU(int(i)) } else { err = errNotAllowdFlagFormat } - case cmd.StatsFlag: + case option.StatsFlag: if b, ok := value.(bool); ok { tx.Flags.SetStats(b) } else { @@ -558,11 +558,11 @@ func (tx *Transaction) GetFlag(key string) (value.Primary, bool) { var ok = true switch strings.ToUpper(key) { - case cmd.RepositoryFlag: + case option.RepositoryFlag: val = value.NewString(tx.Flags.Repository) - case cmd.TimezoneFlag: + case option.TimezoneFlag: val = value.NewString(tx.Flags.Location) - case cmd.DatetimeFormatFlag: + case option.DatetimeFormatFlag: s := "" if 0 < len(tx.Flags.DatetimeFormat) { list := make([]string, 0, len(tx.Flags.DatetimeFormat)) @@ -572,71 +572,71 @@ func (tx *Transaction) GetFlag(key string) (value.Primary, bool) { s = "[" + strings.Join(list, ", ") + "]" } val = value.NewString(s) - case cmd.AnsiQuotesFlag: + case option.AnsiQuotesFlag: val = value.NewBoolean(tx.Flags.AnsiQuotes) - case cmd.StrictEqualFlag: + case option.StrictEqualFlag: val = value.NewBoolean(tx.Flags.StrictEqual) - case cmd.WaitTimeoutFlag: + case option.WaitTimeoutFlag: val = value.NewFloat(tx.Flags.WaitTimeout) - case cmd.ImportFormatFlag: + case option.ImportFormatFlag: val = value.NewString(tx.Flags.ImportOptions.Format.String()) - case cmd.DelimiterFlag: + case option.DelimiterFlag: val = value.NewString(string(tx.Flags.ImportOptions.Delimiter)) - case cmd.AllowUnevenFieldsFlag: + case option.AllowUnevenFieldsFlag: val = value.NewBoolean(tx.Flags.ImportOptions.AllowUnevenFields) - case cmd.DelimiterPositionsFlag: + case option.DelimiterPositionsFlag: s := fixedlen.DelimiterPositions(tx.Flags.ImportOptions.DelimiterPositions).String() if tx.Flags.ImportOptions.SingleLine { s = "S" + s } val = value.NewString(s) - case cmd.JsonQueryFlag: + case option.JsonQueryFlag: val = value.NewString(tx.Flags.ImportOptions.JsonQuery) - case cmd.EncodingFlag: + case option.EncodingFlag: val = value.NewString(tx.Flags.ImportOptions.Encoding.String()) - case cmd.NoHeaderFlag: + case option.NoHeaderFlag: val = value.NewBoolean(tx.Flags.ImportOptions.NoHeader) - case cmd.WithoutNullFlag: + case option.WithoutNullFlag: val = value.NewBoolean(tx.Flags.ImportOptions.WithoutNull) - case cmd.FormatFlag: + case option.FormatFlag: val = value.NewString(tx.Flags.ExportOptions.Format.String()) - case cmd.ExportEncodingFlag: + case option.ExportEncodingFlag: val = value.NewString(tx.Flags.ExportOptions.Encoding.String()) - case cmd.ExportDelimiterFlag: + case option.ExportDelimiterFlag: val = value.NewString(string(tx.Flags.ExportOptions.Delimiter)) - case cmd.ExportDelimiterPositionsFlag: + case option.ExportDelimiterPositionsFlag: s := fixedlen.DelimiterPositions(tx.Flags.ExportOptions.DelimiterPositions).String() if tx.Flags.ExportOptions.SingleLine { s = "S" + s } val = value.NewString(s) - case cmd.WithoutHeaderFlag: + case option.WithoutHeaderFlag: val = value.NewBoolean(tx.Flags.ExportOptions.WithoutHeader) - case cmd.LineBreakFlag: + case option.LineBreakFlag: val = value.NewString(tx.Flags.ExportOptions.LineBreak.String()) - case cmd.EncloseAllFlag: + case option.EncloseAllFlag: val = value.NewBoolean(tx.Flags.ExportOptions.EncloseAll) - case cmd.JsonEscapeFlag: - val = value.NewString(cmd.JsonEscapeTypeToString(tx.Flags.ExportOptions.JsonEscape)) - case cmd.PrettyPrintFlag: + case option.JsonEscapeFlag: + val = value.NewString(option.JsonEscapeTypeToString(tx.Flags.ExportOptions.JsonEscape)) + case option.PrettyPrintFlag: val = value.NewBoolean(tx.Flags.ExportOptions.PrettyPrint) - case cmd.StripEndingLineBreakFlag: + case option.StripEndingLineBreakFlag: val = value.NewBoolean(tx.Flags.ExportOptions.StripEndingLineBreak) - case cmd.EastAsianEncodingFlag: + case option.EastAsianEncodingFlag: val = value.NewBoolean(tx.Flags.ExportOptions.EastAsianEncoding) - case cmd.CountDiacriticalSignFlag: + case option.CountDiacriticalSignFlag: val = value.NewBoolean(tx.Flags.ExportOptions.CountDiacriticalSign) - case cmd.CountFormatCodeFlag: + case option.CountFormatCodeFlag: val = value.NewBoolean(tx.Flags.ExportOptions.CountFormatCode) - case cmd.ColorFlag: + case option.ColorFlag: val = value.NewBoolean(tx.Flags.ExportOptions.Color) - case cmd.QuietFlag: + case option.QuietFlag: val = value.NewBoolean(tx.Flags.Quiet) - case cmd.LimitRecursion: + case option.LimitRecursion: val = value.NewInteger(tx.Flags.LimitRecursion) - case cmd.CPUFlag: + case option.CPUFlag: val = value.NewInteger(int64(tx.Flags.CPU)) - case cmd.StatsFlag: + case option.StatsFlag: val = value.NewBoolean(tx.Flags.Stats) default: ok = false diff --git a/lib/query/transaction_test.go b/lib/query/transaction_test.go index 608bb18..b974d0f 100644 --- a/lib/query/transaction_test.go +++ b/lib/query/transaction_test.go @@ -8,7 +8,7 @@ import ( "sync" "testing" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/go-text" @@ -38,7 +38,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("created_file.csv"), Handler: ch, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -63,7 +63,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("updated_file_1.csv"), Handler: uh, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -77,7 +77,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("created_file.csv"), Handler: ch, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -87,7 +87,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("updated_file_1.csv"), Handler: uh, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -144,7 +144,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("created_file_1.csv"), Handler: ch, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -169,7 +169,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("updated_file_1.csv"), Handler: uh, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -183,7 +183,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("created_file_1.csv"), Handler: ch, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, @@ -193,7 +193,7 @@ func TestTransaction_Commit(t *testing.T) { Path: GetTestFilePath("updated_file_1.csv"), Handler: uh, Encoding: text.UTF8, - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', LineBreak: text.LF, }, diff --git a/lib/query/utils.go b/lib/query/utils.go index 1046482..9047a3c 100644 --- a/lib/query/utils.go +++ b/lib/query/utils.go @@ -7,7 +7,7 @@ import ( "sync" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/ternary" @@ -71,7 +71,7 @@ func InStrSliceWithCaseInsensitive(s string, list []string) bool { return false } -func Distinguish(list []value.Primary, flags *cmd.Flags) []value.Primary { +func Distinguish(list []value.Primary, flags *option.Flags) []value.Primary { values := make(map[string]int, 40) valueKeys := make([]string, 0, 40) @@ -125,7 +125,7 @@ func PutComparisonkeysBuf(buf *bytes.Buffer) { comparisonKeysBufPool.Put(buf) } -func SerializeComparisonKeys(buf *bytes.Buffer, values []value.Primary, flags *cmd.Flags) { +func SerializeComparisonKeys(buf *bytes.Buffer, values []value.Primary, flags *option.Flags) { for i, val := range values { if 0 < i { buf.WriteByte(58) @@ -139,7 +139,7 @@ func SerializeComparisonKeys(buf *bytes.Buffer, values []value.Primary, flags *c } } -func SerializeKey(buf *bytes.Buffer, val value.Primary, flags *cmd.Flags) { +func SerializeKey(buf *bytes.Buffer, val value.Primary, flags *option.Flags) { if value.IsNull(val) { serializeNull(buf) } else if in := value.ToIntegerStrictly(val); !value.IsNull(in) { @@ -208,12 +208,12 @@ func serializeDatetimeFromUnixNano(buf *bytes.Buffer, t int64) { func serializeString(buf *bytes.Buffer, s string) { buf.Write([]byte{91, 83, 93}) - buf.WriteString(strings.ToUpper(cmd.TrimSpace(s))) + buf.WriteString(strings.ToUpper(option.TrimSpace(s))) } func serializeCaseSensitiveString(buf *bytes.Buffer, s string) { buf.Write([]byte{91, 83, 93}) - buf.WriteString(cmd.TrimSpace(s)) + buf.WriteString(option.TrimSpace(s)) } func serializeBoolean(buf *bytes.Buffer, b bool) { diff --git a/lib/query/view.go b/lib/query/view.go index 752e7af..fd9cdc9 100644 --- a/lib/query/view.go +++ b/lib/query/view.go @@ -17,9 +17,9 @@ import ( "strings" "sync" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" "github.com/mithrandie/csvq/lib/json" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -200,9 +200,9 @@ func loadView(ctx context.Context, scope *ReferenceScope, tableExpr parser.Query } options.Delimiter = d[0] if options.Delimiter == '\t' { - options.Format = cmd.TSV + options.Format = option.TSV } else { - options.Format = cmd.CSV + options.Format = option.CSV } case parser.FIXED: if felem == nil { @@ -228,7 +228,7 @@ func loadView(ctx context.Context, scope *ReferenceScope, tableExpr parser.Query return nil, NewTableObjectArgumentsLengthError(tableObject, 5) } options.DelimiterPositions = positions - options.Format = cmd.FIXED + options.Format = option.FIXED case parser.JSON, parser.JSONL: if felem == nil { return nil, NewTableObjectInvalidArgumentError(tableObject, "json query is not specified") @@ -243,15 +243,15 @@ func loadView(ctx context.Context, scope *ReferenceScope, tableExpr parser.Query options.JsonQuery = felem.(*value.String).Raw() options.Encoding = text.UTF8 if tableObject.Type.Token == parser.JSONL { - options.Format = cmd.JSONL + options.Format = option.JSONL } else { - options.Format = cmd.JSON + options.Format = option.JSON } case parser.LTSV: if 2 < len(tableObject.Args) { return nil, NewTableObjectJsonArgumentsLengthError(tableObject, 3) } - options.Format = cmd.LTSV + options.Format = option.LTSV withoutNullIdx, noHeaderIdx = noHeaderIdx, withoutNullIdx default: return nil, NewInvalidTableObjectError(tableObject, tableObject.Type.Literal) @@ -309,7 +309,7 @@ func loadView(ctx context.Context, scope *ReferenceScope, tableExpr parser.Query } if args[encodingIdx] != nil { - if options.Encoding, err = cmd.ParseEncoding(args[0].(*value.String).Raw()); err != nil { + if options.Encoding, err = option.ParseEncoding(args[0].(*value.String).Raw()); err != nil { return nil, NewTableObjectInvalidArgumentError(tableObject, err.Error()) } } @@ -341,7 +341,7 @@ func loadView(ctx context.Context, scope *ReferenceScope, tableExpr parser.Query case parser.Identifier, parser.Stdin: options := scope.Tx.Flags.ImportOptions.Copy() - options.Format = cmd.AutoSelect + options.Format = option.AutoSelect view, err = loadObject( ctx, @@ -589,17 +589,17 @@ func loadObject( forUpdate bool, useInternalId bool, isInlineObject bool, - options cmd.ImportOptions, + options option.ImportOptions, ) (*View, error) { if stdin, ok := tablePath.(parser.Stdin); ok { - if options.Format == cmd.AutoSelect { + if options.Format == option.AutoSelect { options.Format = scope.Tx.Flags.ImportOptions.Format } switch options.Format { - case cmd.TSV: + case option.TSV: options.Delimiter = '\t' - case cmd.JSON, cmd.JSONL: + case option.JSON, option.JSONL: options.Encoding = text.UTF8 } @@ -725,7 +725,7 @@ func cacheViewFromFile( tablePath parser.QueryExpression, forUpdate bool, isInlineObject bool, - options cmd.ImportOptions, + options option.ImportOptions, ) (string, error) { scope.Tx.viewLoadingMutex.Lock() defer scope.Tx.viewLoadingMutex.Unlock() @@ -781,7 +781,7 @@ func cacheViewFromFile( if !ok || (forUpdate && !view.FileInfo.ForUpdate) { fileInfo.DelimiterPositions = options.DelimiterPositions fileInfo.SingleLine = options.SingleLine - fileInfo.JsonQuery = cmd.TrimSpace(options.JsonQuery) + fileInfo.JsonQuery = option.TrimSpace(options.JsonQuery) fileInfo.LineBreak = scope.Tx.Flags.ExportOptions.LineBreak fileInfo.NoHeader = options.NoHeader fileInfo.EncloseAll = scope.Tx.Flags.ExportOptions.EncloseAll @@ -860,15 +860,15 @@ func cacheViewFromFile( return filePath, nil } -func loadViewFromFile(ctx context.Context, flags *cmd.Flags, fp io.ReadSeeker, fileInfo *FileInfo, options cmd.ImportOptions, expr parser.QueryExpression) (*View, error) { +func loadViewFromFile(ctx context.Context, flags *option.Flags, fp io.ReadSeeker, fileInfo *FileInfo, options option.ImportOptions, expr parser.QueryExpression) (*View, error) { switch fileInfo.Format { - case cmd.FIXED: + case option.FIXED: return loadViewFromFixedLengthTextFile(ctx, fp, fileInfo, options.WithoutNull, expr) - case cmd.LTSV: + case option.LTSV: return loadViewFromLTSVFile(ctx, flags, fp, fileInfo, options.WithoutNull, expr) - case cmd.JSON: + case option.JSON: return loadViewFromJsonFile(fp, fileInfo, expr) - case cmd.JSONL: + case option.JSONL: return loadViewFromJsonLinesFile(ctx, flags, fp, fileInfo, expr) } return loadViewFromCSVFile(ctx, fp, fileInfo, options.AllowUnevenFields, options.WithoutNull, expr) @@ -1021,7 +1021,7 @@ func loadViewFromCSVFile(ctx context.Context, fp io.ReadSeeker, fileInfo *FileIn return view, nil } -func loadViewFromLTSVFile(ctx context.Context, flags *cmd.Flags, fp io.ReadSeeker, fileInfo *FileInfo, withoutNull bool, expr parser.QueryExpression) (*View, error) { +func loadViewFromLTSVFile(ctx context.Context, flags *option.Flags, fp io.ReadSeeker, fileInfo *FileInfo, withoutNull bool, expr parser.QueryExpression) (*View, error) { enc, err := text.DetectInSpecifiedEncoding(fp, fileInfo.Encoding) if err != nil { return nil, NewCannotDetectFileEncodingError(expr) @@ -1171,7 +1171,7 @@ func loadViewFromJsonFile(fp io.Reader, fileInfo *FileInfo, expr parser.QueryExp return view, nil } -func loadViewFromJsonLinesFile(ctx context.Context, flags *cmd.Flags, fp io.ReadSeeker, fileInfo *FileInfo, expr parser.QueryExpression) (*View, error) { +func loadViewFromJsonLinesFile(ctx context.Context, flags *option.Flags, fp io.ReadSeeker, fileInfo *FileInfo, expr parser.QueryExpression) (*View, error) { var err error headerList := make([]string, 0, 32) headerMap := make(map[string]bool, 32) @@ -1318,7 +1318,7 @@ func NewDualView() *View { } } -func NewViewFromGroupedRecord(ctx context.Context, flags *cmd.Flags, referenceRecord ReferenceRecord) (*View, error) { +func NewViewFromGroupedRecord(ctx context.Context, flags *option.Flags, referenceRecord ReferenceRecord) (*View, error) { view := NewView() view.Header = referenceRecord.view.Header record := referenceRecord.view.RecordSet[referenceRecord.recordIndex] @@ -1506,7 +1506,7 @@ func (view *View) group(ctx context.Context, scope *ReferenceScope, items []pars return nil } -func (view *View) groupAll(ctx context.Context, flags *cmd.Flags) error { +func (view *View) groupAll(ctx context.Context, flags *option.Flags) error { if 0 < view.RecordLen() { record := make(Record, view.FieldLen()) @@ -1695,7 +1695,7 @@ func (view *View) Select(ctx context.Context, scope *ReferenceScope, clause pars return nil } -func (view *View) GenerateComparisonKeys(ctx context.Context, flags *cmd.Flags) error { +func (view *View) GenerateComparisonKeys(ctx context.Context, flags *option.Flags) error { view.comparisonKeysInEachRecord = make([]string, view.RecordLen()) return NewGoroutineTaskManager(view.RecordLen(), -1, flags.CPU).Run(ctx, func(index int) error { @@ -2174,7 +2174,7 @@ func (view *View) insert(ctx context.Context, fields []parser.QueryExpression, r return len(recordValues), nil } -func (view *View) replace(ctx context.Context, flags *cmd.Flags, fields []parser.QueryExpression, recordValues [][]value.Primary, keys []parser.QueryExpression) (int, error) { +func (view *View) replace(ctx context.Context, flags *option.Flags, fields []parser.QueryExpression, recordValues [][]value.Primary, keys []parser.QueryExpression) (int, error) { fieldIndices, err := view.FieldIndices(fields) if err != nil { return 0, err @@ -2271,7 +2271,7 @@ func (view *View) replace(ctx context.Context, flags *cmd.Flags, fields []parser return len(insertRecords) + replacedCount, nil } -func (view *View) Fix(ctx context.Context, flags *cmd.Flags) error { +func (view *View) Fix(ctx context.Context, flags *option.Flags) error { fieldLen := len(view.selectFields) resize := false if fieldLen != view.FieldLen() { @@ -2338,7 +2338,7 @@ func (view *View) Fix(ctx context.Context, flags *cmd.Flags) error { return nil } -func (view *View) Union(ctx context.Context, flags *cmd.Flags, calcView *View, all bool) (err error) { +func (view *View) Union(ctx context.Context, flags *option.Flags, calcView *View, all bool) (err error) { view.RecordSet = view.RecordSet.Merge(calcView.RecordSet) view.FileInfo = nil @@ -2363,7 +2363,7 @@ func (view *View) Union(ctx context.Context, flags *cmd.Flags, calcView *View, a return } -func (view *View) Except(ctx context.Context, flags *cmd.Flags, calcView *View, all bool) (err error) { +func (view *View) Except(ctx context.Context, flags *option.Flags, calcView *View, all bool) (err error) { if err = view.GenerateComparisonKeys(ctx, flags); err != nil { return err } @@ -2397,7 +2397,7 @@ func (view *View) Except(ctx context.Context, flags *cmd.Flags, calcView *View, return } -func (view *View) Intersect(ctx context.Context, flags *cmd.Flags, calcView *View, all bool) (err error) { +func (view *View) Intersect(ctx context.Context, flags *option.Flags, calcView *View, all bool) (err error) { if err = view.GenerateComparisonKeys(ctx, flags); err != nil { return err } diff --git a/lib/query/view_map.go b/lib/query/view_map.go index a53d8ef..952b95b 100644 --- a/lib/query/view_map.go +++ b/lib/query/view_map.go @@ -5,7 +5,7 @@ import ( "errors" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/file" @@ -59,7 +59,7 @@ func (m ViewMap) Get(fpath parser.Identifier) (*View, error) { return nil, errTableNotLoaded } -func (m ViewMap) GetWithInternalId(ctx context.Context, fpath parser.Identifier, flags *cmd.Flags) (*View, error) { +func (m ViewMap) GetWithInternalId(ctx context.Context, fpath parser.Identifier, flags *option.Flags) (*View, error) { if view, ok := m.Load(fpath.Literal); ok { ret := view.Copy() diff --git a/lib/query/view_test.go b/lib/query/view_test.go index 6ee8305..12902b8 100644 --- a/lib/query/view_test.go +++ b/lib/query/view_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/value" @@ -26,7 +26,7 @@ var viewLoadTests = []struct { ForUpdate bool UseInternalId bool Stdin string - ImportFormat cmd.Format + ImportFormat option.Format Delimiter rune AllowUnevenFields bool DelimiterPositions []int @@ -309,7 +309,7 @@ var viewLoadTests = []struct { }, }, Stdin: "column1\tcolumn2\n1\t\"str1\"", - ImportFormat: cmd.TSV, + ImportFormat: option.TSV, Result: &View{ Header: NewHeader("t", []string{"column1", "column2"}), RecordSet: []Record{ @@ -320,7 +320,7 @@ var viewLoadTests = []struct { }, FileInfo: &FileInfo{ Path: "STDIN", - Format: cmd.TSV, + Format: option.TSV, Delimiter: '\t', Encoding: text.UTF8, LineBreak: text.LF, @@ -390,7 +390,7 @@ var viewLoadTests = []struct { }, }, Stdin: "{\"key\":[{\"column1\": 1, \"column2\": \"str1\"}]}", - ImportFormat: cmd.JSON, + ImportFormat: option.JSON, JsonQuery: "key{}", Result: &View{ Header: NewHeader("t", []string{"column1", "column2"}), @@ -404,7 +404,7 @@ var viewLoadTests = []struct { Path: "STDIN", Delimiter: ',', JsonQuery: "key{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, ViewType: ViewTypeStdin, @@ -432,7 +432,7 @@ var viewLoadTests = []struct { }, }, Stdin: "{\"column1\": 1, \"column2\": \"str1\"}\n{\"column1\": 2, \"column2\": \"str2\"}", - ImportFormat: cmd.JSONL, + ImportFormat: option.JSONL, JsonQuery: "", Result: &View{ Header: NewHeader("t", []string{"column1", "column2"}), @@ -450,7 +450,7 @@ var viewLoadTests = []struct { Path: "STDIN", Delimiter: ',', JsonQuery: "", - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, LineBreak: text.LF, ViewType: ViewTypeStdin, @@ -478,7 +478,7 @@ var viewLoadTests = []struct { }, }, Stdin: "{\"column1\": 1, \"column2\": \"str1\"}\n\"str\"", - ImportFormat: cmd.JSONL, + ImportFormat: option.JSONL, JsonQuery: "", Error: "json lines must be an array of objects", }, @@ -490,7 +490,7 @@ var viewLoadTests = []struct { }, }, Stdin: "[{\"item1\": \"value\\u00221\",\"item2\": 1},{\"item1\": \"value2\",\"item2\": 2}]", - ImportFormat: cmd.JSON, + ImportFormat: option.JSON, JsonQuery: "{}", Result: &View{ Header: NewHeader("t", []string{"item1", "item2"}), @@ -508,7 +508,7 @@ var viewLoadTests = []struct { Path: "STDIN", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.HexDigits, @@ -539,7 +539,7 @@ var viewLoadTests = []struct { }, }, Stdin: "[{\"item1\": \"\\u0076\\u0061\\u006c\\u0075\\u0065\\u0031\",\"item2\": 1},{\"item1\": \"\\u0076\\u0061\\u006c\\u0075\\u0065\\u0032\",\"item2\": 2}]", - ImportFormat: cmd.JSON, + ImportFormat: option.JSON, JsonQuery: "{}", Result: &View{ Header: NewHeader("t", []string{"item1", "item2"}), @@ -557,7 +557,7 @@ var viewLoadTests = []struct { Path: "STDIN", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.AllWithHexDigits, @@ -588,13 +588,13 @@ var viewLoadTests = []struct { }, }, Stdin: "{\"key\":[{\"column1\": 1, \"column2\": \"str1\"}]}", - ImportFormat: cmd.JSON, + ImportFormat: option.JSON, JsonQuery: "key{", Error: "json loading error: column 4: unexpected termination", }, { Name: "LoadView Fixed-Length Text File", - ImportFormat: cmd.FIXED, + ImportFormat: option.FIXED, From: parser.FromClause{ Tables: []parser.QueryExpression{ parser.Table{ @@ -622,7 +622,7 @@ var viewLoadTests = []struct { Path: "fixed_length.txt", Delimiter: ',', DelimiterPositions: []int{7, 12}, - Format: cmd.FIXED, + Format: option.FIXED, NoHeader: false, Encoding: text.UTF8, LineBreak: text.LF, @@ -637,7 +637,7 @@ var viewLoadTests = []struct { { Name: "LoadView Fixed-Length Text File NoHeader", NoHeader: true, - ImportFormat: cmd.FIXED, + ImportFormat: option.FIXED, From: parser.FromClause{ Tables: []parser.QueryExpression{ parser.Table{ @@ -669,7 +669,7 @@ var viewLoadTests = []struct { Path: "fixed_length.txt", Delimiter: ',', DelimiterPositions: []int{7, 12}, - Format: cmd.FIXED, + Format: option.FIXED, NoHeader: true, Encoding: text.UTF8, LineBreak: text.LF, @@ -683,7 +683,7 @@ var viewLoadTests = []struct { }, { Name: "LoadView Fixed-Length Text File Position Error", - ImportFormat: cmd.FIXED, + ImportFormat: option.FIXED, DelimiterPositions: []int{6, 2}, From: parser.FromClause{ Tables: []parser.QueryExpression{ @@ -812,7 +812,7 @@ var viewLoadTests = []struct { FileInfo: &FileInfo{ Path: "table5.csv", Delimiter: ',', - Format: cmd.CSV, + Format: option.CSV, Encoding: text.SJIS, LineBreak: text.LF, NoHeader: true, @@ -856,7 +856,7 @@ var viewLoadTests = []struct { FileInfo: &FileInfo{ Path: "table3.tsv", Delimiter: '\t', - Format: cmd.TSV, + Format: option.TSV, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1065,7 +1065,7 @@ var viewLoadTests = []struct { Path: "fixed_length.txt", Delimiter: ',', DelimiterPositions: []int{7, 12}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1110,7 +1110,7 @@ var viewLoadTests = []struct { Path: "fixed_length_bom.txt", Delimiter: ',', DelimiterPositions: []int{7, 12}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8M, LineBreak: text.LF, }, @@ -1155,7 +1155,7 @@ var viewLoadTests = []struct { Path: "fixed_length_sl.txt", Delimiter: ',', DelimiterPositions: []int{1, 5}, - Format: cmd.FIXED, + Format: option.FIXED, Encoding: text.UTF8, LineBreak: text.LF, SingleLine: true, @@ -1266,7 +1266,7 @@ var viewLoadTests = []struct { Path: "table.json", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1307,7 +1307,7 @@ var viewLoadTests = []struct { Path: "table_h.json", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.HexDigits, @@ -1349,7 +1349,7 @@ var viewLoadTests = []struct { Path: "table_a.json", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSON, + Format: option.JSON, Encoding: text.UTF8, LineBreak: text.LF, JsonEscape: json.AllWithHexDigits, @@ -1438,7 +1438,7 @@ var viewLoadTests = []struct { Path: "table7.jsonl", Delimiter: ',', JsonQuery: "{}", - Format: cmd.JSONL, + Format: option.JSONL, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1481,7 +1481,7 @@ var viewLoadTests = []struct { FileInfo: &FileInfo{ Path: "table6.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1528,7 +1528,7 @@ var viewLoadTests = []struct { FileInfo: &FileInfo{ Path: "table6.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8, LineBreak: text.LF, }, @@ -1571,7 +1571,7 @@ var viewLoadTests = []struct { FileInfo: &FileInfo{ Path: "table6_bom.ltsv", Delimiter: ',', - Format: cmd.LTSV, + Format: option.LTSV, Encoding: text.UTF8M, LineBreak: text.LF, }, @@ -2462,7 +2462,7 @@ var viewLoadTests = []struct { }, FileInfo: &FileInfo{ Path: "", - Format: cmd.JSON, + Format: option.JSON, Delimiter: ',', JsonQuery: "{column1, column2}", Encoding: text.UTF8, @@ -2586,7 +2586,7 @@ var viewLoadTests = []struct { }, FileInfo: &FileInfo{ Path: "", - Format: cmd.JSON, + Format: option.JSON, Delimiter: ',', JsonQuery: "{}", Encoding: text.UTF8, @@ -2629,7 +2629,7 @@ var viewLoadTests = []struct { }, FileInfo: &FileInfo{ Path: "", - Format: cmd.JSON, + Format: option.JSON, Delimiter: ',', JsonQuery: "{}", Encoding: text.UTF8, @@ -2689,7 +2689,7 @@ var viewLoadTests = []struct { }, FileInfo: &FileInfo{ Path: "", - Format: cmd.CSV, + Format: option.CSV, Delimiter: ',', JsonQuery: "", Encoding: text.UTF8, diff --git a/lib/syntax/element.go b/lib/syntax/element.go index f970724..24d36e7 100644 --- a/lib/syntax/element.go +++ b/lib/syntax/element.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/go-text/color" ) @@ -277,7 +277,7 @@ type String string func (e String) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.StringEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.StringEffect, s)) } return s } @@ -287,7 +287,7 @@ type Integer string func (e Integer) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.NumberEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.NumberEffect, s)) } return s } @@ -297,7 +297,7 @@ type Float string func (e Float) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.NumberEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.NumberEffect, s)) } return s } @@ -307,7 +307,7 @@ type Identifier string func (e Identifier) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(cmd.IdentifierEffect, s) + s = p.Render(option.IdentifierEffect, s) } return s } @@ -317,7 +317,7 @@ type Datetime string func (e Datetime) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.DatetimeEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.DatetimeEffect, s)) } return s } @@ -327,7 +327,7 @@ type Boolean string func (e Boolean) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.BooleanEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.BooleanEffect, s)) } return s } @@ -337,7 +337,7 @@ type Ternary string func (e Ternary) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.TernaryEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.TernaryEffect, s)) } return s } @@ -347,7 +347,7 @@ type Null string func (e Null) Format(p *color.Palette) string { s := string(e) if p != nil { - s = p.Render(ItalicEffect, p.Render(cmd.NullEffect, s)) + s = p.Render(ItalicEffect, p.Render(option.NullEffect, s)) } return s } diff --git a/lib/syntax/element_test.go b/lib/syntax/element_test.go index 86c70f8..51bb62e 100644 --- a/lib/syntax/element_test.go +++ b/lib/syntax/element_test.go @@ -4,14 +4,14 @@ import ( "context" "testing" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/go-text/color" ) -var syntaxTestEnv, _ = cmd.NewEnvironment(context.Background(), file.DefaultWaitTimeout, file.DefaultRetryDelay) -var syntaxTestPalette, _ = cmd.NewPalette(syntaxTestEnv) +var syntaxTestEnv, _ = option.NewEnvironment(context.Background(), file.DefaultWaitTimeout, file.DefaultRetryDelay) +var syntaxTestPalette, _ = option.NewPalette(syntaxTestEnv) func TestName_Format(t *testing.T) { var e Name = "str" @@ -52,7 +52,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Option{String("str1"), String("str2")}}, UsePalette: true, - Expect: "[" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")) + "]", + Expect: "[" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")) + "]", }, { Grammar: []Element{FollowingContinuousOption{String("str1"), String("str2")}}, @@ -67,7 +67,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{ContinuousOption{String("str1"), String("str2")}}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")) + " [, " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")) + " ...]", + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")) + " [, " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")) + " ...]", }, { Grammar: []Element{AnyOne{String("str1"), String("str2")}}, @@ -77,7 +77,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{AnyOne{String("str1"), String("str2")}}, UsePalette: true, - Expect: "{" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + "|" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")) + "}", + Expect: "{" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + "|" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")) + "}", }, { Grammar: []Element{Parentheses{String("str1"), String("str2")}}, @@ -87,7 +87,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Parentheses{String("str1"), String("str2")}}, UsePalette: true, - Expect: "(" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")) + ")", + Expect: "(" + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")) + ")", }, { Grammar: []Element{PlainGroup{String("str1"), String("str2")}}, @@ -97,7 +97,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{PlainGroup{String("str1"), String("str2")}}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")), }, { Grammar: []Element{ConnectedGroup{String("str1"), String("str2")}}, @@ -107,7 +107,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{ConnectedGroup{String("str1"), String("str2")}}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str1")) + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str2")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str1")) + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str2")), }, { Grammar: []Element{Function{Name: "fn", Args: []Element{Option{Keyword("DISTINCT")}, String("str"), Option{String("arg1"), String("arg2")}}, AfterArgs: []Element{Keyword("OVER"), Parentheses{Link("partition_clause")}}, Return: Return(String("string"))}}, @@ -119,9 +119,9 @@ var grammarFormatTests = []struct { UsePalette: true, Expect: syntaxTestPalette.Render(KeywordEffect, "fn") + "([" + syntaxTestPalette.Render(KeywordEffect, "DISTINCT") + "] " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str")) + syntaxTestPalette.Render(TypeEffect, "::string") + " [, " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "arg1")) + syntaxTestPalette.Render(TypeEffect, "::string") + " [, " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "arg2")) + syntaxTestPalette.Render(TypeEffect, "::string") + "]]) " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str")) + syntaxTestPalette.Render(TypeEffect, "::string") + " [, " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "arg1")) + syntaxTestPalette.Render(TypeEffect, "::string") + " [, " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "arg2")) + syntaxTestPalette.Render(TypeEffect, "::string") + "]]) " + syntaxTestPalette.Render(KeywordEffect, "OVER") + " (" + syntaxTestPalette.Render(LinkEffect, "") + ") " + syntaxTestPalette.Render(TypeEffect, "return::string"), @@ -144,7 +144,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{ArgWithDefValue{Arg: String("str"), Default: String("1")}}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str")) + syntaxTestPalette.Render(TypeEffect, "::string") + " " + syntaxTestPalette.Render(KeywordEffect, "DEFAULT") + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "1")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str")) + syntaxTestPalette.Render(TypeEffect, "::string") + " " + syntaxTestPalette.Render(KeywordEffect, "DEFAULT") + " " + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "1")), }, { Grammar: []Element{String("str")}, @@ -154,7 +154,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{String("str")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str")), }, { Grammar: []Element{Integer("int")}, @@ -164,7 +164,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Integer("int")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.NumberEffect, "int")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.NumberEffect, "int")), }, { Grammar: []Element{Float("float")}, @@ -174,7 +174,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Float("float")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.NumberEffect, "float")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.NumberEffect, "float")), }, { Grammar: []Element{Identifier("ident")}, @@ -184,7 +184,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Identifier("ident")}, UsePalette: true, - Expect: syntaxTestPalette.Render(cmd.IdentifierEffect, "ident"), + Expect: syntaxTestPalette.Render(option.IdentifierEffect, "ident"), }, { Grammar: []Element{Datetime("dt")}, @@ -194,7 +194,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Datetime("dt")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.DatetimeEffect, "dt")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.DatetimeEffect, "dt")), }, { Grammar: []Element{Boolean("bool")}, @@ -204,7 +204,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Boolean("bool")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.BooleanEffect, "bool")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.BooleanEffect, "bool")), }, { Grammar: []Element{Ternary("ternary")}, @@ -214,7 +214,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Ternary("ternary")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.TernaryEffect, "ternary")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.TernaryEffect, "ternary")), }, { Grammar: []Element{Null("null")}, @@ -224,7 +224,7 @@ var grammarFormatTests = []struct { { Grammar: []Element{Null("null")}, UsePalette: true, - Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.NullEffect, "null")), + Expect: syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.NullEffect, "null")), }, { Grammar: []Element{Variable("@var")}, @@ -291,11 +291,11 @@ var grammarFormatTests = []struct { }}, UsePalette: true, Expect: "abc " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.StringEffect, "str")) + " " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.TernaryEffect, "TRUE")) + " " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.TernaryEffect, "ternary")) + " " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.NullEffect, "NULL")) + " " + - syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(cmd.NullEffect, "null")) + " " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.StringEffect, "str")) + " " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.TernaryEffect, "TRUE")) + " " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.TernaryEffect, "ternary")) + " " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.NullEffect, "NULL")) + " " + + syntaxTestPalette.Render(ItalicEffect, syntaxTestPalette.Render(option.NullEffect, "null")) + " " + syntaxTestPalette.Render(LinkEffect, ""), }, } diff --git a/lib/terminal/completer_readline.go b/lib/terminal/completer_readline.go index 18a007c..0700bda 100644 --- a/lib/terminal/completer_readline.go +++ b/lib/terminal/completer_readline.go @@ -11,7 +11,7 @@ import ( "strings" "unicode" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" @@ -180,13 +180,13 @@ func NewCompleter(scope *query.ReferenceScope) *Completer { tableColumns: make(map[string][]string), } - completer.flagList = make([]string, 0, len(cmd.FlagList)) - for _, v := range cmd.FlagList { - completer.flagList = append(completer.flagList, cmd.FlagSymbol(v)) + completer.flagList = make([]string, 0, len(option.FlagList)) + for _, v := range option.FlagList { + completer.flagList = append(completer.flagList, option.FlagSymbol(v)) } completer.runinfoList = make([]string, 0, len(query.RuntimeInformatinList)) for _, v := range query.RuntimeInformatinList { - completer.runinfoList = append(completer.runinfoList, cmd.RuntimeInformationSymbol(v)) + completer.runinfoList = append(completer.runinfoList, option.RuntimeInformationSymbol(v)) } sort.Strings(completer.flagList) @@ -329,7 +329,7 @@ func (c *Completer) updateVariables() { c.varList = make([]string, 0, len(varKeys)) for _, k := range varKeys { - c.varList = append(c.varList, cmd.VariableSymbol(k)) + c.varList = append(c.varList, option.VariableSymbol(k)) } } @@ -339,8 +339,8 @@ func (c *Completer) updateEnvironmentVariables() { c.enclosedEnvList = make([]string, 0, len(env)) for _, e := range env { words := strings.Split(e, "=") - c.envList = append(c.envList, cmd.EnvironmentVariableSymbol(words[0])) - c.enclosedEnvList = append(c.enclosedEnvList, cmd.EnclosedEnvironmentVariableSymbol(words[0])) + c.envList = append(c.envList, option.EnvironmentVariableSymbol(words[0])) + c.enclosedEnvList = append(c.enclosedEnvList, option.EnclosedEnvironmentVariableSymbol(words[0])) } sort.Strings(c.envList) sort.Strings(c.enclosedEnvList) @@ -501,9 +501,9 @@ func (c *Completer) TableObjectArgs(line string, origLine string, index int) rea case 0: if c.tokens[c.lastIdx].Token == '(' { switch strings.ToUpper(c.tokens[0].Literal) { - case cmd.CSV.String(): + case option.CSV.String(): cands = c.candidateList(delimiterCandidates, false) - case cmd.FIXED.String(): + case option.FIXED.String(): cands = c.candidateList(delimiterPositionsCandidates, false) } } @@ -514,14 +514,14 @@ func (c *Completer) TableObjectArgs(line string, origLine string, index int) rea case 2: if c.tokens[c.lastIdx].Token == ',' { switch strings.ToUpper(c.tokens[0].Literal) { - case cmd.CSV.String(), cmd.FIXED.String(): + case option.CSV.String(), option.FIXED.String(): cands = c.candidateList(c.encodingList(), false) } } case 3, 4: if c.tokens[c.lastIdx].Token == ',' { switch strings.ToUpper(c.tokens[0].Literal) { - case cmd.CSV.String(), cmd.FIXED.String(): + case option.CSV.String(), option.FIXED.String(): cands = c.candidateList([]string{ternary.TRUE.String(), ternary.FALSE.String()}, false) } } @@ -1902,32 +1902,32 @@ func (c *Completer) SetArgs(line string, origLine string, index int) readline.Ca case parser.TO: if i == c.lastIdx && c.tokens[c.lastIdx-1].Token == parser.FLAG { switch strings.ToUpper(c.tokens[c.lastIdx-1].Literal) { - case cmd.RepositoryFlag: + case option.RepositoryFlag: return nil, c.SearchDirs(line, origLine, index), true - case cmd.TimezoneFlag: + case option.TimezoneFlag: return nil, c.candidateList([]string{"Local", "UTC"}, false), true - case cmd.ImportFormatFlag: + case option.ImportFormatFlag: return nil, c.candidateList(c.importFormatList(), false), true - case cmd.DelimiterFlag, cmd.ExportDelimiterFlag: + case option.DelimiterFlag, option.ExportDelimiterFlag: return nil, c.candidateList(delimiterCandidates, false), true - case cmd.DelimiterPositionsFlag, cmd.ExportDelimiterPositionsFlag: + case option.DelimiterPositionsFlag, option.ExportDelimiterPositionsFlag: return nil, c.candidateList(delimiterPositionsCandidates, false), true - case cmd.EncodingFlag: + case option.EncodingFlag: return nil, c.candidateList(c.encodingList(), false), true - case cmd.ExportEncodingFlag: + case option.ExportEncodingFlag: return nil, c.candidateList(exportEncodingsCandidates, false), true - case cmd.AnsiQuotesFlag, cmd.StrictEqualFlag, cmd.AllowUnevenFieldsFlag, - cmd.NoHeaderFlag, cmd.WithoutNullFlag, - cmd.WithoutHeaderFlag, cmd.EncloseAllFlag, cmd.PrettyPrintFlag, - cmd.StripEndingLineBreakFlag, cmd.EastAsianEncodingFlag, - cmd.CountDiacriticalSignFlag, cmd.CountFormatCodeFlag, - cmd.ColorFlag, cmd.QuietFlag, cmd.StatsFlag: + case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, + option.NoHeaderFlag, option.WithoutNullFlag, + option.WithoutHeaderFlag, option.EncloseAllFlag, option.PrettyPrintFlag, + option.StripEndingLineBreakFlag, option.EastAsianEncodingFlag, + option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, + option.ColorFlag, option.QuietFlag, option.StatsFlag: return nil, c.candidateList([]string{ternary.TRUE.String(), ternary.FALSE.String()}, false), true - case cmd.FormatFlag: + case option.FormatFlag: return nil, c.candidateList(c.tableFormatList(), false), true - case cmd.LineBreakFlag: + case option.LineBreakFlag: return nil, c.candidateList(c.lineBreakList(), false), true - case cmd.JsonEscapeFlag: + case option.JsonEscapeFlag: return nil, c.candidateList(c.jsonEscapeTypeList(), false), true } } @@ -1984,7 +1984,7 @@ func (c *Completer) AddFlagArgs(line string, origLine string, index int) readlin func(i int) (keywords []string, customList readline.CandidateList, breakLoop bool) { switch c.tokens[i].Token { case parser.TO: - return nil, c.candidateList([]string{cmd.FlagSymbol(cmd.DatetimeFormatFlag)}, false), true + return nil, c.candidateList([]string{option.FlagSymbol(option.DatetimeFormatFlag)}, false), true case parser.ADD: if i < c.lastIdx { keywords = append(keywords, "TO") @@ -2004,7 +2004,7 @@ func (c *Completer) RemoveFlagArgs(line string, origLine string, index int) read func(i int) (keywords []string, customList readline.CandidateList, breakLoop bool) { switch c.tokens[i].Token { case parser.FROM: - return nil, c.candidateList([]string{cmd.FlagSymbol(cmd.DatetimeFormatFlag)}, false), true + return nil, c.candidateList([]string{option.FlagSymbol(option.DatetimeFormatFlag)}, false), true case parser.REMOVE: if i < c.lastIdx { keywords = append(keywords, "FROM") @@ -2119,7 +2119,7 @@ func (c *Completer) SearchAllTablesWithSpace(line string, origLine string, index func (c *Completer) SearchAllTables(line string, _ string, _ int) readline.CandidateList { tableKeys := c.scope.Tx.CachedViews.SortedKeys() - files := c.ListFiles(line, []string{cmd.CsvExt, cmd.TsvExt, cmd.JsonExt, cmd.JsonlExt, cmd.LtsvExt, cmd.TextExt}, c.scope.Tx.Flags.Repository) + files := c.ListFiles(line, []string{option.CsvExt, option.TsvExt, option.JsonExt, option.JsonlExt, option.LtsvExt, option.TextExt}, c.scope.Tx.Flags.Repository) defaultDir := c.scope.Tx.Flags.Repository if len(defaultDir) < 1 { @@ -2165,7 +2165,7 @@ func (c *Completer) SearchAllTables(line string, _ string, _ int) readline.Candi func (c *Completer) SearchExecutableFiles(line string, origLine string, index int) readline.CandidateList { cands := c.SearchValues(line, origLine, index) - files := c.ListFiles(line, []string{cmd.SqlExt, cmd.CsvqProcExt}, "") + files := c.ListFiles(line, []string{option.SqlExt, option.CsvqProcExt}, "") return append(cands, c.identifierList(files, false)...) } @@ -2861,15 +2861,15 @@ func (c *Completer) analyticFunctionCandidateList(line string) readline.Candidat } func (c *Completer) environmentVariableList(line string) []string { - if 2 < len(line) && strings.HasPrefix(line, cmd.EnvironmentVariableSign+"`") { + if 2 < len(line) && strings.HasPrefix(line, option.EnvironmentVariableSign+"`") { return c.enclosedEnvList } return c.envList } func (c *Completer) tableFormatList() []string { - list := make([]string, 0, len(cmd.FormatLiteral)) - for _, v := range cmd.FormatLiteral { + list := make([]string, 0, len(option.FormatLiteral)) + for _, v := range option.FormatLiteral { list = append(list, v) } sort.Strings(list) @@ -2877,9 +2877,9 @@ func (c *Completer) tableFormatList() []string { } func (c *Completer) importFormatList() []string { - list := make([]string, 0, len(cmd.ImportFormats)) - for _, v := range cmd.ImportFormats { - list = append(list, cmd.FormatLiteral[v]) + list := make([]string, 0, len(option.ImportFormats)) + for _, v := range option.ImportFormats { + list = append(list, option.FormatLiteral[v]) } sort.Strings(list) return list @@ -2904,8 +2904,8 @@ func (c *Completer) lineBreakList() []string { } func (c *Completer) jsonEscapeTypeList() []string { - list := make([]string, 0, len(cmd.JsonEscapeTypeLiteral)) - for _, v := range cmd.JsonEscapeTypeLiteral { + list := make([]string, 0, len(option.JsonEscapeTypeLiteral)) + for _, v := range option.JsonEscapeTypeLiteral { list = append(list, v) } sort.Strings(list) diff --git a/lib/terminal/completer_readline_test.go b/lib/terminal/completer_readline_test.go index 633b384..2efafd1 100644 --- a/lib/terminal/completer_readline_test.go +++ b/lib/terminal/completer_readline_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/value" @@ -130,10 +130,10 @@ func TestCompleter_Update(t *testing.T) { }) c := NewCompleter(scope) - if len(c.flagList) != len(cmd.FlagList) || !strings.HasPrefix(c.flagList[0], cmd.FlagSign) { + if len(c.flagList) != len(option.FlagList) || !strings.HasPrefix(c.flagList[0], option.FlagSign) { t.Error("flags are not set correctly") } - if len(c.runinfoList) != len(query.RuntimeInformatinList) || !strings.HasPrefix(c.runinfoList[0], cmd.RuntimeInformationSign) { + if len(c.runinfoList) != len(query.RuntimeInformatinList) || !strings.HasPrefix(c.runinfoList[0], option.RuntimeInformationSign) { t.Error("runtime information are not set correctly") } if len(c.funcs) != len(query.Functions)+3 { @@ -171,7 +171,7 @@ func TestCompleter_Update(t *testing.T) { if !reflect.DeepEqual(c.varList, []string{"@var"}) { t.Error("variables are not set correctly") } - if !strings.HasPrefix(c.envList[0], cmd.EnvironmentVariableSign) || !strings.HasPrefix(c.enclosedEnvList[0], cmd.EnvironmentVariableSign+"`") { + if !strings.HasPrefix(c.envList[0], option.EnvironmentVariableSign) || !strings.HasPrefix(c.enclosedEnvList[0], option.EnvironmentVariableSign+"`") { t.Error("environment variables are not set correctly") } @@ -4162,7 +4162,7 @@ func TestCompleter_ColumnList(t *testing.T) { }, ) - TestTx.Flags.ExportOptions.Format = cmd.CSV + TestTx.Flags.ExportOptions.Format = option.CSV _ = os.Chdir(CompletionTestDir) completer := NewCompleter(scope) diff --git a/lib/terminal/main_test.go b/lib/terminal/main_test.go index 383c0cf..7d4b8db 100644 --- a/lib/terminal/main_test.go +++ b/lib/terminal/main_test.go @@ -8,8 +8,8 @@ import ( "runtime" "testing" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/file" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/query" "github.com/mitchellh/go-homedir" @@ -40,7 +40,7 @@ func run(m *testing.M) int { return m.Run() } -func initFlag(flags *cmd.Flags) { +func initFlag(flags *option.Flags) { cpu := runtime.NumCPU() / 2 if cpu < 1 { cpu = 1 @@ -51,8 +51,8 @@ func initFlag(flags *cmd.Flags) { flags.AnsiQuotes = false flags.StrictEqual = false flags.WaitTimeout = 15 - flags.ImportOptions = cmd.NewImportOptions() - flags.ExportOptions = cmd.NewExportOptions() + flags.ImportOptions = option.NewImportOptions() + flags.ExportOptions = option.NewExportOptions() flags.Quiet = false flags.LimitRecursion = 5 flags.CPU = cpu diff --git a/lib/terminal/terminal.go b/lib/terminal/terminal.go index 61cb4f2..056556b 100644 --- a/lib/terminal/terminal.go +++ b/lib/terminal/terminal.go @@ -7,8 +7,8 @@ import ( "strings" "unicode" - "github.com/mithrandie/csvq/lib/cmd" "github.com/mithrandie/csvq/lib/excmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/parser" "github.com/mithrandie/csvq/lib/query" "github.com/mithrandie/csvq/lib/value" @@ -93,7 +93,7 @@ func (p *Prompt) RenderPrompt(ctx context.Context) (string, error) { } if p.scope.Tx.Flags.ExportOptions.Color { if strings.IndexByte(s, 0x1b) < 0 { - s = p.scope.Tx.Palette.Render(cmd.PromptEffect, s) + s = p.scope.Tx.Palette.Render(option.PromptEffect, s) } } else { s = p.StripEscapeSequence(s) @@ -108,7 +108,7 @@ func (p *Prompt) RenderContinuousPrompt(ctx context.Context) (string, error) { } if p.scope.Tx.Flags.ExportOptions.Color { if strings.IndexByte(s, 0x1b) < 0 { - s = p.scope.Tx.Palette.Render(cmd.PromptEffect, s) + s = p.scope.Tx.Palette.Render(option.PromptEffect, s) } } else { s = p.StripEscapeSequence(s) diff --git a/lib/terminal/terminal_general.go b/lib/terminal/terminal_general.go index 1004e47..be7ef93 100644 --- a/lib/terminal/terminal_general.go +++ b/lib/terminal/terminal_general.go @@ -6,7 +6,7 @@ import ( "context" "io" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/query" "golang.org/x/crypto/ssh/terminal" @@ -39,7 +39,7 @@ func NewTerminal(ctx context.Context, scope *query.ReferenceScope) (query.Virtua } t := SSHTerminal{ - terminal: terminal.NewTerminal(NewStdIO(scope.Tx.Session), scope.Tx.Palette.Render(cmd.PromptEffect, DefaultPrompt)), + terminal: terminal.NewTerminal(NewStdIO(scope.Tx.Session), scope.Tx.Palette.Render(option.PromptEffect, DefaultPrompt)), stdin: stdin, origState: origState, rawState: rawState, diff --git a/lib/terminal/terminal_readline.go b/lib/terminal/terminal_readline.go index 7d923bd..0041433 100644 --- a/lib/terminal/terminal_readline.go +++ b/lib/terminal/terminal_readline.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/csvq/lib/query" "github.com/mitchellh/go-homedir" @@ -19,7 +19,7 @@ type ReadLineTerminal struct { terminal *readline.Instance fd int prompt *Prompt - env *cmd.Environment + env *option.Environment completer *Completer tx *query.Transaction } diff --git a/lib/value/comparison.go b/lib/value/comparison.go index d48a69f..57c0f12 100644 --- a/lib/value/comparison.go +++ b/lib/value/comparison.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/ternary" ) @@ -116,8 +116,8 @@ func CompareCombinedly(p1 Primary, p2 Primary, datetimeFormats []string, locatio if s1, ok := p1.(*String); ok { if s2, ok := p2.(*String); ok { - v1 := strings.ToUpper(cmd.TrimSpace(s1.Raw())) - v2 := strings.ToUpper(cmd.TrimSpace(s2.Raw())) + v1 := strings.ToUpper(option.TrimSpace(s1.Raw())) + v2 := strings.ToUpper(option.TrimSpace(s2.Raw())) if v1 == v2 { return IsEqual diff --git a/lib/value/conv.go b/lib/value/conv.go index 8a3ebb0..b3a312b 100644 --- a/lib/value/conv.go +++ b/lib/value/conv.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/ternary" ) @@ -57,7 +57,7 @@ func (dfmap DatetimeFormatMap) Get(s string) string { } func StrToTime(s string, formats []string, location *time.Location) (time.Time, bool) { - s = cmd.TrimSpace(s) + s = option.TrimSpace(s) for _, format := range formats { if t, e := time.ParseInLocation(DatetimeFormats.Get(format), s, location); e == nil { @@ -263,7 +263,7 @@ func ToInteger(p Primary) Primary { } return NewInteger(int64(val.Raw())) case *String: - s := cmd.TrimSpace(val.Raw()) + s := option.TrimSpace(val.Raw()) if i, e := strconv.ParseInt(s, 10, 64); e == nil { return NewInteger(i) } @@ -280,7 +280,7 @@ func ToIntegerStrictly(p Primary) Primary { case *Integer: return NewInteger(p.(*Integer).Raw()) case *String: - s := cmd.TrimSpace(p.(*String).Raw()) + s := option.TrimSpace(p.(*String).Raw()) if i, e := strconv.ParseInt(s, 10, 64); e == nil { return NewInteger(i) } @@ -296,7 +296,7 @@ func ToFloat(p Primary) Primary { case *Float: return NewFloat(p.(*Float).Raw()) case *String: - s := cmd.TrimSpace(p.(*String).Raw()) + s := option.TrimSpace(p.(*String).Raw()) if f, e := strconv.ParseFloat(s, 64); e == nil { return NewFloat(f) } diff --git a/lib/value/conv_test.go b/lib/value/conv_test.go index 1421acf..88973fc 100644 --- a/lib/value/conv_test.go +++ b/lib/value/conv_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/ternary" ) @@ -562,7 +562,7 @@ func TestToString(t *testing.T) { var p Primary var s Primary - location, _ := cmd.GetLocation("UTC") + location, _ := option.GetLocation("UTC") p = NewString("str") s = ToString(p) @@ -641,7 +641,7 @@ func BenchmarkStrToTime5(b *testing.B) { func BenchmarkStrToTime6(b *testing.B) { formats := []string{"01/02/2006"} - location, _ := cmd.GetLocation("UTC") + location, _ := option.GetLocation("UTC") for i := 0; i < b.N; i++ { s := "02 Jan 06 15:04 PDT" @@ -651,7 +651,7 @@ func BenchmarkStrToTime6(b *testing.B) { func BenchmarkStrToTime7(b *testing.B) { formats := []string{"01/02/2006"} - location, _ := cmd.GetLocation("UTC") + location, _ := option.GetLocation("UTC") for i := 0; i < b.N; i++ { s := "abcdefghijklmnopq" diff --git a/lib/value/type.go b/lib/value/type.go index 701ca47..eaaa7f3 100644 --- a/lib/value/type.go +++ b/lib/value/type.go @@ -4,7 +4,7 @@ import ( "strconv" "time" - "github.com/mithrandie/csvq/lib/cmd" + "github.com/mithrandie/csvq/lib/option" "github.com/mithrandie/ternary" ) @@ -44,7 +44,7 @@ type String struct { } func (s String) String() string { - return cmd.QuoteString(s.literal) + return option.QuoteString(s.literal) } func NewString(s string) *String { @@ -58,7 +58,7 @@ func (s String) Raw() string { } func (s String) Ternary() ternary.Value { - lit := cmd.TrimSpace(s.Raw()) + lit := option.TrimSpace(s.Raw()) if b, err := strconv.ParseBool(lit); err == nil { return ternary.ConvertFromBool(b) } @@ -202,7 +202,7 @@ func NewDatetime(t time.Time) *Datetime { } func (dt Datetime) String() string { - return cmd.QuoteString(dt.value.Format(time.RFC3339Nano)) + return option.QuoteString(dt.value.Format(time.RFC3339Nano)) } func (dt Datetime) Raw() time.Time { From b81d3135003b1484ceaedcbbdac50cbca1fbadbd Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Mon, 4 Jul 2022 04:37:33 +0900 Subject: [PATCH 15/17] Add the command option --scientific-notation. --- docs/_posts/2006-01-02-command.md | 3 ++ docs/sitemap.xml | 2 +- lib/action/calc.go | 2 +- lib/cli/app.go | 8 +++++ lib/option/flags.go | 8 +++++ lib/option/flags_test.go | 9 ++++++ lib/query/built_in_command.go | 8 ++--- lib/query/built_in_command_test.go | 21 +++++++++++++ lib/query/encode.go | 40 ++++++++++++++---------- lib/query/encode_test.go | 49 +++++++++++++++++++++++++++++- lib/query/function.go | 14 ++++++++- lib/query/function_test.go | 41 ++++++++++++++++++++++--- lib/query/sort_value.go | 2 +- lib/query/transaction.go | 8 +++++ lib/terminal/completer_readline.go | 1 + lib/value/conv.go | 9 ++++-- lib/value/conv_test.go | 16 ++++++++++ lib/value/type.go | 2 +- 18 files changed, 209 insertions(+), 34 deletions(-) diff --git a/docs/_posts/2006-01-02-command.md b/docs/_posts/2006-01-02-command.md index f8a35cf..8681bb7 100644 --- a/docs/_posts/2006-01-02-command.md +++ b/docs/_posts/2006-01-02-command.md @@ -259,6 +259,9 @@ When this option is not specified, the file specified by the _--out_ option will --pretty-print, -P : Make JSON output easier to read in query results. +--scientific-notation -SN +: Use Scientific Notation for large exponents in output. + --east-asian-encoding, -W : Count ambiguous characters as fullwidth. If not, then that characters are counted as halfwidth. diff --git a/docs/sitemap.xml b/docs/sitemap.xml index f3dd1c0..7c33aad 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -18,7 +18,7 @@
    https://mithrandie.github.io/csvq/reference/command.html - 2022-06-18T12:43:41+00:00 + 2022-07-03T19:08:14+00:00 https://mithrandie.github.io/csvq/reference/statement.html diff --git a/lib/action/calc.go b/lib/action/calc.go index b4ce615..5ae2119 100644 --- a/lib/action/calc.go +++ b/lib/action/calc.go @@ -49,7 +49,7 @@ func Calc(ctx context.Context, proc *query.Processor, expr string) error { } return err } - values[i], _, _ = query.ConvertFieldContents(p, true) + values[i], _, _ = query.ConvertFieldContents(p, true, proc.Tx.Flags.ExportOptions.ScientificNotation) } return proc.Tx.Session.WriteToStdout(strings.Join(values, string(proc.Tx.Flags.ExportOptions.Delimiter))) diff --git a/lib/cli/app.go b/lib/cli/app.go index 7d233f2..00ed2d0 100644 --- a/lib/cli/app.go +++ b/lib/cli/app.go @@ -171,6 +171,11 @@ func Run() { Aliases: []string{"P"}, Usage: "make JSON output easier to read in query results", }, + &cli.BoolFlag{ + Name: "scientific-notation", + Aliases: []string{"SN"}, + Usage: "use scientific notation for large exponents in output", + }, &cli.BoolFlag{ Name: "east-asian-encoding", Aliases: []string{"W"}, @@ -472,6 +477,9 @@ func overwriteFlags(c *cli.Context, tx *query.Transaction) error { if c.IsSet("pretty-print") { _ = tx.SetFlag(option.PrettyPrintFlag, c.Bool("pretty-print")) } + if c.IsSet("scientific-notation") { + _ = tx.SetFlag(option.ScientificNotationFlag, c.Bool("scientific-notation")) + } if c.IsSet("east-asian-encoding") { _ = tx.SetFlag(option.EastAsianEncodingFlag, c.Bool("east-asian-encoding")) diff --git a/lib/option/flags.go b/lib/option/flags.go index 472f89e..0d74df9 100644 --- a/lib/option/flags.go +++ b/lib/option/flags.go @@ -47,6 +47,7 @@ const ( EncloseAllFlag = "ENCLOSE_ALL" JsonEscapeFlag = "JSON_ESCAPE" PrettyPrintFlag = "PRETTY_PRINT" + ScientificNotationFlag = "SCIENTIFIC_NOTATION" EastAsianEncodingFlag = "EAST_ASIAN_ENCODING" CountDiacriticalSignFlag = "COUNT_DIACRITICAL_SIGN" CountFormatCodeFlag = "COUNT_FORMAT_CODE" @@ -82,6 +83,7 @@ var FlagList = []string{ EncloseAllFlag, JsonEscapeFlag, PrettyPrintFlag, + ScientificNotationFlag, EastAsianEncodingFlag, CountDiacriticalSignFlag, CountFormatCodeFlag, @@ -207,6 +209,7 @@ type ExportOptions struct { EncloseAll bool JsonEscape txjson.EscapeType PrettyPrint bool + ScientificNotation bool // For Calculation of String Width EastAsianEncoding bool @@ -241,6 +244,7 @@ func NewExportOptions() ExportOptions { EncloseAll: false, JsonEscape: txjson.Backslash, PrettyPrint: false, + ScientificNotation: false, EastAsianEncoding: false, CountDiacriticalSign: false, CountFormatCode: false, @@ -592,6 +596,10 @@ func (f *Flags) SetPrettyPrint(b bool) { f.ExportOptions.PrettyPrint = b } +func (f *Flags) SetScientificNotation(b bool) { + f.ExportOptions.ScientificNotation = b +} + func (f *Flags) SetStripEndingLineBreak(b bool) { f.ExportOptions.StripEndingLineBreak = b } diff --git a/lib/option/flags_test.go b/lib/option/flags_test.go index 998fa7d..6426215 100644 --- a/lib/option/flags_test.go +++ b/lib/option/flags_test.go @@ -619,6 +619,15 @@ func TestFlags_SetPrettyPrint(t *testing.T) { } } +func TestFlags_SetScientificNotation(t *testing.T) { + flags, _ := NewFlags(nil) + + flags.SetScientificNotation(true) + if !flags.ExportOptions.ScientificNotation { + t.Errorf("scientific-notation = %t, expect to set %t", flags.ExportOptions.ScientificNotation, true) + } +} + func TestFlags_SetStripEndingLineBreak(t *testing.T) { flags, _ := NewFlags(nil) diff --git a/lib/query/built_in_command.go b/lib/query/built_in_command.go index 73f5e4e..6e6f629 100644 --- a/lib/query/built_in_command.go +++ b/lib/query/built_in_command.go @@ -225,7 +225,7 @@ func SetFlag(ctx context.Context, scope *ReferenceScope, expr parser.SetFlag) er val = p.(*value.String).Raw() case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, option.EncloseAllFlag, - option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.PrettyPrintFlag, option.ScientificNotationFlag, option.StripEndingLineBreakFlag, option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, option.QuietFlag, option.StatsFlag: p = value.ToBoolean(v) @@ -271,7 +271,7 @@ func AddFlagElement(ctx context.Context, scope *ReferenceScope, expr parser.AddF option.JsonQueryFlag, option.EncodingFlag, option.ExportEncodingFlag, option.FormatFlag, option.ExportDelimiterFlag, option.ExportDelimiterPositionsFlag, option.LineBreakFlag, option.JsonEscapeFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, - option.EncloseAllFlag, option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.EncloseAllFlag, option.PrettyPrintFlag, option.ScientificNotationFlag, option.StripEndingLineBreakFlag, option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, option.QuietFlag, option.StatsFlag, option.WaitTimeoutFlag, @@ -320,7 +320,7 @@ func RemoveFlagElement(ctx context.Context, scope *ReferenceScope, expr parser.R option.JsonQueryFlag, option.EncodingFlag, option.ExportEncodingFlag, option.FormatFlag, option.ExportDelimiterFlag, option.ExportDelimiterPositionsFlag, option.LineBreakFlag, option.JsonEscapeFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, - option.EncloseAllFlag, option.PrettyPrintFlag, option.StripEndingLineBreakFlag, + option.EncloseAllFlag, option.PrettyPrintFlag, option.ScientificNotationFlag, option.StripEndingLineBreakFlag, option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, option.QuietFlag, option.StatsFlag, option.WaitTimeoutFlag, @@ -456,7 +456,7 @@ func showFlag(tx *Transaction, flagName string) (string, bool) { case option.WaitTimeoutFlag: s = tx.Palette.Render(option.NumberEffect, val.(*value.Float).String()) case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, - option.NoHeaderFlag, option.WithoutNullFlag, option.StripEndingLineBreakFlag, + option.NoHeaderFlag, option.WithoutNullFlag, option.StripEndingLineBreakFlag, option.ScientificNotationFlag, option.ColorFlag, option.QuietFlag, option.StatsFlag: s = tx.Palette.Render(option.BooleanEffect, val.(*value.Boolean).String()) } diff --git a/lib/query/built_in_command_test.go b/lib/query/built_in_command_test.go index 9323f53..e793775 100644 --- a/lib/query/built_in_command_test.go +++ b/lib/query/built_in_command_test.go @@ -521,6 +521,13 @@ var setFlagTests = []struct { Value: parser.NewTernaryValueFromString("true"), }, }, + { + Name: "Set Scientific Notation", + Expr: parser.SetFlag{ + Flag: parser.Flag{Name: "scientific_notation"}, + Value: parser.NewTernaryValueFromString("true"), + }, + }, { Name: "Set Strip Ending Line Break", Expr: parser.SetFlag{ @@ -1391,6 +1398,19 @@ var showFlagTests = []struct { }, Result: "\033[34;1m@@PRETTY_PRINT:\033[0m \033[33;1mtrue\033[0m", }, + { + Name: "Show Scientific Notation", + Expr: parser.ShowFlag{ + Flag: parser.Flag{Name: "scientific_notation"}, + }, + SetExprs: []parser.SetFlag{ + { + Flag: parser.Flag{Name: "scientific_notation"}, + Value: parser.NewTernaryValueFromString("true"), + }, + }, + Result: "\033[34;1m@@SCIENTIFIC_NOTATION:\033[0m \033[33;1mtrue\033[0m", + }, { Name: "Show StripEndingLineBreak", Expr: parser.ShowFlag{ @@ -2269,6 +2289,7 @@ var showObjectsTests = []struct { " @@ENCLOSE_ALL: false\n" + " @@JSON_ESCAPE: (ignored) BACKSLASH\n" + " @@PRETTY_PRINT: (ignored) false\n" + + " @@SCIENTIFIC_NOTATION: false\n" + " @@EAST_ASIAN_ENCODING: (ignored) false\n" + " @@COUNT_DIACRITICAL_SIGN: (ignored) false\n" + " @@COUNT_FORMAT_CODE: (ignored) false\n" + diff --git a/lib/query/encode.go b/lib/query/encode.go index 10e2ed5..268074a 100644 --- a/lib/query/encode.go +++ b/lib/query/encode.go @@ -74,7 +74,7 @@ func encodeCSV(ctx context.Context, fp io.Writer, view *View, options option.Exp } for j := range view.RecordSet[i] { - str, effect, _ := ConvertFieldContents(view.RecordSet[i][j][0], false) + str, effect, _ := ConvertFieldContents(view.RecordSet[i][j][0], false, options.ScientificNotation) quote := false if options.EncloseAll && (effect == option.StringEffect || effect == option.DatetimeEffect) { quote = true @@ -124,7 +124,7 @@ func encodeFixedLengthFormat(ctx context.Context, fp io.Writer, view *View, opti fields := make([]fixedlen.Field, fieldLen) for j := range view.RecordSet[i] { - str, _, a := ConvertFieldContents(view.RecordSet[i][j][0], false) + str, _, a := ConvertFieldContents(view.RecordSet[i][j][0], false, options.ScientificNotation) fields[j] = fixedlen.NewField(str, a) } fieldList[i+recordStartPos] = fields @@ -178,7 +178,7 @@ func encodeFixedLengthFormat(ctx context.Context, fp io.Writer, view *View, opti } for j := range view.RecordSet[i] { - str, _, a := ConvertFieldContents(view.RecordSet[i][j][0], false) + str, _, a := ConvertFieldContents(view.RecordSet[i][j][0], false, options.ScientificNotation) fields[j] = fixedlen.NewField(str, a) } if err := w.Write(fields); err != nil { @@ -219,6 +219,7 @@ func encodeJson(ctx context.Context, fp io.Writer, view *View, options option.Ex e.EscapeType = options.JsonEscape e.LineBreak = options.LineBreak e.PrettyPrint = options.PrettyPrint + e.FloatFormat = jsonFloatFormat(options.ScientificNotation) if options.PrettyPrint && options.Color { e.Palette = palette } @@ -256,6 +257,7 @@ func encodeJsonLines(ctx context.Context, fp io.Writer, view *View, options opti e.EscapeType = options.JsonEscape e.LineBreak = options.LineBreak e.PrettyPrint = options.PrettyPrint + e.FloatFormat = jsonFloatFormat(options.ScientificNotation) if options.PrettyPrint && options.Color { e.Palette = palette } @@ -355,7 +357,7 @@ func encodeText(ctx context.Context, fp io.Writer, view *View, options option.Ex rfields := make([]table.Field, fieldLen) for j := range view.RecordSet[i] { - str, effect, align := ConvertFieldContents(view.RecordSet[i][j][0], isPlainTable) + str, effect, align := ConvertFieldContents(view.RecordSet[i][j][0], isPlainTable, options.ScientificNotation) if options.Format == option.TEXT || options.Format == option.BOX { textStrBuf.Reset() textLineBuf.Reset() @@ -440,7 +442,7 @@ func encodeLTSV(ctx context.Context, fp io.Writer, view *View, options option.Ex } for j := range view.RecordSet[i] { - fields[j], _, _ = ConvertFieldContents(view.RecordSet[i][j][0], false) + fields[j], _, _ = ConvertFieldContents(view.RecordSet[i][j][0], false, options.ScientificNotation) } if err := w.Write(fields); err != nil { return NewDataEncodingError(err.Error()) @@ -452,40 +454,46 @@ func encodeLTSV(ctx context.Context, fp io.Writer, view *View, options option.Ex return nil } -func ConvertFieldContents(val value.Primary, forTextTable bool) (string, string, text.FieldAlignment) { +func jsonFloatFormat(useScientificNotation bool) txjson.FloatFormat { + if useScientificNotation { + return txjson.ENotationForLargeExponents + } + return txjson.NoExponent +} + +func ConvertFieldContents(val value.Primary, forTextTable bool, useScientificNotation bool) (string, string, text.FieldAlignment) { var s string var effect = option.NoEffect var align = text.NotAligned - switch val.(type) { + switch v := val.(type) { case *value.String: - s = val.(*value.String).Raw() + s = v.Raw() effect = option.StringEffect case *value.Integer: - s = val.(*value.Integer).String() + s = v.String() effect = option.NumberEffect align = text.RightAligned case *value.Float: - s = val.(*value.Float).String() + s = value.Float64ToStr(v.Raw(), useScientificNotation) effect = option.NumberEffect align = text.RightAligned case *value.Boolean: - s = val.(*value.Boolean).String() + s = v.String() effect = option.BooleanEffect align = text.Centering case *value.Ternary: - t := val.(*value.Ternary) if forTextTable { - s = t.Ternary().String() + s = v.Ternary().String() effect = option.TernaryEffect align = text.Centering - } else if t.Ternary() != ternary.UNKNOWN { - s = strconv.FormatBool(t.Ternary().ParseBool()) + } else if v.Ternary() != ternary.UNKNOWN { + s = strconv.FormatBool(v.Ternary().ParseBool()) effect = option.BooleanEffect align = text.Centering } case *value.Datetime: - s = val.(*value.Datetime).Format(time.RFC3339Nano) + s = v.Format(time.RFC3339Nano) effect = option.DatetimeEffect case *value.Null: if forTextTable { diff --git a/lib/query/encode_test.go b/lib/query/encode_test.go index bd96250..d2e757c 100644 --- a/lib/query/encode_test.go +++ b/lib/query/encode_test.go @@ -10,7 +10,6 @@ import ( "github.com/mithrandie/go-text" "github.com/mithrandie/go-text/json" - "github.com/mithrandie/ternary" ) @@ -27,6 +26,7 @@ var encodeViewTests = []struct { EncloseAll bool JsonEscape json.EscapeType PrettyPrint bool + ScientificNotation bool UseColor bool Result string Error string @@ -116,6 +116,22 @@ var encodeViewTests = []struct { "| | \033[32mghijkl\033[0m |\n" + "+--------+--------+", }, + { + Name: "Text using Scientific Notation", + View: &View{ + Header: NewHeader("test", []string{"c1"}), + RecordSet: []Record{ + NewRecord([]value.Primary{value.NewFloat(0.00000123)}), + }, + }, + Format: option.TEXT, + ScientificNotation: true, + Result: "+----------+\n" + + "| c1 |\n" + + "+----------+\n" + + "| 1.23e-06 |\n" + + "+----------+", + }, { Name: "Box", View: &View{ @@ -477,6 +493,22 @@ var encodeViewTests = []struct { " }\n" + "]", }, + { + Name: "JSON using Scientific Notation", + View: &View{ + Header: NewHeader("test", []string{"c1"}), + RecordSet: []Record{ + NewRecord([]value.Primary{value.NewFloat(0.00000123)}), + }, + }, + Format: option.JSON, + ScientificNotation: true, + Result: "[" + + "{" + + "\"c1\":1.23e-06" + + "}" + + "]", + }, { Name: "JSONL", View: &View{ @@ -510,6 +542,20 @@ var encodeViewTests = []struct { "\"c3\":null" + "}\n", }, + { + Name: "JSONL using Scientific Notation", + View: &View{ + Header: NewHeader("test", []string{"c1"}), + RecordSet: []Record{ + NewRecord([]value.Primary{value.NewFloat(0.00000123)}), + }, + }, + Format: option.JSONL, + ScientificNotation: true, + Result: "{" + + "\"c1\":1.23e-06" + + "}\n", + }, { Name: "LTSV", View: &View{ @@ -633,6 +679,7 @@ func TestEncodeView(t *testing.T) { options.EncloseAll = v.EncloseAll options.JsonEscape = v.JsonEscape options.PrettyPrint = v.PrettyPrint + options.ScientificNotation = v.ScientificNotation options.SingleLine = v.WriteAsSingleLine buf.Reset() diff --git a/lib/query/function.go b/lib/query/function.go index 016c192..fe47dd9 100644 --- a/lib/query/function.go +++ b/lib/query/function.go @@ -30,6 +30,7 @@ import ( "github.com/mithrandie/csvq/lib/value" "github.com/mithrandie/go-text" + txjson "github.com/mithrandie/go-text/json" "github.com/mithrandie/ternary" ) @@ -2018,5 +2019,16 @@ func JsonObject(ctx context.Context, scope *ReferenceScope, fn parser.Function) record[i] = view.RecordSet[0][i][0] } structure, _ := json.ConvertRecordValueToJsonStructure(pathes, record) - return value.NewString(structure.Encode()), nil + + encoder := txjson.NewEncoder() + encoder.EscapeType = scope.Tx.Flags.ExportOptions.JsonEscape + encoder.LineBreak = scope.Tx.Flags.ExportOptions.LineBreak + encoder.FloatFormat = jsonFloatFormat(scope.Tx.Flags.ExportOptions.ScientificNotation) + + val, err := encoder.Encode(structure) + if err != nil { + return nil, NewDataEncodingError(fmt.Sprintf("%s in JSON encoding", err.Error())) + } + + return value.NewString(val), nil } diff --git a/lib/query/function_test.go b/lib/query/function_test.go index 30aed54..b674e51 100644 --- a/lib/query/function_test.go +++ b/lib/query/function_test.go @@ -4288,11 +4288,12 @@ func TestNow(t *testing.T) { } var jsonObjectTests = []struct { - Name string - Function parser.Function - Scope *ReferenceScope - Result value.Primary - Error string + Name string + Function parser.Function + ScientificNotation bool + Scope *ReferenceScope + Result value.Primary + Error string }{ { Name: "Json Object", @@ -4317,6 +4318,30 @@ var jsonObjectTests = []struct { }), Result: value.NewString("{\"column1\":11}"), }, + { + Name: "Json Object using Scientific Notation", + Function: parser.Function{ + Name: "json_object", + Args: []parser.QueryExpression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + }, + }, + ScientificNotation: true, + Scope: GenerateReferenceScope(nil, nil, time.Time{}, []ReferenceRecord{ + { + view: &View{ + Header: NewHeaderWithId("table1", []string{"column1", "column2"}), + RecordSet: []Record{ + NewRecordWithId(0, []value.Primary{value.NewInteger(1), value.NewInteger(2)}), + NewRecordWithId(1, []value.Primary{value.NewFloat(0.00000123), value.NewInteger(12)}), + }, + }, + recordIndex: 1, + cache: NewFieldIndexCache(10, LimitToUseFieldIndexSliceChache), + }, + }), + Result: value.NewString("{\"column1\":1.23e-06}"), + }, { Name: "Json Object with All Columns", Function: parser.Function{ @@ -4371,11 +4396,17 @@ var jsonObjectTests = []struct { } func TestJsonObject(t *testing.T) { + defer func() { + TestTx.Flags.ExportOptions.ScientificNotation = false + }() + for _, v := range jsonObjectTests { if v.Scope == nil { v.Scope = NewReferenceScope(TestTx) } + TestTx.Flags.ExportOptions.ScientificNotation = v.ScientificNotation + result, err := JsonObject(context.Background(), v.Scope, v.Function) if err != nil { if len(v.Error) < 1 { diff --git a/lib/query/sort_value.go b/lib/query/sort_value.go index a1a26c3..6bd2cb2 100644 --- a/lib/query/sort_value.go +++ b/lib/query/sort_value.go @@ -84,7 +84,7 @@ func (values SortValues) Serialize(buf *bytes.Buffer) { case IntegerType, BooleanType: serializeInteger(buf, value.Int64ToStr(val.Integer)) case FloatType: - serializeFloat(buf, value.Float64ToStr(val.Float)) + serializeFloat(buf, value.Float64ToStr(val.Float, false)) case DatetimeType: serializeDatetimeFromUnixNano(buf, val.Datetime) case StringType: diff --git a/lib/query/transaction.go b/lib/query/transaction.go index ac527e3..7b748e9 100644 --- a/lib/query/transaction.go +++ b/lib/query/transaction.go @@ -489,6 +489,12 @@ func (tx *Transaction) setFlag(key string, value interface{}, outFile string) er } else { err = errNotAllowdFlagFormat } + case option.ScientificNotationFlag: + if b, ok := value.(bool); ok { + tx.Flags.SetScientificNotation(b) + } else { + err = errNotAllowdFlagFormat + } case option.StripEndingLineBreakFlag: if b, ok := value.(bool); ok { tx.Flags.SetStripEndingLineBreak(b) @@ -620,6 +626,8 @@ func (tx *Transaction) GetFlag(key string) (value.Primary, bool) { val = value.NewString(option.JsonEscapeTypeToString(tx.Flags.ExportOptions.JsonEscape)) case option.PrettyPrintFlag: val = value.NewBoolean(tx.Flags.ExportOptions.PrettyPrint) + case option.ScientificNotationFlag: + val = value.NewBoolean(tx.Flags.ExportOptions.ScientificNotation) case option.StripEndingLineBreakFlag: val = value.NewBoolean(tx.Flags.ExportOptions.StripEndingLineBreak) case option.EastAsianEncodingFlag: diff --git a/lib/terminal/completer_readline.go b/lib/terminal/completer_readline.go index 0700bda..e5fa20a 100644 --- a/lib/terminal/completer_readline.go +++ b/lib/terminal/completer_readline.go @@ -1919,6 +1919,7 @@ func (c *Completer) SetArgs(line string, origLine string, index int) readline.Ca case option.AnsiQuotesFlag, option.StrictEqualFlag, option.AllowUnevenFieldsFlag, option.NoHeaderFlag, option.WithoutNullFlag, option.WithoutHeaderFlag, option.EncloseAllFlag, option.PrettyPrintFlag, + option.ScientificNotationFlag, option.StripEndingLineBreakFlag, option.EastAsianEncodingFlag, option.CountDiacriticalSignFlag, option.CountFormatCodeFlag, option.ColorFlag, option.QuietFlag, option.StatsFlag: diff --git a/lib/value/conv.go b/lib/value/conv.go index b3a312b..6fdf454 100644 --- a/lib/value/conv.go +++ b/lib/value/conv.go @@ -225,7 +225,7 @@ func ConvertDatetimeFormat(format string) string { } func Float64ToTime(f float64, location *time.Location) time.Time { - s := Float64ToStr(f) + s := Float64ToStr(f, false) ar := strings.Split(s, ".") sec, _ := strconv.ParseInt(ar[0], 10, 64) @@ -249,7 +249,10 @@ func Int64ToStr(i int64) string { return strconv.FormatInt(i, 10) } -func Float64ToStr(f float64) string { +func Float64ToStr(f float64, useScientificNotation bool) string { + if useScientificNotation { + return strconv.FormatFloat(f, 'g', -1, 64) + } return strconv.FormatFloat(f, 'f', -1, 64) } @@ -341,7 +344,7 @@ func ToString(p Primary) Primary { case *Integer: return NewString(Int64ToStr(p.(*Integer).Raw())) case *Float: - return NewString(Float64ToStr(p.(*Float).Raw())) + return NewString(Float64ToStr(p.(*Float).Raw(), false)) } return NewNull() } diff --git a/lib/value/conv_test.go b/lib/value/conv_test.go index 88973fc..c37dba6 100644 --- a/lib/value/conv_test.go +++ b/lib/value/conv_test.go @@ -297,6 +297,22 @@ func TestFloat64ToTime(t *testing.T) { } } +func TestFloat64ToStr(t *testing.T) { + f := 0.000000123 + expect := "0.000000123" + + result := Float64ToStr(f, false) + if result != expect { + t.Errorf("result = %q, want %q for %f", result, expect, f) + } + + expect = "1.23e-07" + result = Float64ToStr(f, true) + if result != expect { + t.Errorf("result = %q, want %q for %f", result, expect, f) + } +} + func TestToInteger(t *testing.T) { var p Primary var i Primary diff --git a/lib/value/type.go b/lib/value/type.go index eaaa7f3..a90e9d9 100644 --- a/lib/value/type.go +++ b/lib/value/type.go @@ -115,7 +115,7 @@ func NewFloat(f float64) *Float { } func (f Float) String() string { - return Float64ToStr(f.value) + return Float64ToStr(f.value, false) } func (f Float) Raw() float64 { From 22ec4d3389d17653fdaaf832496a5b074fb2005d Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Mon, 4 Jul 2022 05:10:10 +0900 Subject: [PATCH 16/17] Fix a bug of JSON_OBJECT function. --- lib/query/field_analyzer.go | 9 +++++++++ lib/query/field_analyzer_test.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/query/field_analyzer.go b/lib/query/field_analyzer.go index b07317c..23a0ead 100644 --- a/lib/query/field_analyzer.go +++ b/lib/query/field_analyzer.go @@ -1,6 +1,8 @@ package query import ( + "strings" + "github.com/mithrandie/csvq/lib/parser" ) @@ -10,6 +12,10 @@ func HasAggregateFunction(expr parser.QueryExpression, scope *ReferenceScope) (b return true, nil case parser.Function: e := expr.(parser.Function) + if strings.ToUpper(e.Name) == "JSON_OBJECT" { + return false, nil + } + if udfn, err := scope.GetFunction(expr, expr.(parser.Function).Name); err == nil && udfn.IsAggregate { return true, nil } @@ -206,6 +212,9 @@ func SearchAnalyticFunctions(expr parser.QueryExpression) ([]parser.AnalyticFunc e := expr.(parser.All) return searchAnalyticFunctionsInRowValueComparison(e.LHS, e.Values) case parser.Function: + if strings.ToUpper(expr.(parser.Function).Name) == "JSON_OBJECT" { + return nil, nil + } return SearchAnalyticFunctionsInList(expr.(parser.Function).Args) case parser.AggregateFunction: return SearchAnalyticFunctionsInList(expr.(parser.AggregateFunction).Args) diff --git a/lib/query/field_analyzer_test.go b/lib/query/field_analyzer_test.go index 6d97bb8..7dd1039 100644 --- a/lib/query/field_analyzer_test.go +++ b/lib/query/field_analyzer_test.go @@ -1,10 +1,11 @@ package query import ( - "github.com/mithrandie/csvq/lib/parser" "reflect" "testing" "time" + + "github.com/mithrandie/csvq/lib/parser" ) var hasAggregateFunctionTests = []struct { @@ -52,6 +53,20 @@ var hasAggregateFunctionTests = []struct { }, Result: false, }, + { + Name: "JSON_OBJECT Function", + Expr: parser.Function{ + Name: "json_object", + Args: []parser.QueryExpression{ + parser.Field{ + Object: parser.FieldReference{ + Column: parser.Identifier{Literal: "column1"}, + }, + }, + }, + }, + Result: false, + }, { Name: "User Defined Aggregate Function", Expr: parser.Function{ @@ -492,6 +507,20 @@ var searchAnalyticFunctionsTests = []struct { }, }, }, + { + Name: "JSON_OBJECT Function", + Expr: parser.Function{ + Name: "json_object", + Args: []parser.QueryExpression{ + parser.Field{ + Object: parser.FieldReference{ + Column: parser.Identifier{Literal: "column1"}, + }, + }, + }, + }, + Result: []parser.AnalyticFunction(nil), + }, } func TestSearchAnalyticFunctions(t *testing.T) { From cb9dec2bf7a5d5c0f7c0d5450e111527590c54f8 Mon Sep 17 00:00:00 2001 From: Mithrandie Date: Mon, 4 Jul 2022 05:32:42 +0900 Subject: [PATCH 17/17] Update docs for Release v1.17.7. --- CHANGELOG.md | 9 +++++++++ docs/changelog.md | 9 +++++++++ docs/index.md | 6 +++--- docs/sitemap.xml | 4 ++-- lib/query/version.go | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a6540..1fdd7d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## Version 1.17.7 + +Released on Jul 3, 2022 + +- Add [system defined constants](https://mithrandie.github.io/csvq/reference/system-defined-constant.html). +- Handle NaN and Infinity. +- Add several numeric and datetime functions. +- Fix some bugs. + ## Version 1.17.6 Released on Jun 30, 2022 diff --git a/docs/changelog.md b/docs/changelog.md index dd60e69..50cd57c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,6 +5,15 @@ title: Change Log - csvq # Change Log +## Version 1.17.7 + +Released on Jul 3, 2022 + +- Add [system defined constants](https://mithrandie.github.io/csvq/reference/system-defined-constant.html). +- Handle NaN and Infinity. +- Add several numeric and datetime functions. +- Fix some bugs. + ## Version 1.17.6 Released on Jun 30, 2022 diff --git a/docs/index.md b/docs/index.md index 22bd4e9..e583e4a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,10 +13,10 @@ In the multiple operations, you can use variables, cursors, temporary tables, an ## Latest Release -Version 1.17.6 -: Released on Jun 30, 2022 +Version 1.17.7 +: Released on Jul 3, 2022 - + file_downloaddownload diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 7c33aad..90a8bb3 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -6,7 +6,7 @@ http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> https://mithrandie.github.io/csvq/ - 2022-06-30T13:40:41+00:00 + 2022-07-03T20:31:51+00:00 https://mithrandie.github.io/csvq/reference.html @@ -182,7 +182,7 @@ https://mithrandie.github.io/csvq/changelog.html - 2022-06-30T13:40:41+00:00 + 2022-07-03T20:31:51+00:00 https://mithrandie.github.io/csvq/license.html diff --git a/lib/query/version.go b/lib/query/version.go index ac7b27d..834987c 100644 --- a/lib/query/version.go +++ b/lib/query/version.go @@ -1,3 +1,3 @@ package query -var Version = "v1.17.6" +var Version = "v1.17.7"