diff --git a/Makefile b/Makefile index 17f24c67..76ac9eb0 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,18 @@ ifeq ($(shell command -v glide 2>/dev/null),) curl https://glide.sh/get | sh endif +.PHONY: goyacc +goyacc: +ifeq ($(shell command -v goyacc 2>/dev/null),) + go get -u github.com/cznic/goyacc +endif + +.PHONY: yacc +yacc: goyacc + cd lib/parser && \ + goyacc -o parser.go -v parser.output parser.y && \ + cd ../.. + .PHONY: test test: go test -cover `glide novendor` diff --git a/docs/_includes/side_menu.html b/docs/_includes/side_menu.html index 39d802a5..c811cf04 100644 --- a/docs/_includes/side_menu.html +++ b/docs/_includes/side_menu.html @@ -61,6 +61,7 @@
  • Cryptographic Hash Functions
  • Cast Functions
  • System Functions
  • +
  • Analytic Functions
  • diff --git a/docs/_posts/2006-01-02-analytic-functions.md b/docs/_posts/2006-01-02-analytic-functions.md new file mode 100644 index 00000000..7d2b35a8 --- /dev/null +++ b/docs/_posts/2006-01-02-analytic-functions.md @@ -0,0 +1,89 @@ +--- +layout: default +title: Analytic Functions - Reference Manual - csvq +category: reference +--- + +# Analytic Functions + +Analytic functions calculate values of groups. +Analytic Functions can be used only in [Select Clause]({{ '/reference/select-query.html#select_clause' | relative_url }}) and [Order By Clause]({{ '/reference/select-query.html#order_by_clause' | relative_url }}) + +| name | description | +| :- | :- | +| [ROW_NUMBER](#row_number) | Return sequential numbers | +| [RANK](#rank) | Return ranks | +| [DENSE_RANK](#dense_rank) | Return ranks without any gaps in the ranking | + +## Syntax +{: #syntax} + +```sql +analytic_function + : function_name([args]) OVER ([partition_clause] [order_by_clause]) + +args + : value [, value ...] + +partition_clause + : PARTITION BY value [, value ...] +``` + +_value_ +: [value]({{ '/reference/value.html' | relative_url }}) + +_order_by_clause_ +: [Order By Clause]({{ '/reference/select_query.html#order_by_clause' | relative_url }}) + +Analytic Functions sort the result set by _order_by_clause_ and calculate values within each of groups partitioned by _partition_clause_. +If there is no _partition_clause_, then all records of result set are dealt with as one group. + +## Definitions + +### ROW_NUMBER +{: #row_number} + +``` +ROW_NUMBER() OVER ([partition_clause] [order_by_clause]) +``` + +_partition_clause_ +: [Partition Clause](#syntax) + +_order_by_clause_ +: [Order By Clause]({{ '/reference/select_query.html#order_by_clause' | relative_url }}) + +Return sequential numbers of records in a group. + + +### RANK +{: #rank} + +``` +RANK() OVER ([partition_clause] [order_by_clause]) +``` + +_partition_clause_ +: [Partition Clause](#syntax) + +_order_by_clause_ +: [Order By Clause]({{ '/reference/select_query.html#order_by_clause' | relative_url }}) + +Returns ranks of records in a group. + + +### DENSE_RANK +{: #dense_rank} + +``` +DENSE_RANK() OVER ([partition_clause] [order_by_clause]) +``` + +_partition_clause_ +: [Partition Clause](#syntax) + +_order_by_clause_ +: [Order By Clause]({{ '/reference/select_query.html#order_by_clause' | relative_url }}) + +Returns ranks of records without any gaps in the ranking in a group. + diff --git a/docs/_posts/2006-01-02-arithmetic-operators.md b/docs/_posts/2006-01-02-arithmetic-operators.md index 9cc7a9b9..b030355a 100644 --- a/docs/_posts/2006-01-02-arithmetic-operators.md +++ b/docs/_posts/2006-01-02-arithmetic-operators.md @@ -6,7 +6,7 @@ category: reference # Arithmetic Operators -| name | description | +| operator | description | | :- | :- | | + | Addition | | \- | Subtraction | @@ -26,4 +26,4 @@ _float_ An arithmetic operator calculate float values, and return a integer or float value. If each of operands is not a float value, the value is converted to a float value. -If either of operands is null or conversion to float failed, return null. +If either of operands is null or conversions to float failed, return null. diff --git a/docs/_posts/2006-01-02-comparison-operators.md b/docs/_posts/2006-01-02-comparison-operators.md index 47340a9e..a2f81120 100644 --- a/docs/_posts/2006-01-02-comparison-operators.md +++ b/docs/_posts/2006-01-02-comparison-operators.md @@ -6,7 +6,7 @@ category: reference # Comparison Operators -| name | description | +| operator | description | | :- | :- | | [Relational Operators](#relational_operators) | Compare values | | [IS](#is) | Compare a value with ternary value | @@ -22,7 +22,7 @@ A comparison operator returns a ternary value. ## Relational Operators {: #relational_operators} -| name | description | +| operator | description | | :- | :- | | \= | Equal | | < | Less than | @@ -128,7 +128,7 @@ _multiple_fields_subquery_ Check if a _value_ or _row_value_ is in within a set of _values_ or a result set of _select_query_. -A IN operation is equivalent to a ANY operation that operator is specified as "=". +A IN operation is equivalent to a [ANY](#any) operation that _relational_operator_ is specified as "=". ## LIKE {: #like} @@ -185,7 +185,7 @@ If any of comparison results is TRUE, return TRUE. If there is no TRUE result and there is at least one UNKNOWN result, return UNKNOWN. Otherwise return FALSE. -If _select_query_ returns no values, return FALSE. +If _select_query_ returns no record, return FALSE. ## ALL {: #all} @@ -218,7 +218,7 @@ If any of comparison results is FALSE, return FALSE. If there is no FALSE result and there is at least one UNKNOWN result, return UNKNOWN. Otherwise return TRUE. -If _select_query_ returns no values, return TRUE. +If _select_query_ returns no record, return TRUE. ## Exists {: #exists} diff --git a/docs/_posts/2006-01-02-datetime-functions.md b/docs/_posts/2006-01-02-datetime-functions.md index 7b394302..4197e7df 100644 --- a/docs/_posts/2006-01-02-datetime-functions.md +++ b/docs/_posts/2006-01-02-datetime-functions.md @@ -8,7 +8,7 @@ category: reference | name | description | | :- | :- | -| [NOW](#now) | Return current date and time | +| [NOW](#now) | Return a datetime value of current date and time | | [DATETIME_FORMAT](#datetime_format) | Format a datetime | | [YEAR](#year) | Return year of a datetime | | [MONTH](#month) | Return month of a datetime | @@ -48,7 +48,7 @@ NOW() _return_ : [datetime]({{ '/reference/value.html#datetime' | relative_url }}) -Return current date and time. +Return a datetime value of current date and time. ### DATETIME_FORMAT {: #datetime_format} diff --git a/docs/_posts/2006-01-02-logic-operators.md b/docs/_posts/2006-01-02-logic-operators.md index 4208222b..119f640d 100644 --- a/docs/_posts/2006-01-02-logic-operators.md +++ b/docs/_posts/2006-01-02-logic-operators.md @@ -6,7 +6,7 @@ category: reference # Logic Operators -| name | description | +| operator | description | | :- | :- | | [AND](#and) | Logical AND | | [OR](#or) | Logical OR | diff --git a/docs/_posts/2006-01-02-numeric-functions.md b/docs/_posts/2006-01-02-numeric-functions.md index 0788d718..703205e4 100644 --- a/docs/_posts/2006-01-02-numeric-functions.md +++ b/docs/_posts/2006-01-02-numeric-functions.md @@ -69,7 +69,7 @@ _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) Round _number_ up to _place_ decimal place. -If _place_ is negative number, _place_ representing a place in integer part, +If _place_ is a negative number, _place_ representing a place in the integer part. ### FLOOR {: #floor} @@ -100,7 +100,7 @@ _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) Round _number_ down to _place_ decimal place. -If _place_ is negative number, _place_ representing a place in integer part, +If _place_ is a negative number, _place_ representing a place in the integer part. ### ROUND {: #round} @@ -131,7 +131,7 @@ _return_ : [float]({{ '/reference/value.html#float' | relative_url }}) or [integer]({{ '/reference/value.html#integer' | relative_url }}) Round _number_ to _place_ decimal place. -If _place_ is negative number, _place_ representing a place in integer part, +If _place_ is a negative number, _place_ representing a place in the integer part. ### ABS {: #abs} diff --git a/docs/_posts/2006-01-02-select-query.md b/docs/_posts/2006-01-02-select-query.md index 4712e48e..da0f062a 100644 --- a/docs/_posts/2006-01-02-select-query.md +++ b/docs/_posts/2006-01-02-select-query.md @@ -218,27 +218,27 @@ ORDER BY order_item [, order_item ...] ```sql order_item - : field_name - | field_name [ASC|DESC] + : field_name [order_direction] [null_position] + +order_direction + : {ASC|DESC} + +null_position + : NULLS {FIRST|LAST} ``` _field_name_ : [value]({{ '/reference/value.html' | relative_url }}) - If DISTINCT keyword is specified in the select clause, you can use only enumerated fields in the select clause as _field_name_. + If DISTINCT keyword is specified in the select clause, you can use only enumerated fields in the select clause as _field_name_. -Default order direction is ASC. -If order direction is not specified, the next order_item's direction is applied. +_order_direction_ +: _ASC_ sorts records in ascending order. _DESC_ sorts in descending order. _ASC_ is the default. -```sql --- Following expressions return same results -ORDER BY column1, column2 -ORDER BY column1 ASC, column2 ASC +_null_position_ +: _FIRST_ puts null values first. _LAST_ puts null values last. + If _order_direction_ is specified as _ASC_ then _FIRST_ is the default, otherwise _LAST_ is the default. --- Following expressions return same results -ORDER BY column1, column2 ASC, column3, column4 DESC -ORDER BY column1 ASC, column2 ASC, column3 DESC, column4 DESC -``` ## Limit Clause {: #limit_clause} @@ -246,12 +246,21 @@ ORDER BY column1 ASC, column2 ASC, column3 DESC, column4 DESC The Limit clause is used to specify the maximum number of records to return. ```sql -LIMIT number +limit_clause + : LIMIT number_of_records [WITH TIES] + | LIMIT percent PERCENT [WITH TIES] ``` -_number_ +_number_of_records_ : [integer]({{ '/reference/value.html#integer' | relative_url }}) +_percent_ +: [float]({{ '/reference/value.html#integer' | relative_url }}) + +If _PERCENT_ keyword is specified, maximum number of records is _percent_ percent of the result set that includes the excluded records by _Offset Clause_. + +If _WITH TIES_ keywords are specified, all records that have the same sort keys specified by _Order By Clause_ as the last record of the limited records are included in the records to return. +If there is no _Order By Clause_ in the query, _WITH TIES_ keywords are ignored. ## Offset Clause {: #offset_clause} diff --git a/docs/_posts/2006-01-02-set-operators.md b/docs/_posts/2006-01-02-set-operators.md index 24b5596d..db3719bf 100644 --- a/docs/_posts/2006-01-02-set-operators.md +++ b/docs/_posts/2006-01-02-set-operators.md @@ -6,7 +6,7 @@ category: reference # Set Operators -| name | description | +| operator | description | | :- | :- | | [UNION](#union) | Return the union of result sets | | [EXCEPT](#except) | Return the relative complement of result sets | @@ -37,7 +37,7 @@ select_query EXCEPT [ALL] select_query _select_query_ : [select_set_entity]({{ '/reference/select-query.html' | relative_url }}) -Return records of a first result set that do not appear in a second result set. +Return records of the result set of the left-hand side query that do not appear in the result set of the right-hand side query. ## INTERSECT {: #intersect} diff --git a/docs/_posts/2006-01-02-statement.md b/docs/_posts/2006-01-02-statement.md index c309c26f..c5e1caa7 100644 --- a/docs/_posts/2006-01-02-statement.md +++ b/docs/_posts/2006-01-02-statement.md @@ -139,12 +139,12 @@ HAVING IF IN INNER INSERT INTERSECT INTO IS JOIN LAST LEFT LIKE LIMIT -NATURAL NOT NULL -OFFSET ON OPEN OR ORDER OUTER -PRINT +NATURAL NOT NULL NULLS +OFFSET ON OPEN OR ORDER OUTER OVER +PARTITION PERCENT PRINT RENAME RIGHT ROLLBACK SELECT SET SEPARATOR STDIN -TABLE THEN TO +TABLE THEN TIES TO UNION UPDATE USING VALUES VAR WHEN WHERE WHILE WITH diff --git a/docs/_posts/2006-01-02-string-operators.md b/docs/_posts/2006-01-02-string-operators.md index 14e80caf..da364e8c 100644 --- a/docs/_posts/2006-01-02-string-operators.md +++ b/docs/_posts/2006-01-02-string-operators.md @@ -6,7 +6,7 @@ category: reference # String Operators -| name | description | +| operator | description | | :- | :- | | \|\| | Concatnation | diff --git a/docs/_posts/2006-01-02-value.md b/docs/_posts/2006-01-02-value.md index ded438c1..8db75c6b 100644 --- a/docs/_posts/2006-01-02-value.md +++ b/docs/_posts/2006-01-02-value.md @@ -107,6 +107,7 @@ user.id -- table name and column name * [Cryptographic Hash Functions]({{ '/reference/cryptographic-hash-functions.html' | relative_url }}) * [Cast Functions]({{ '/reference/cast-functions.html' | relative_url }}) * [System Functions]({{ '/reference/system-functions.html' | relative_url }}) +* [Analytic Functions]({{ '/reference/analytic-functions.html' | relative_url }}) ### Subquery {: #subquery} diff --git a/docs/reference.md b/docs/reference.md index 0acb756c..4e5a7a6e 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -39,3 +39,4 @@ title: Reference Manual - csvq * [Cryptographic Hash Functions]({{ '/reference/cryptographic-hash-functions.html' | relative_url }}) * [Cast Functions]({{ '/reference/cast-functions.html' | relative_url }}) * [System Functions]({{ '/reference/system-functions.html' | relative_url }}) + * [Analytic Functions]({{ '/reference/analytic-functions.html' | relative_url }}) diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 07bed01b..94e75646 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -10,7 +10,7 @@ https://mithrandie.github.io/csvq/reference.html - 2017-06-29T17:08:49+00:00 + 2017-07-02T23:29:47+00:00 https://mithrandie.github.io/csvq/reference/install.html @@ -22,15 +22,15 @@ https://mithrandie.github.io/csvq/reference/statement.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T04:36:43+00:00 https://mithrandie.github.io/csvq/reference/value.html - 2017-06-29T17:08:49+00:00 + 2017-07-02T23:29:47+00:00 https://mithrandie.github.io/csvq/reference/select-query.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T04:36:43+00:00 https://mithrandie.github.io/csvq/reference/insert-query.html @@ -86,23 +86,23 @@ https://mithrandie.github.io/csvq/reference/arithmetic-operators.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/comparison-operators.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/logic-operators.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/string-operators.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/set-operators.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/aggregate-functions.html @@ -118,11 +118,11 @@ https://mithrandie.github.io/csvq/reference/numeric-functions.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/datetime-functions.html - 2017-06-29T17:08:49+00:00 + 2017-06-30T20:24:07+00:00 https://mithrandie.github.io/csvq/reference/cryptographic-hash-functions.html @@ -136,6 +136,10 @@ https://mithrandie.github.io/csvq/reference/system-functions.html 2017-06-29T17:08:49+00:00 + + https://mithrandie.github.io/csvq/reference/analytic-functions.html + 2017-07-02T23:29:47+00:00 + https://mithrandie.github.io/csvq/license.html 2017-06-29T17:08:49+00:00 diff --git a/lib/action/calc_test.go b/lib/action/calc_test.go index 7246d728..e7fd21d6 100644 --- a/lib/action/calc_test.go +++ b/lib/action/calc_test.go @@ -37,7 +37,7 @@ var calcTests = []struct { { Stdin: "foo", Input: "error", - Error: "identifier = error: field does not exist", + Error: "field error does not exist", }, } diff --git a/lib/action/main_test.go b/lib/action/main_test.go index 208a5be9..86527138 100644 --- a/lib/action/main_test.go +++ b/lib/action/main_test.go @@ -14,10 +14,14 @@ func GetTestFilePath(filename string) string { } func TestMain(m *testing.M) { + os.Exit(run(m)) +} + +func run(m *testing.M) int { + defer teardown() + setup() - r := m.Run() - teardown() - os.Exit(r) + return m.Run() } func setup() { diff --git a/lib/cmd/main_test.go b/lib/cmd/main_test.go index 7b23dd52..c29142f5 100644 --- a/lib/cmd/main_test.go +++ b/lib/cmd/main_test.go @@ -13,10 +13,14 @@ func GetTestFilePath(filename string) string { } func TestMain(m *testing.M) { + os.Exit(run(m)) +} + +func run(m *testing.M) int { + defer teardown() + setup() - r := m.Run() - teardown() - os.Exit(r) + return m.Run() } func setup() { diff --git a/lib/parser/ast.go b/lib/parser/ast.go index 92adfd08..280f8d77 100644 --- a/lib/parser/ast.go +++ b/lib/parser/ast.go @@ -541,22 +541,51 @@ func (ob OrderByClause) String() string { } type LimitClause struct { - Limit string - Number int64 + Limit string + Value Expression + Percent string + With Expression } -func (l LimitClause) String() string { - s := []string{l.Limit, strconv.FormatInt(l.Number, 10)} +func (e LimitClause) String() string { + s := []string{e.Limit, e.Value.String()} + if e.IsPercentage() { + s = append(s, e.Percent) + } + if e.With != nil { + s = append(s, e.With.String()) + } + return joinWithSpace(s) +} + +func (e LimitClause) IsPercentage() bool { + return 0 < len(e.Percent) +} + +func (e LimitClause) IsWithTies() bool { + if e.With == nil { + return false + } + return e.With.(LimitWith).Type.Token == TIES +} + +type LimitWith struct { + With string + Type Token +} + +func (e LimitWith) String() string { + s := []string{e.With, e.Type.Literal} return joinWithSpace(s) } type OffsetClause struct { Offset string - Number int64 + Value Expression } func (e OffsetClause) String() string { - s := []string{e.Offset, strconv.FormatInt(e.Number, 10)} + s := []string{e.Offset, e.Value.String()} return joinWithSpace(s) } @@ -889,14 +918,19 @@ func (si Stdin) String() string { } type OrderItem struct { - Item Expression + Value Expression Direction Token + Nulls string + Position Token } -func (oi OrderItem) String() string { - s := []string{oi.Item.String()} - if !oi.Direction.IsEmpty() { - s = append(s, oi.Direction.Literal) +func (e OrderItem) String() string { + s := []string{e.Value.String()} + if !e.Direction.IsEmpty() { + s = append(s, e.Direction.Literal) + } + if 0 < len(e.Nulls) { + s = append(s, e.Nulls, e.Position.Literal) } return joinWithSpace(s) } @@ -973,6 +1007,68 @@ func (gc GroupConcat) String() string { return gc.GroupConcat + "(" + joinWithSpace(s) + ")" } +type AnalyticFunction struct { + Name string + Option Option + Over string + AnalyticClause AnalyticClause +} + +func (e AnalyticFunction) String() string { + s := []string{ + e.Name + "(" + e.Option.String() + ")", + e.Over, + "(" + e.AnalyticClause.String() + ")", + } + return joinWithSpace(s) +} + +type AnalyticClause struct { + Partition Expression + OrderByClause Expression +} + +func (e AnalyticClause) String() string { + s := []string{} + if e.Partition != nil { + s = append(s, e.Partition.String()) + } + if e.OrderByClause != nil { + s = append(s, e.OrderByClause.String()) + } + return joinWithSpace(s) +} + +func (e AnalyticClause) PartitionValues() []Expression { + if e.Partition == nil { + return nil + } + return e.Partition.(Partition).Values +} + +func (e AnalyticClause) OrderValues() []Expression { + if e.OrderByClause == nil { + return nil + } + + items := e.OrderByClause.(OrderByClause).Items + result := make([]Expression, len(items)) + for i, v := range items { + result[i] = v.(OrderItem).Value + } + return result +} + +type Partition struct { + PartitionBy string + Values []Expression +} + +func (e Partition) String() string { + s := []string{e.PartitionBy, listExpressions(e.Values)} + return joinWithSpace(s) +} + type Variable struct { Name string } diff --git a/lib/parser/ast_test.go b/lib/parser/ast_test.go index c972b2ae..1196337c 100644 --- a/lib/parser/ast_test.go +++ b/lib/parser/ast_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/mithrandie/csvq/lib/ternary" + "reflect" ) func TestIsPrimary(t *testing.T) { @@ -516,17 +517,17 @@ func TestSelectQuery_String(t *testing.T) { OrderBy: "order by", Items: []Expression{ OrderItem{ - Item: Identifier{Literal: "column"}, + Value: Identifier{Literal: "column"}, }, }, }, LimitClause: LimitClause{ - Limit: "limit", - Number: 10, + Limit: "limit", + Value: NewInteger(10), }, OffsetClause: OffsetClause{ Offset: "offset", - Number: 10, + Value: NewInteger(10), }, } expect := "select column from table order by column limit 10 offset 10" @@ -694,10 +695,10 @@ func TestOrderByClause_String(t *testing.T) { OrderBy: "order by", Items: []Expression{ OrderItem{ - Item: Identifier{Literal: "column1"}, + Value: Identifier{Literal: "column1"}, }, OrderItem{ - Item: Identifier{Literal: "column2"}, + Value: Identifier{Literal: "column2"}, Direction: Token{Token: ASC, Literal: "asc"}, }, }, @@ -709,15 +710,53 @@ func TestOrderByClause_String(t *testing.T) { } func TestLimitClause_String(t *testing.T) { - e := LimitClause{Limit: "limit", Number: 10} - expect := "limit 10" + e := LimitClause{Limit: "limit", Value: NewInteger(10), With: LimitWith{With: "with", Type: Token{Token: TIES, Literal: "ties"}}} + expect := "limit 10 with ties" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } + + e = LimitClause{Limit: "limit", Value: NewInteger(10), Percent: "percent"} + expect = "limit 10 percent" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } +} + +func TestLimitClause_IsPercentage(t *testing.T) { + e := LimitClause{Limit: "limit", Value: NewInteger(10)} + if e.IsPercentage() { + t.Errorf("percentage = %t, want %t for %#v", e.IsPercentage(), false, e) + } + + e = LimitClause{Limit: "limit", Value: NewInteger(10), Percent: "percent"} + if !e.IsPercentage() { + t.Errorf("percentage = %t, want %t for %#v", e.IsPercentage(), true, e) + } +} + +func TestLimitClause_IsWithTies(t *testing.T) { + e := LimitClause{Limit: "limit", Value: NewInteger(10)} + if e.IsWithTies() { + t.Errorf("with ties = %t, want %t for %#v", e.IsWithTies(), false, e) + } + + e = LimitClause{Limit: "limit", Value: NewInteger(10), With: LimitWith{With: "with", Type: Token{Token: TIES, Literal: "ties"}}} + if !e.IsWithTies() { + t.Errorf("with ties = %t, want %t for %#v", e.IsWithTies(), true, e) + } +} + +func TestLimitWith_String(t *testing.T) { + e := LimitWith{With: "with", Type: Token{Token: TIES, Literal: "ties"}} + expect := "with ties" if e.String() != expect { t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) } } func TestOffsetClause_String(t *testing.T) { - e := OffsetClause{Offset: "offset", Number: 10} + e := OffsetClause{Offset: "offset", Value: NewInteger(10)} expect := "offset 10" if e.String() != expect { t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) @@ -1269,7 +1308,7 @@ func TestStdin_String(t *testing.T) { func TestOrderItem_String(t *testing.T) { e := OrderItem{ - Item: Identifier{Literal: "column"}, + Value: Identifier{Literal: "column"}, Direction: Token{Token: DESC, Literal: "desc"}, } expect := "column desc" @@ -1278,12 +1317,22 @@ func TestOrderItem_String(t *testing.T) { } e = OrderItem{ - Item: Identifier{Literal: "column"}, + Value: Identifier{Literal: "column"}, } expect = "column" if e.String() != expect { t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) } + + e = OrderItem{ + Value: Identifier{Literal: "column"}, + Nulls: "nulls", + Position: Token{Token: FIRST, Literal: "first"}, + } + expect = "column nulls first" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } } func TestCase_String(t *testing.T) { @@ -1376,6 +1425,121 @@ func TestGroupConcat_String(t *testing.T) { } } +func TestAnalyticFunction_String(t *testing.T) { + e := AnalyticFunction{ + Name: "avg", + Option: Option{ + Args: []Expression{ + Identifier{Literal: "column4"}, + }, + }, + Over: "over", + AnalyticClause: AnalyticClause{ + Partition: Partition{ + PartitionBy: "partition by", + Values: []Expression{ + Identifier{Literal: "column1"}, + Identifier{Literal: "column2"}, + }, + }, + OrderByClause: OrderByClause{ + OrderBy: "order by", + Items: []Expression{ + OrderItem{Value: Identifier{Literal: "column3"}}, + }, + }, + }, + } + expect := "avg(column4) over (partition by column1, column2 order by column3)" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } +} + +func TestAnalyticClause_String(t *testing.T) { + e := AnalyticClause{ + Partition: Partition{ + PartitionBy: "partition by", + Values: []Expression{ + Identifier{Literal: "column1"}, + Identifier{Literal: "column2"}, + }, + }, + OrderByClause: OrderByClause{ + OrderBy: "order by", + Items: []Expression{ + OrderItem{Value: Identifier{Literal: "column3"}}, + }, + }, + } + expect := "partition by column1, column2 order by column3" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } +} + +func TestAnalyticClause_PartitionValues(t *testing.T) { + e := AnalyticClause{ + Partition: Partition{ + PartitionBy: "partition by", + Values: []Expression{ + Identifier{Literal: "column1"}, + Identifier{Literal: "column2"}, + }, + }, + } + expect := []Expression{ + Identifier{Literal: "column1"}, + Identifier{Literal: "column2"}, + } + if !reflect.DeepEqual(e.PartitionValues(), expect) { + t.Errorf("partition values = %q, want %q for %#v", e.PartitionValues(), expect, e) + } + + e = AnalyticClause{} + expect = []Expression(nil) + if !reflect.DeepEqual(e.PartitionValues(), expect) { + t.Errorf("partition values = %q, want %q for %#v", e.PartitionValues(), expect, e) + } +} + +func TestAnalyticClause_OrderValues(t *testing.T) { + e := AnalyticClause{ + OrderByClause: OrderByClause{ + OrderBy: "order by", + Items: []Expression{ + OrderItem{Value: Identifier{Literal: "column3"}}, + }, + }, + } + expect := []Expression{ + Identifier{Literal: "column3"}, + } + if !reflect.DeepEqual(e.OrderValues(), expect) { + t.Errorf("order values = %q, want %q for %#v", e.OrderValues(), expect, e) + } + + e = AnalyticClause{} + expect = []Expression(nil) + if !reflect.DeepEqual(e.OrderValues(), expect) { + t.Errorf("order values = %q, want %q for %#v", e.OrderValues(), expect, e) + } +} + +func TestPartition_String(t *testing.T) { + e := Partition{ + PartitionBy: "partition by", + Values: []Expression{ + Identifier{Literal: "column1"}, + Identifier{Literal: "column2"}, + }, + } + expect := "partition by column1, column2" + if e.String() != expect { + t.Errorf("string = %q, want %q for %#v", e.String(), expect, e) + } +} + func TestVariable_String(t *testing.T) { e := Variable{ Name: "@var", diff --git a/lib/parser/conv.go b/lib/parser/conv.go index c5ed1344..bd389d4f 100644 --- a/lib/parser/conv.go +++ b/lib/parser/conv.go @@ -38,11 +38,6 @@ func Float64ToStr(f float64) string { return strconv.FormatFloat(f, 'f', -1, 64) } -func StrToInt64(s string) int64 { - i, _ := strconv.ParseInt(s, 10, 64) - return i -} - func Float64ToPrimary(f float64) Primary { s := Float64ToStr(f) if i, e := strconv.ParseInt(s, 10, 64); e == nil { @@ -55,9 +50,13 @@ func PrimaryToInteger(p Primary) Primary { switch p.(type) { case Integer: return p + case Float: + if i, e := strconv.ParseInt(p.(Float).literal, 10, 64); e == nil { + return NewInteger(i) + } case String: - if f, e := strconv.ParseFloat(p.(String).Value(), 64); e == nil { - return NewInteger(int64(f)) + if i, e := strconv.ParseInt(p.(String).Value(), 10, 64); e == nil { + return NewInteger(i) } } diff --git a/lib/parser/conv_test.go b/lib/parser/conv_test.go index 2c913820..d943c456 100644 --- a/lib/parser/conv_test.go +++ b/lib/parser/conv_test.go @@ -70,16 +70,34 @@ func TestPrimaryToInteger(t *testing.T) { t.Errorf("primary type = %T, want Integer for %#v", i, p) } + p = NewFloat(1) + i = PrimaryToInteger(p) + if _, ok := i.(Integer); !ok { + t.Errorf("primary type = %T, want Integer for %#v", i, p) + } + + p = NewFloat(1.6) + i = PrimaryToInteger(p) + if _, ok := i.(Null); !ok { + t.Errorf("primary type = %T, want Null for %#v", i, p) + } + p = NewString("1") i = PrimaryToInteger(p) if _, ok := i.(Integer); !ok { t.Errorf("primary type = %T, want Integer for %#v", i, p) } + p = NewString("1.5") + i = PrimaryToInteger(p) + if _, ok := i.(Null); !ok { + t.Errorf("primary type = %T, want Null for %#v", i, p) + } + p = NewString("error") i = PrimaryToInteger(p) if _, ok := i.(Null); !ok { - t.Errorf("primary type = %T, want Integer for %#v", i, p) + t.Errorf("primary type = %T, want Null for %#v", i, p) } } diff --git a/lib/parser/parser.go b/lib/parser/parser.go index b23ac6be..4c08f110 100644 --- a/lib/parser/parser.go +++ b/lib/parser/parser.go @@ -67,60 +67,65 @@ const ASC = 57383 const DESC = 57384 const LIMIT = 57385 const OFFSET = 57386 -const JOIN = 57387 -const INNER = 57388 -const OUTER = 57389 -const LEFT = 57390 -const RIGHT = 57391 -const FULL = 57392 -const CROSS = 57393 -const ON = 57394 -const USING = 57395 -const NATURAL = 57396 -const UNION = 57397 -const INTERSECT = 57398 -const EXCEPT = 57399 -const ALL = 57400 -const ANY = 57401 -const EXISTS = 57402 -const IN = 57403 -const AND = 57404 -const OR = 57405 -const NOT = 57406 -const BETWEEN = 57407 -const LIKE = 57408 -const IS = 57409 -const NULL = 57410 -const DISTINCT = 57411 -const WITH = 57412 -const CASE = 57413 -const IF = 57414 -const ELSEIF = 57415 -const WHILE = 57416 -const WHEN = 57417 -const THEN = 57418 -const ELSE = 57419 -const DO = 57420 -const END = 57421 -const DECLARE = 57422 -const CURSOR = 57423 -const FOR = 57424 -const FETCH = 57425 -const OPEN = 57426 -const CLOSE = 57427 -const DISPOSE = 57428 -const GROUP_CONCAT = 57429 -const SEPARATOR = 57430 -const COMMIT = 57431 -const ROLLBACK = 57432 -const CONTINUE = 57433 -const BREAK = 57434 -const EXIT = 57435 -const PRINT = 57436 -const VAR = 57437 -const COMPARISON_OP = 57438 -const STRING_OP = 57439 -const SUBSTITUTION_OP = 57440 +const TIES = 57387 +const PERCENT = 57388 +const JOIN = 57389 +const INNER = 57390 +const OUTER = 57391 +const LEFT = 57392 +const RIGHT = 57393 +const FULL = 57394 +const CROSS = 57395 +const ON = 57396 +const USING = 57397 +const NATURAL = 57398 +const UNION = 57399 +const INTERSECT = 57400 +const EXCEPT = 57401 +const ALL = 57402 +const ANY = 57403 +const EXISTS = 57404 +const IN = 57405 +const AND = 57406 +const OR = 57407 +const NOT = 57408 +const BETWEEN = 57409 +const LIKE = 57410 +const IS = 57411 +const NULL = 57412 +const NULLS = 57413 +const DISTINCT = 57414 +const WITH = 57415 +const CASE = 57416 +const IF = 57417 +const ELSEIF = 57418 +const WHILE = 57419 +const WHEN = 57420 +const THEN = 57421 +const ELSE = 57422 +const DO = 57423 +const END = 57424 +const DECLARE = 57425 +const CURSOR = 57426 +const FOR = 57427 +const FETCH = 57428 +const OPEN = 57429 +const CLOSE = 57430 +const DISPOSE = 57431 +const GROUP_CONCAT = 57432 +const SEPARATOR = 57433 +const PARTITION = 57434 +const OVER = 57435 +const COMMIT = 57436 +const ROLLBACK = 57437 +const CONTINUE = 57438 +const BREAK = 57439 +const EXIT = 57440 +const PRINT = 57441 +const VAR = 57442 +const COMPARISON_OP = 57443 +const STRING_OP = 57444 +const SUBSTITUTION_OP = 57445 var yyToknames = [...]string{ "$end", @@ -167,6 +172,8 @@ var yyToknames = [...]string{ "DESC", "LIMIT", "OFFSET", + "TIES", + "PERCENT", "JOIN", "INNER", "OUTER", @@ -191,6 +198,7 @@ var yyToknames = [...]string{ "LIKE", "IS", "NULL", + "NULLS", "DISTINCT", "WITH", "CASE", @@ -211,6 +219,8 @@ var yyToknames = [...]string{ "DISPOSE", "GROUP_CONCAT", "SEPARATOR", + "PARTITION", + "OVER", "COMMIT", "ROLLBACK", "CONTINUE", @@ -239,7 +249,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line parser.y:1325 +//line parser.y:1395 func SetDebugLevel(level int, verbose bool) { yyDebug = level @@ -259,300 +269,316 @@ var yyExca = [...]int{ 1, -1, -2, 0, -1, 16, - 55, 45, - 56, 45, 57, 45, + 58, 45, + 59, 45, -2, 56, -1, 113, - 61, 222, - 65, 222, - 66, 222, - -2, 236, + 63, 235, + 67, 235, + 68, 235, + -2, 249, -1, 132, - 45, 224, - 47, 228, - -2, 160, + 47, 237, + 49, 241, + -2, 173, -1, 167, - 55, 46, - 56, 46, 57, 46, - -2, 74, + 58, 46, + 59, 46, + -2, 77, -1, 169, - 107, 121, - -2, 220, + 112, 131, + -2, 233, -1, 171, - 75, 151, - -2, 222, + 78, 166, + -2, 235, -1, 180, - 37, 121, - 88, 121, - 107, 121, - -2, 220, + 37, 131, + 91, 131, + 112, 131, + -2, 233, -1, 197, - 61, 222, - 65, 222, - 66, 222, - -2, 145, - -1, 205, - 61, 222, - 65, 222, - 66, 222, - -2, 87, - -1, 217, - 47, 228, - -2, 224, - -1, 233, - 61, 222, - 65, 222, - 66, 222, - -2, 217, - -1, 239, - 67, 0, - 96, 0, - 99, 0, - -2, 92, - -1, 240, - 67, 0, - 96, 0, - 99, 0, - -2, 94, - -1, 283, - 61, 222, - 65, 222, - 66, 222, + 63, 235, + 67, 235, + 68, 235, + -2, 159, + -1, 204, + 63, 235, + 67, 235, + 68, 235, + -2, 61, + -1, 208, + 63, 235, + 67, 235, + 68, 235, + -2, 93, + -1, 221, + 49, 241, + -2, 237, + -1, 237, + 63, 235, + 67, 235, + 68, 235, + -2, 230, + -1, 243, + 69, 0, + 101, 0, + 104, 0, + -2, 102, + -1, 244, + 69, 0, + 101, 0, + 104, 0, + -2, 104, + -1, 287, + 63, 235, + 67, 235, + 68, 235, -2, 51, - -1, 329, - 67, 0, - 96, 0, - 99, 0, - -2, 103, - -1, 333, - 61, 222, - 65, 222, - 66, 222, - -2, 156, - -1, 367, - 61, 222, - 65, 222, - 66, 222, - -2, 175, - -1, 393, - 79, 153, - -2, 222, - -1, 397, - 107, 83, - 108, 83, - -2, 46, + -1, 294, + 112, 131, + -2, 233, + -1, 295, + 63, 235, + 67, 235, + 68, 235, + -2, 64, + -1, 337, + 69, 0, + 101, 0, + 104, 0, + -2, 113, + -1, 341, + 63, 235, + 67, 235, + 68, 235, + -2, 171, + -1, 379, + 63, 235, + 67, 235, + 68, 235, + -2, 188, -1, 405, - 61, 222, - 65, 222, - 66, 222, + 82, 168, + -2, 235, + -1, 409, + 112, 86, + 113, 86, + -2, 46, + -1, 417, + 63, 235, + 67, 235, + 68, 235, -2, 55, - -1, 422, - 61, 222, - 65, 222, - 66, 222, - -2, 184, - -1, 429, - 75, 168, - 77, 168, - 79, 168, - -2, 222, - -1, 437, - 91, 18, - 92, 18, + -1, 438, + 63, 235, + 67, 235, + 68, 235, + -2, 197, + -1, 445, + 78, 181, + 80, 181, + 82, 181, + -2, 235, + -1, 453, + 96, 18, + 97, 18, -2, 1, - -1, 440, - 61, 222, - 65, 222, - 66, 222, - -2, 143, + -1, 457, + 63, 235, + 67, 235, + 68, 235, + -2, 157, } const yyPrivate = 57344 -const yyLast = 1132 +const yyLast = 1142 var yyAct = [...]int{ - 80, 40, 450, 40, 311, 459, 375, 44, 76, 380, - 305, 321, 46, 47, 48, 49, 50, 51, 52, 297, - 411, 2, 186, 94, 209, 132, 166, 203, 271, 194, - 92, 67, 68, 69, 53, 43, 1, 388, 218, 216, - 131, 111, 114, 40, 381, 258, 109, 86, 23, 77, - 23, 338, 189, 64, 155, 133, 56, 45, 59, 119, - 221, 137, 222, 223, 224, 219, 421, 374, 217, 183, - 364, 362, 142, 183, 57, 57, 61, 136, 138, 146, - 147, 148, 401, 300, 291, 288, 151, 59, 167, 157, - 158, 159, 160, 161, 39, 39, 39, 37, 143, 176, - 128, 400, 408, 206, 463, 16, 449, 433, 163, 162, - 164, 432, 431, 154, 423, 420, 137, 39, 373, 363, - 334, 185, 220, 59, 39, 59, 256, 40, 85, 38, - 199, 38, 168, 169, 441, 295, 211, 263, 346, 344, - 137, 342, 152, 151, 228, 153, 157, 158, 159, 160, - 161, 40, 174, 180, 215, 45, 188, 159, 160, 161, - 42, 110, 157, 158, 159, 160, 161, 42, 168, 164, - 191, 192, 301, 264, 264, 184, 101, 103, 91, 156, - 227, 234, 40, 119, 57, 213, 237, 42, 207, 42, - 40, 144, 40, 40, 145, 465, 235, 232, 23, 90, - 354, 172, 457, 273, 173, 438, 426, 264, 40, 241, - 263, 392, 386, 349, 453, 324, 298, 42, 452, 323, - 261, 137, 260, 454, 402, 317, 270, 314, 453, 23, - 279, 261, 324, 339, 280, 40, 468, 464, 447, 316, - 318, 425, 121, 320, 264, 104, 264, 264, 164, 243, - 310, 267, 299, 242, 244, 266, 304, 303, 395, 182, - 333, 308, 97, 190, 167, 326, 117, 264, 343, 345, - 347, 102, 325, 40, 313, 322, 306, 175, 236, 38, - 415, 179, 332, 371, 352, 353, 336, 284, 355, 286, - 287, 369, 75, 108, 273, 285, 113, 285, 285, 269, - 268, 350, 178, 137, 106, 348, 246, 245, 137, 211, - 38, 307, 236, 302, 201, 370, 124, 358, 359, 361, - 23, 125, 365, 357, 40, 366, 298, 385, 368, 116, - 117, 118, 282, 372, 387, 259, 221, 383, 222, 223, - 224, 219, 54, 397, 217, 397, 384, 397, 165, 221, - 382, 222, 223, 224, 63, 40, 62, 171, 289, 389, - 177, 149, 55, 264, 40, 229, 230, 187, 127, 115, - 137, 23, 137, 298, 231, 120, 273, 139, 112, 417, - 193, 197, 59, 404, 410, 406, 205, 418, 419, 376, - 377, 378, 379, 59, 41, 414, 264, 416, 59, 66, - 226, 38, 23, 290, 40, 233, 202, 434, 60, 264, - 435, 130, 238, 239, 240, 59, 137, 292, 247, 248, - 249, 250, 251, 252, 253, 437, 65, 444, 40, 93, - 88, 445, 436, 446, 89, 262, 265, 443, 40, 237, - 10, 442, 451, 9, 8, 7, 455, 6, 283, 58, - 58, 23, 38, 40, 458, 456, 210, 70, 71, 72, - 73, 74, 462, 448, 5, 4, 337, 40, 170, 296, - 82, 195, 467, 196, 273, 23, 470, 135, 396, 134, - 398, 460, 399, 38, 95, 23, 126, 3, 273, 129, - 81, 58, 84, 140, 141, 469, 78, 83, 407, 79, - 23, 204, 200, 327, 123, 329, 328, 356, 330, 331, - 281, 36, 15, 274, 23, 100, 101, 103, 14, 104, - 105, 13, 340, 12, 11, 272, 0, 0, 0, 341, - 122, 0, 38, 0, 0, 221, 351, 222, 223, 224, - 219, 412, 413, 217, 439, 0, 58, 0, 0, 197, - 0, 0, 205, 0, 0, 0, 38, 0, 212, 58, - 0, 214, 367, 0, 0, 225, 38, 0, 0, 0, - 58, 0, 0, 0, 0, 122, 0, 0, 106, 0, - 0, 38, 163, 162, 164, 390, 0, 154, 0, 0, - 0, 0, 0, 0, 0, 38, 466, 0, 0, 257, - 393, 0, 0, 0, 0, 296, 0, 296, 0, 296, - 0, 102, 0, 278, 208, 0, 152, 151, 405, 153, - 157, 158, 159, 160, 161, 296, 0, 0, 41, 0, - 39, 0, 18, 34, 19, 0, 17, 0, 212, 0, - 0, 0, 20, 422, 0, 21, 0, 0, 0, 0, - 0, 58, 428, 0, 0, 429, 0, 309, 430, 312, - 315, 212, 212, 0, 0, 0, 0, 0, 0, 0, - 0, 296, 0, 440, 0, 0, 0, 0, 0, 59, - 100, 101, 103, 0, 104, 105, 41, 0, 0, 275, - 0, 32, 0, 0, 0, 122, 0, 26, 0, 0, - 30, 27, 28, 29, 0, 0, 24, 25, 276, 277, - 33, 35, 22, 0, 461, 0, 0, 0, 0, 0, - 360, 0, 319, 42, 0, 0, 0, 0, 0, 0, - 0, 212, 0, 58, 0, 98, 0, 0, 58, 99, - 0, 0, 0, 106, 0, 315, 96, 0, 212, 0, - 0, 122, 163, 162, 164, 0, 0, 154, 0, 0, - 0, 0, 107, 0, 0, 0, 41, 0, 39, 0, - 18, 34, 19, 0, 17, 0, 102, 198, 0, 0, - 20, 87, 0, 21, 0, 0, 152, 151, 0, 153, - 157, 158, 159, 160, 161, 212, 0, 254, 255, 0, - 58, 0, 58, 0, 0, 312, 0, 0, 0, 212, - 212, 0, 0, 0, 0, 424, 0, 59, 100, 101, - 103, 0, 104, 105, 41, 0, 39, 31, 0, 32, - 122, 0, 122, 0, 122, 26, 0, 0, 30, 27, - 28, 29, 0, 0, 24, 25, 58, 0, 33, 35, - 22, 409, 315, 163, 162, 164, 0, 0, 154, 0, - 0, 42, 59, 100, 101, 103, 0, 104, 105, 41, - 0, 0, 312, 98, 0, 0, 0, 99, 0, 0, - 0, 106, 0, 0, 96, 0, 0, 152, 151, 0, - 153, 157, 158, 159, 160, 161, 0, 0, 0, 255, - 107, 59, 100, 101, 103, 0, 104, 105, 41, 0, - 0, 293, 294, 0, 102, 0, 0, 0, 98, 87, - 0, 0, 99, 0, 0, 0, 106, 0, 0, 96, - 0, 0, 163, 162, 164, 0, 0, 154, 0, 0, - 0, 163, 162, 164, 0, 107, 154, 0, 0, 0, - 0, 0, 0, 0, 0, 427, 0, 98, 0, 102, - 335, 99, 0, 0, 87, 106, 152, 151, 96, 153, - 157, 158, 159, 160, 161, 152, 151, 0, 153, 157, - 158, 159, 160, 161, 107, 163, 162, 164, 0, 0, - 154, 0, 0, 0, 0, 163, 162, 164, 102, 403, - 154, 0, 0, 87, 0, 163, 162, 164, 0, 394, - 154, 0, 0, 0, 0, 0, 0, 0, 0, 152, - 151, 181, 153, 157, 158, 159, 160, 161, 0, 152, - 151, 0, 153, 157, 158, 159, 160, 161, 0, 152, - 151, 0, 153, 157, 158, 159, 160, 161, 163, 162, - 164, 0, 0, 154, 0, 0, 0, 0, 163, 162, - 164, 0, 150, 154, 0, 0, 0, 391, 162, 164, - 0, 0, 154, 0, 0, 0, 163, 0, 164, 0, + 80, 40, 392, 40, 53, 166, 44, 467, 319, 477, + 387, 46, 47, 48, 49, 50, 51, 52, 329, 305, + 43, 1, 313, 198, 205, 85, 38, 275, 38, 186, + 67, 68, 69, 427, 213, 194, 2, 94, 303, 92, + 111, 296, 400, 40, 393, 132, 262, 77, 222, 86, + 23, 37, 23, 220, 109, 346, 131, 64, 110, 155, + 45, 137, 114, 59, 16, 133, 56, 163, 162, 164, + 189, 142, 154, 437, 386, 413, 376, 119, 146, 147, + 148, 374, 136, 138, 57, 57, 61, 183, 167, 39, + 183, 308, 59, 163, 162, 164, 412, 424, 154, 176, + 299, 39, 292, 143, 152, 151, 128, 153, 157, 158, + 159, 160, 161, 488, 484, 39, 137, 45, 466, 449, + 185, 225, 448, 226, 227, 228, 223, 40, 447, 221, + 152, 151, 439, 153, 157, 158, 159, 160, 161, 436, + 137, 258, 259, 157, 158, 159, 160, 161, 419, 209, + 472, 40, 385, 375, 39, 342, 59, 174, 260, 59, + 39, 219, 210, 168, 294, 76, 201, 3, 168, 169, + 42, 241, 188, 268, 268, 240, 38, 458, 267, 163, + 162, 164, 40, 354, 154, 352, 224, 42, 191, 192, + 40, 350, 40, 40, 57, 217, 231, 232, 180, 42, + 23, 236, 42, 168, 239, 101, 103, 38, 309, 240, + 122, 268, 40, 267, 245, 184, 152, 151, 277, 153, + 157, 158, 159, 160, 161, 137, 264, 274, 259, 164, + 151, 23, 284, 157, 158, 159, 160, 161, 283, 40, + 119, 288, 144, 290, 291, 91, 328, 90, 268, 156, + 268, 268, 211, 455, 289, 122, 289, 289, 42, 483, + 238, 318, 145, 325, 172, 340, 322, 173, 167, 344, + 312, 268, 351, 353, 355, 311, 307, 40, 321, 356, + 486, 316, 475, 334, 330, 333, 454, 360, 361, 442, + 404, 363, 398, 215, 212, 357, 362, 341, 159, 160, + 161, 265, 38, 470, 358, 102, 332, 469, 471, 414, + 331, 137, 265, 277, 347, 470, 137, 332, 492, 485, + 464, 441, 298, 209, 372, 121, 23, 373, 367, 75, + 108, 104, 40, 113, 397, 382, 271, 377, 164, 370, + 270, 369, 407, 378, 182, 395, 190, 175, 179, 399, + 178, 409, 401, 409, 247, 409, 380, 38, 246, 248, + 117, 384, 97, 40, 273, 272, 250, 249, 116, 117, + 118, 371, 418, 314, 431, 268, 40, 306, 383, 122, + 381, 23, 137, 315, 137, 165, 310, 203, 38, 408, + 416, 410, 106, 411, 171, 433, 426, 177, 124, 277, + 324, 326, 301, 302, 490, 366, 327, 225, 268, 226, + 227, 228, 23, 423, 125, 365, 40, 193, 197, 286, + 54, 451, 204, 208, 396, 268, 394, 430, 263, 432, + 233, 234, 137, 421, 422, 122, 241, 63, 62, 235, + 462, 38, 237, 452, 40, 293, 149, 461, 463, 242, + 243, 244, 453, 88, 40, 251, 252, 253, 254, 255, + 256, 257, 468, 456, 465, 23, 460, 473, 120, 38, + 40, 474, 58, 58, 215, 55, 476, 459, 480, 38, + 70, 71, 72, 73, 74, 287, 59, 489, 40, 59, + 187, 306, 491, 23, 127, 38, 494, 478, 59, 495, + 115, 295, 139, 23, 230, 112, 277, 130, 60, 126, + 41, 66, 129, 38, 58, 493, 140, 141, 122, 23, + 122, 450, 122, 59, 277, 59, 100, 101, 103, 65, + 104, 105, 41, 93, 89, 266, 269, 23, 388, 389, + 390, 391, 306, 425, 335, 10, 337, 9, 8, 7, + 100, 101, 103, 6, 104, 105, 434, 435, 214, 5, + 4, 345, 225, 348, 226, 227, 228, 223, 170, 58, + 221, 82, 195, 304, 200, 196, 135, 359, 134, 200, + 482, 216, 58, 98, 218, 481, 95, 99, 229, 81, + 197, 106, 84, 58, 78, 96, 225, 208, 226, 227, + 228, 223, 428, 429, 221, 83, 79, 379, 420, 300, + 336, 107, 338, 339, 207, 106, 206, 202, 123, 364, + 285, 36, 261, 15, 278, 14, 13, 102, 199, 163, + 402, 164, 87, 349, 154, 12, 282, 11, 276, 0, + 0, 0, 0, 0, 41, 405, 39, 0, 18, 34, + 19, 102, 17, 0, 0, 0, 0, 0, 20, 0, + 0, 21, 0, 417, 0, 216, 152, 151, 0, 153, + 157, 158, 159, 160, 161, 0, 0, 0, 58, 0, + 0, 0, 0, 0, 317, 0, 320, 323, 216, 216, + 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, + 0, 444, 0, 0, 445, 0, 0, 0, 279, 0, + 32, 0, 0, 304, 0, 304, 26, 304, 0, 30, + 27, 28, 29, 0, 0, 0, 457, 24, 25, 280, + 281, 33, 35, 22, 41, 0, 39, 304, 18, 34, + 19, 0, 17, 0, 42, 0, 200, 368, 20, 0, + 0, 21, 0, 200, 0, 0, 0, 0, 0, 0, + 0, 0, 216, 0, 58, 0, 0, 0, 479, 58, + 446, 0, 0, 0, 0, 0, 323, 0, 0, 216, + 0, 0, 0, 0, 0, 0, 0, 304, 0, 0, + 59, 100, 101, 103, 0, 104, 105, 41, 31, 39, + 32, 0, 0, 0, 0, 0, 26, 0, 0, 30, + 27, 28, 29, 0, 0, 0, 0, 24, 25, 0, + 0, 33, 35, 22, 0, 0, 0, 0, 0, 0, + 216, 0, 0, 0, 42, 58, 0, 58, 0, 0, + 320, 0, 0, 0, 216, 216, 0, 0, 98, 0, + 440, 0, 99, 0, 0, 0, 106, 0, 0, 0, + 96, 59, 100, 101, 103, 0, 104, 105, 41, 0, + 0, 0, 59, 100, 101, 103, 107, 104, 105, 41, + 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, + 297, 323, 102, 0, 0, 0, 0, 87, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 163, 162, + 164, 0, 320, 154, 0, 0, 0, 298, 0, 98, + 0, 0, 0, 99, 0, 0, 0, 106, 0, 0, + 98, 96, 0, 0, 99, 0, 0, 0, 106, 0, + 0, 0, 96, 0, 0, 152, 151, 107, 153, 157, + 158, 159, 160, 161, 163, 162, 164, 0, 107, 154, + 0, 0, 0, 102, 343, 163, 162, 164, 87, 487, + 154, 0, 0, 0, 102, 0, 0, 0, 0, 87, + 443, 0, 0, 0, 0, 163, 162, 164, 0, 0, + 154, 152, 151, 0, 153, 157, 158, 159, 160, 161, + 415, 0, 152, 151, 0, 153, 157, 158, 159, 160, + 161, 0, 0, 0, 0, 0, 163, 162, 164, 0, 0, 154, 152, 151, 0, 153, 157, 158, 159, 160, - 161, 164, 152, 151, 154, 153, 157, 158, 159, 160, - 161, 152, 151, 0, 153, 157, 158, 159, 160, 161, - 152, 151, 0, 153, 157, 158, 159, 160, 161, 0, + 161, 406, 163, 162, 164, 0, 0, 154, 0, 0, + 0, 163, 162, 164, 0, 0, 154, 0, 0, 181, + 163, 162, 164, 152, 151, 154, 153, 157, 158, 159, + 160, 161, 403, 162, 164, 150, 0, 154, 0, 152, + 151, 0, 153, 157, 158, 159, 160, 161, 152, 151, + 0, 153, 157, 158, 159, 160, 161, 152, 151, 0, + 153, 157, 158, 159, 160, 161, 0, 0, 164, 152, + 151, 154, 153, 157, 158, 159, 160, 161, 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, 152, 151, 0, 153, 157, 158, 159, 160, 161, } var yyPact = [...]int{ - 755, -1000, 755, -52, -52, -52, -52, -52, -52, -52, - -52, -1000, -1000, -1000, -1000, -1000, 305, 342, 411, 394, - 327, 325, 388, -52, -52, -52, 411, 411, 411, 411, - 411, 897, 897, -52, 366, 897, 355, 274, 85, 173, - -1000, -1000, 111, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 273, 281, 411, 352, -8, 389, -1000, - 54, 363, 411, 411, -52, -10, 93, -1000, -1000, -1000, - 113, -52, -52, -52, 341, 986, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 85, -1000, 813, 27, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 897, 105, 61, 897, - -1000, -1000, 170, -1000, -1000, -1000, -1000, 47, 943, 198, - -39, -1000, 76, 46, 349, 54, 205, 205, 205, 897, - 675, -1000, 23, 270, 400, 897, 82, 411, 411, -1000, - 411, 349, 14, -1000, 378, -1000, -1000, -1000, -1000, 54, - 38, 339, -1000, 388, 897, 99, -1000, -1000, -1000, 383, - 755, 897, 897, 897, 184, 188, 248, 897, 897, 897, - 897, 897, 897, 897, -1000, 690, 19, -1000, 411, 173, - 145, 996, 31, 31, 190, 241, -1000, 1027, -1000, -1000, - 173, 617, 411, 383, 510, -1000, 294, 897, -1000, 111, - -1000, 111, 111, 996, -1000, -23, 336, 996, -1000, -1000, - -1000, 397, -1000, -1000, -24, 870, 31, 83, -1000, 355, - -25, 73, 63, -1000, -1000, -1000, 268, 303, 229, 266, - 54, -1000, -1000, -1000, -1000, -1000, 411, 349, 411, 121, - 119, 411, -1000, 996, 111, -52, -35, 142, 62, -11, - -11, 236, 897, 31, 897, 31, 31, 55, 55, -1000, - -1000, -1000, 1014, 1027, -1000, 897, -1000, -1000, 13, 858, - 156, 897, -1000, 813, -1000, -1000, 31, 35, 33, 32, - 305, 134, 617, -1000, -1000, 897, -52, -52, 122, -1000, - -52, 284, 277, 996, 210, -1000, -1000, 210, 675, 411, - -1000, 897, -1000, -1000, -1000, -1000, -37, 12, -38, 349, - 411, 897, 54, 246, 229, 238, -1000, 54, -1000, -1000, - -1000, 11, -41, 359, 411, 316, -1000, 411, 310, -52, - -1000, 133, 142, 755, 897, -1000, -1000, 1005, -1000, -11, - -1000, -1000, -1000, 791, -1000, -1000, -1000, 132, 145, 897, - 933, 196, 104, -1000, 104, -1000, 104, -1000, -6, 150, - -1000, 923, -1000, -1000, 617, -1000, -1000, 897, 897, -1000, - -1000, -1000, 31, 81, 411, -1000, -1000, 996, 489, 54, - 235, 54, 290, -1000, 411, -1000, -1000, -1000, 411, 411, - 8, -42, 897, 7, 411, -1000, 169, 127, 159, -1000, - 879, 897, -1000, 996, 897, 31, 5, -1000, 4, 0, - -1000, 402, -52, 617, 126, 996, -1000, -1000, 31, -1000, - -1000, -1000, 897, 28, 290, 54, 489, -1000, -1000, -1000, - 359, 411, 996, -1000, -1000, -52, 166, 755, 1027, 996, - -1000, -1000, -1000, -1000, -1, -1000, 141, 755, 149, -1000, - 996, 411, 290, -1000, -1000, -1000, -1000, -52, -1000, -1000, - 123, 141, 617, 897, -52, -3, -1000, 165, 116, 155, - -1000, 520, -1000, -1000, -52, 164, 617, -1000, -52, -1000, - -1000, + 723, -1000, 723, -54, -54, -54, -54, -54, -54, -54, + -54, -1000, -1000, -1000, -1000, -1000, 383, 455, 519, 494, + 409, 408, 500, -54, -54, -54, 519, 519, 519, 519, + 519, 868, 868, -54, 493, 868, 486, 311, 137, 253, + -1000, -1000, 147, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 355, 374, 519, 478, -7, 485, -1000, + 59, 488, 519, 519, -54, -10, 139, -1000, -1000, -1000, + 178, -54, -54, -54, 426, 986, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 137, -1000, 786, 58, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 868, 163, 91, 868, + -1000, -1000, 199, -1000, -1000, -1000, -1000, 87, 968, 281, + -26, -1000, 111, 3, 472, 59, 286, 286, 286, 868, + 521, -1000, 54, 343, 868, 868, 141, 519, 519, -1000, + 519, 472, 73, -1000, 482, -1000, -1000, -1000, -1000, 59, + 86, 404, -1000, 500, 868, 175, -1000, -1000, -1000, 499, + 723, 868, 868, 868, 272, 291, 306, 868, 868, 868, + 868, 868, 868, 868, -1000, 29, 46, -1000, 519, 253, + 223, 977, 67, 67, 273, 304, -1000, 1032, -1000, -1000, + 253, 633, 519, 499, 545, -1000, 381, 868, -1000, 147, + -1000, 147, 147, 977, -1000, -11, 423, 977, -1000, -1000, + 53, -1000, -1000, 868, 844, -1000, -13, 361, 977, -1000, + 67, 88, -1000, 486, -22, 104, 93, -1000, -1000, -1000, + 339, 359, 324, 336, 59, -1000, -1000, -1000, -1000, -1000, + 519, 472, 519, 155, 152, 519, -1000, 977, 147, -54, + -23, 230, 38, 128, 128, 322, 868, 67, 868, 67, + 67, 191, 191, -1000, -1000, -1000, 565, 1032, -1000, 868, + -1000, -1000, 43, 857, 234, 868, -1000, 786, -1000, -1000, + 67, 80, 74, 72, 383, 213, 633, -1000, -1000, 868, + -54, -54, 215, -1000, -54, 376, 365, 977, 302, -1000, + -1000, 302, 521, 519, 253, 977, -1000, 249, 326, 868, + 256, -1000, -1000, -1000, -32, 41, -37, 472, 519, 868, + 59, 333, 324, 331, -1000, 59, -1000, -1000, -1000, 40, + -39, 508, 519, 392, -1000, 519, 388, -54, -1000, 210, + 230, 723, 868, -1000, -1000, 998, -1000, 128, -1000, -1000, + -1000, 115, -1000, -1000, -1000, 208, 223, 868, 952, 278, + 102, -1000, 102, -1000, 102, -1000, -16, 232, -1000, 921, + -1000, -1000, 633, -1000, -1000, 868, 868, -1000, -1000, 36, + -1000, -1000, -1000, 403, 67, 76, 519, -1000, -1000, 977, + 548, 59, 327, 59, 514, -1000, 519, -1000, -1000, -1000, + 519, 519, 27, -40, 868, 20, 519, -1000, 246, 207, + 241, -1000, 901, 868, -1000, 977, 868, 67, 16, -1000, + 10, 7, -1000, 516, -54, 633, 204, 977, -1000, 160, + -1000, -1000, -1000, -1000, 67, -1000, -1000, -1000, 868, 66, + 514, 59, 548, -1000, -1000, -1000, 508, 519, 977, -1000, + -1000, -54, 245, 723, 1032, 977, -1000, -1000, -1000, -1000, + 6, -1000, 227, 723, 231, 39, -1000, 977, 519, 514, + -1000, -1000, -1000, -1000, -54, -1000, -1000, 200, 227, 633, + 868, -54, 167, 2, -1000, 244, 198, 239, -1000, 890, + -1000, 1, 383, 364, -1000, -54, 243, 633, -1000, -1000, + 868, -1000, -54, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 35, 28, 21, 525, 524, 523, 521, 518, 513, - 512, 487, 105, 97, 511, 42, 22, 510, 507, 34, - 504, 502, 49, 8, 260, 262, 135, 501, 0, 499, - 497, 496, 492, 490, 45, 484, 55, 479, 25, 477, - 20, 473, 471, 470, 468, 466, 19, 26, 27, 40, - 56, 4, 29, 51, 465, 464, 456, 24, 447, 445, - 444, 44, 9, 6, 443, 440, 37, 11, 5, 2, - 430, 434, 199, 178, 30, 429, 23, 128, 46, 47, - 426, 53, 335, 54, 417, 39, 10, 38, 52, 179, - 7, + 0, 20, 27, 36, 638, 637, 635, 626, 625, 624, + 623, 167, 64, 51, 621, 62, 29, 620, 619, 4, + 618, 41, 617, 47, 165, 297, 362, 38, 24, 616, + 614, 609, 608, 0, 606, 605, 594, 592, 589, 46, + 586, 23, 585, 580, 65, 578, 45, 576, 33, 575, + 572, 571, 568, 561, 19, 5, 56, 66, 8, 35, + 55, 560, 559, 558, 34, 553, 549, 548, 44, 2, + 10, 547, 545, 42, 18, 9, 7, 453, 534, 247, + 245, 39, 533, 37, 25, 54, 49, 529, 57, 428, + 59, 53, 22, 48, 70, 249, 6, } var yyR1 = [...]int{ @@ -562,24 +588,26 @@ var yyR1 = [...]int{ 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 12, 12, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, - 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 25, 25, 26, 26, 27, 84, 84, 84, - 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 31, 31, 31, 31, 31, 32, 32, 32, 33, - 33, 34, 34, 34, 35, 35, 36, 36, 36, 37, - 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, - 39, 39, 40, 40, 40, 41, 41, 42, 42, 43, - 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, - 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, - 54, 54, 54, 54, 55, 56, 57, 57, 58, 58, - 59, 60, 60, 61, 61, 62, 62, 63, 63, 63, - 63, 63, 64, 64, 65, 66, 66, 67, 67, 68, - 68, 69, 69, 70, 71, 72, 72, 73, 73, 74, - 75, 76, 77, 78, 78, 79, 80, 80, 81, 81, - 82, 82, 83, 83, 85, 85, 86, 86, 87, 87, - 87, 87, 88, 88, 89, 89, 90, 90, + 20, 21, 21, 22, 22, 23, 23, 23, 23, 23, + 23, 24, 24, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 26, 26, 27, 27, 28, + 28, 29, 29, 30, 30, 31, 31, 31, 32, 32, + 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 36, 36, 36, 36, 36, 37, 37, 37, 38, + 38, 39, 39, 39, 40, 40, 41, 42, 43, 43, + 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, + 46, 47, 47, 47, 47, 47, 48, 48, 48, 49, + 49, 49, 50, 50, 51, 52, 52, 53, 53, 54, + 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, + 59, 60, 60, 61, 61, 61, 61, 62, 63, 64, + 64, 65, 65, 66, 67, 67, 68, 68, 69, 69, + 70, 70, 70, 70, 70, 71, 71, 72, 73, 73, + 74, 74, 75, 75, 76, 76, 77, 78, 79, 79, + 80, 80, 81, 82, 83, 84, 85, 85, 86, 87, + 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, + 92, 93, 93, 93, 93, 94, 94, 95, 95, 96, + 96, } var yyR2 = [...]int{ @@ -588,137 +616,143 @@ var yyR2 = [...]int{ 3, 2, 2, 2, 6, 3, 3, 3, 5, 8, 9, 7, 9, 2, 8, 9, 2, 2, 5, 3, 4, 5, 4, 4, 4, 1, 1, 3, 0, 2, - 0, 2, 0, 3, 0, 2, 0, 3, 0, 2, - 0, 2, 1, 1, 1, 1, 1, 1, 1, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 3, 1, 1, 3, 2, 0, 1, 1, + 0, 2, 0, 3, 0, 2, 0, 3, 0, 3, + 4, 0, 2, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 1, 3, 1, + 3, 2, 4, 1, 1, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 4, 4, 6, 6, 4, 6, 4, 4, 4, 6, 4, 4, 6, 4, 2, 3, 3, 3, 3, 3, 3, 3, 2, 4, - 1, 0, 2, 2, 5, 7, 1, 2, 3, 1, - 1, 1, 1, 2, 3, 1, 1, 5, 5, 6, - 6, 4, 0, 2, 4, 1, 1, 1, 3, 5, - 0, 1, 0, 2, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 4, 2, - 5, 8, 4, 7, 6, 3, 1, 3, 4, 5, - 6, 6, 8, 1, 3, 1, 3, 0, 1, 1, - 2, 2, 5, 7, 7, 4, 2, 0, 2, 4, - 2, 0, 2, 1, 1, 1, 2, 1, 2, 1, - 1, 1, 1, 1, 3, 3, 1, 3, 1, 3, - 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, - 1, 1, 0, 1, 1, 1, 0, 1, + 1, 0, 2, 2, 5, 7, 8, 2, 0, 3, + 1, 2, 3, 1, 1, 1, 1, 2, 3, 1, + 1, 5, 5, 6, 6, 4, 0, 2, 4, 1, + 1, 1, 1, 3, 5, 0, 1, 0, 2, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 4, 2, 5, 8, 4, 7, 6, 3, 1, + 3, 4, 5, 6, 6, 8, 1, 3, 1, 3, + 0, 1, 1, 2, 2, 5, 7, 7, 4, 2, + 0, 2, 4, 2, 0, 2, 1, 1, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 3, 3, 1, + 3, 1, 3, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, + 1, } var yyChk = [...]int{ - -1000, -1, -3, -11, -54, -55, -58, -59, -60, -64, - -65, -5, -6, -7, -8, -10, -12, 19, 15, 17, - 25, 28, 95, -79, 89, 90, 80, 84, 85, 86, - 83, 72, 74, 93, 16, 94, -14, -13, -77, 13, - -28, 11, 106, -1, -90, 109, -90, -90, -90, -90, - -90, -90, -90, -19, 37, 20, -50, -36, -70, 4, - 14, -50, 29, 29, -81, -80, 11, -90, -90, -90, - -70, -70, -70, -70, -70, -24, -23, -22, -31, -29, - -28, -33, -43, -30, -32, -77, -79, 106, -70, -71, - -72, -73, -74, -75, -76, -35, 71, -25, 60, 64, - 5, 6, 101, 7, 9, 10, 68, 87, -24, -78, - -77, -90, 12, -24, -15, 14, 55, 56, 57, 98, - -82, 69, -11, -20, 43, 40, -70, 16, 108, -70, - 22, -49, -38, -36, -37, -39, 23, -28, 24, 14, - -70, -70, -90, 108, 98, 81, -90, -90, -90, 20, - 76, 97, 96, 99, 67, -83, -89, 100, 101, 102, - 103, 104, 63, 62, 64, -24, -47, -28, 105, 106, - -44, -24, 96, 99, -83, -89, -28, -24, -72, -73, - 106, 78, 61, 108, 99, -90, -16, 18, -49, -88, - 58, -88, -88, -24, -52, -42, -41, -24, 102, 107, - -21, 44, 6, -48, -27, -24, 21, 106, -11, -57, - -56, -23, -70, -50, -70, -16, -85, 54, -87, 51, - 108, 46, 48, 49, 50, -70, 22, -49, 106, 26, - 27, 35, -81, -24, 82, -78, -77, -1, -24, -24, - -24, -83, 65, 61, 66, 59, 58, -24, -24, -24, - -24, -24, -24, -24, 107, 108, 107, -70, -34, -82, - -53, 75, -25, 106, -28, -25, 65, 61, 59, 58, - -34, -2, -4, -3, -9, 72, 91, 92, -70, -78, - -22, -17, 38, -24, -13, -12, -13, -13, 108, 22, - 6, 108, -84, 41, 42, -26, -25, -46, -23, -15, - 108, 99, 45, -85, -87, -86, 47, 45, -49, -70, - -16, -51, -70, -61, 106, -70, -23, 106, -23, -11, - -90, -67, -66, 77, 73, -74, -76, -24, -25, -24, - -25, -25, -47, -24, 107, 102, -47, -45, -53, 77, - -24, -25, 106, -28, 106, -28, 106, -28, -19, 79, - -2, -24, -90, -90, 78, -90, -18, 39, 40, -52, - -70, -48, 108, 107, 108, -16, -57, -24, -38, 45, - -86, 45, -38, 107, 108, -63, 30, 31, 32, 33, - -62, -61, 34, -46, 36, -90, 79, -67, -66, -1, - -24, 62, 79, -24, 76, 62, -26, -28, -26, -26, - 107, 88, 74, 76, -2, -24, -47, -26, 21, -11, - -46, -40, 52, 53, -38, 45, -38, -51, -23, -23, - 107, 108, -24, 107, -70, 72, 79, 76, -24, -24, - -25, 107, 107, 107, 5, -90, -2, -3, 79, -26, - -24, 106, -38, -40, -63, -62, -90, 72, -1, 107, - -69, -68, 77, 73, 74, -51, -90, 79, -69, -68, - -2, -24, -90, 107, 72, 79, 76, -90, 72, -2, - -90, + -1000, -1, -3, -11, -61, -62, -65, -66, -67, -71, + -72, -5, -6, -7, -8, -10, -12, 19, 15, 17, + 25, 28, 100, -86, 94, 95, 83, 87, 88, 89, + 86, 75, 77, 98, 16, 99, -14, -13, -84, 13, + -33, 11, 111, -1, -96, 114, -96, -96, -96, -96, + -96, -96, -96, -19, 37, 20, -57, -44, -77, 4, + 14, -57, 29, 29, -88, -87, 11, -96, -96, -96, + -77, -77, -77, -77, -77, -25, -24, -23, -36, -34, + -33, -38, -51, -35, -37, -84, -86, 111, -77, -78, + -79, -80, -81, -82, -83, -40, 74, -26, 62, 66, + 5, 6, 106, 7, 9, 10, 70, 90, -25, -85, + -84, -96, 12, -25, -15, 14, 57, 58, 59, 103, + -89, 72, -11, -20, 43, 40, -77, 16, 113, -77, + 22, -56, -46, -44, -45, -47, 23, -33, 24, 14, + -77, -77, -96, 113, 103, 84, -96, -96, -96, 20, + 79, 102, 101, 104, 69, -90, -95, 105, 106, 107, + 108, 109, 65, 64, 66, -25, -55, -33, 110, 111, + -52, -25, 101, 104, -90, -95, -33, -25, -79, -80, + 111, 81, 63, 113, 104, -96, -16, 18, -56, -94, + 60, -94, -94, -25, -59, -50, -49, -25, -41, 107, + -77, 112, -22, 44, -25, -28, -29, -30, -25, -41, + 21, 111, -11, -64, -63, -24, -77, -57, -77, -16, + -91, 56, -93, 53, 113, 48, 50, 51, 52, -77, + 22, -56, 111, 26, 27, 35, -88, -25, 85, -85, + -84, -1, -25, -25, -25, -90, 67, 63, 68, 61, + 60, -25, -25, -25, -25, -25, -25, -25, 112, 113, + 112, -77, -39, -89, -60, 78, -26, 111, -33, -26, + 67, 63, 61, 60, -39, -2, -4, -3, -9, 75, + 96, 97, -77, -85, -23, -17, 38, -25, -13, -12, + -13, -13, 113, 22, 111, -25, -21, 46, 73, 113, + -31, 41, 42, -27, -26, -54, -24, -15, 113, 104, + 47, -91, -93, -92, 49, 47, -56, -77, -16, -58, + -77, -68, 111, -77, -24, 111, -24, -11, -96, -74, + -73, 80, 76, -81, -83, -25, -26, -25, -26, -26, + -55, -25, 112, 107, -55, -53, -60, 80, -25, -26, + 111, -33, 111, -33, 111, -33, -19, 82, -2, -25, + -96, -96, 81, -96, -18, 39, 40, -59, -77, -39, + -21, 45, -28, 71, 113, 112, 113, -16, -64, -25, + -46, 47, -92, 47, -46, 112, 113, -70, 30, 31, + 32, 33, -69, -68, 34, -54, 36, -96, 82, -74, + -73, -1, -25, 64, 82, -25, 79, 64, -27, -33, + -27, -27, 112, 91, 77, 79, -2, -25, -55, 112, + -32, 30, 31, -27, 21, -11, -54, -48, 54, 55, + -46, 47, -46, -58, -24, -24, 112, 113, -25, 112, + -77, 75, 82, 79, -25, -25, -26, 112, 112, 112, + 5, -96, -2, -3, 82, 93, -27, -25, 111, -46, + -48, -70, -69, -96, 75, -1, 112, -76, -75, 80, + 76, 77, 111, -58, -96, 82, -76, -75, -2, -25, + -96, -42, -43, 92, 112, 75, 82, 79, 112, -19, + 40, -96, 75, -2, -55, -96, } var yyDef = [...]int{ - 1, -2, 1, 236, 236, 236, 236, 236, 236, 236, - 236, 13, 14, 15, 16, 17, -2, 0, 0, 0, - 0, 0, 0, 236, 236, 236, 0, 0, 0, 0, - 0, 0, 0, 236, 0, 0, 48, 0, 0, 220, - 46, 212, 0, 2, 5, 237, 6, 7, 8, 9, - 10, 11, 12, 58, 0, 0, 0, 162, 126, 203, - 0, 0, 0, 0, 236, 218, 216, 21, 22, 23, - 0, 236, 236, 236, 0, 222, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 0, 68, 62, - 63, 64, 65, 66, 67, 120, 150, 222, 0, 0, - 204, 205, 0, 207, 209, 210, 211, 0, 222, 0, - 79, 33, 0, -2, 50, 0, 232, 232, 232, 0, - 0, 221, 0, 60, 0, 0, 0, 0, 0, 127, - 0, 50, -2, 131, 132, 135, 136, 129, 130, 0, + 1, -2, 1, 249, 249, 249, 249, 249, 249, 249, + 249, 13, 14, 15, 16, 17, -2, 0, 0, 0, + 0, 0, 0, 249, 249, 249, 0, 0, 0, 0, + 0, 0, 0, 249, 0, 0, 48, 0, 0, 233, + 46, 225, 0, 2, 5, 250, 6, 7, 8, 9, + 10, 11, 12, 58, 0, 0, 0, 175, 140, 216, + 0, 0, 0, 0, 249, 231, 229, 21, 22, 23, + 0, 249, 249, 249, 0, 235, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 0, 71, 65, + 66, 67, 68, 69, 70, 130, 165, 235, 0, 0, + 217, 218, 0, 220, 222, 223, 224, 0, 235, 0, + 82, 33, 0, -2, 50, 0, 245, 245, 245, 0, + 0, 234, 0, 63, 0, 0, 0, 0, 0, 141, + 0, 50, -2, 145, 146, 149, 150, 143, 144, 0, 0, 0, 20, 0, 0, 0, 25, 26, 27, 0, - 1, 0, 234, 235, 222, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 223, 222, 0, -2, 0, -2, - 0, -2, 234, 235, 0, 0, 110, 118, 206, 208, + 1, 0, 247, 248, 235, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, 0, -2, 0, -2, + 0, -2, 247, 248, 0, 0, 120, 128, 219, 221, -2, 3, 0, 0, 0, 39, 52, 0, 49, 0, - 233, 0, 0, 215, 47, 166, 147, -2, 146, 90, - 40, 0, 59, 57, 158, -2, 0, 0, 172, 48, - 176, 0, 68, 163, 128, 178, 0, -2, 226, 0, - 0, 225, 229, 230, 231, 133, 0, 50, 0, 0, - 0, 0, 219, -2, 0, 236, 213, 197, 91, -2, - -2, 0, 0, 0, 0, 0, 0, 111, 112, 113, - 114, 115, 116, 117, 81, 0, 82, 69, 0, 0, - 152, 0, 93, 0, 83, 95, 0, 0, 0, 0, - 56, 0, 3, 18, 19, 0, 236, 236, 0, 214, - 236, 54, 0, -2, 42, 45, 43, 44, 0, 0, - 61, 0, 86, 88, 89, 170, 84, 0, 154, 50, - 0, 0, 0, 0, 226, 0, 227, 0, 161, 134, - 179, 0, 164, 187, 0, 183, 192, 0, 0, 236, - 28, 0, 197, 1, 0, 96, 97, 222, 100, -2, - 104, 107, 157, -2, 119, 122, 123, 0, 169, 0, - 222, 0, 0, 102, 0, 106, 0, 109, 0, 0, - 4, 222, 36, 37, 3, 38, 41, 0, 0, 167, - 148, 159, 0, 0, 0, 174, 177, -2, 142, 0, - 0, 0, 141, 180, 0, 181, 188, 189, 0, 0, - 0, 185, 0, 0, 0, 24, 0, 0, 196, 198, - 222, 0, 149, -2, 0, 0, 0, -2, 0, 0, - 124, 0, 236, 1, 0, -2, 53, 85, 0, 173, - 155, 137, 0, 0, 138, 0, 142, 165, 190, 191, - 187, 0, -2, 193, 194, 236, 0, 1, 98, -2, - 99, 101, 105, 108, 0, 31, 201, -2, 0, 171, - -2, 0, 140, 139, 182, 186, 29, 236, 195, 125, - 0, 201, 3, 0, 236, 0, 30, 0, 0, 200, - 202, 222, 32, 144, 236, 0, 3, 34, 236, 199, - 35, + 246, 0, 0, 228, 47, 179, 162, -2, 160, 161, + 71, 100, 40, 0, -2, 57, 89, 95, -2, 94, + 0, 0, 185, 48, 189, 0, 71, 176, 142, 191, + 0, -2, 239, 0, 0, 238, 242, 243, 244, 147, + 0, 50, 0, 0, 0, 0, 232, -2, 0, 249, + 226, 210, 101, -2, -2, 0, 0, 0, 0, 0, + 0, 121, 122, 123, 124, 125, 126, 127, 84, 0, + 85, 72, 0, 0, 167, 0, 103, 0, 86, 105, + 0, 0, 0, 0, 56, 0, 3, 18, 19, 0, + 249, 249, 0, 227, 249, 54, 0, -2, 42, 45, + 43, 44, 0, 0, -2, -2, 59, 61, 0, 0, + 91, 96, 97, 183, 87, 0, 169, 50, 0, 0, + 0, 0, 239, 0, 240, 0, 174, 148, 192, 0, + 177, 200, 0, 196, 205, 0, 0, 249, 28, 0, + 210, 1, 0, 106, 107, 235, 110, -2, 114, 117, + 172, -2, 129, 132, 133, 0, 182, 0, 235, 0, + 0, 112, 0, 116, 0, 119, 0, 0, 4, 235, + 36, 37, 3, 38, 41, 0, 0, 180, 163, 0, + 60, 62, 90, 0, 0, 0, 0, 187, 190, -2, + 156, 0, 0, 0, 155, 193, 0, 194, 201, 202, + 0, 0, 0, 198, 0, 0, 0, 24, 0, 0, + 209, 211, 235, 0, 164, -2, 0, 0, 0, -2, + 0, 0, 134, 0, 249, 1, 0, -2, 53, 129, + 92, 98, 99, 88, 0, 186, 170, 151, 0, 0, + 152, 0, 156, 178, 203, 204, 200, 0, -2, 206, + 207, 249, 0, 1, 108, -2, 109, 111, 115, 118, + 0, 31, 214, -2, 0, 0, 184, -2, 0, 154, + 153, 195, 199, 29, 249, 208, 135, 0, 214, 3, + 0, 249, 138, 0, 30, 0, 0, 213, 215, 235, + 32, 0, 56, 0, 158, 249, 0, 3, 136, 137, + 0, 34, 249, 212, 139, 35, } 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, 3, 3, 3, 3, 104, 3, 3, - 106, 107, 102, 100, 108, 101, 105, 103, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 109, - 3, 99, + 3, 3, 3, 3, 3, 3, 3, 109, 3, 3, + 111, 112, 107, 105, 113, 106, 110, 108, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 114, + 3, 104, } var yyTok2 = [...]int{ @@ -731,7 +765,8 @@ var yyTok2 = [...]int{ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, } var yyTok3 = [...]int{ 0, @@ -1076,245 +1111,245 @@ yydefault: case 1: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:148 + //line parser.y:154 { yyVAL.program = nil yylex.(*Lexer).program = yyVAL.program } case 2: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:153 + //line parser.y:159 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[2].program...) yylex.(*Lexer).program = yyVAL.program } case 3: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:160 + //line parser.y:166 { yyVAL.program = nil yylex.(*Lexer).program = yyVAL.program } case 4: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:165 + //line parser.y:171 { yyVAL.program = append([]Statement{yyDollar[1].statement}, yyDollar[2].program...) yylex.(*Lexer).program = yyVAL.program } case 5: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:172 + //line parser.y:178 { yyVAL.statement = yyDollar[1].expression } case 6: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:176 + //line parser.y:182 { yyVAL.statement = yyDollar[1].expression } case 7: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:180 + //line parser.y:186 { yyVAL.statement = yyDollar[1].expression } case 8: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:184 + //line parser.y:190 { yyVAL.statement = yyDollar[1].expression } case 9: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:188 + //line parser.y:194 { yyVAL.statement = yyDollar[1].expression } case 10: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:192 + //line parser.y:198 { yyVAL.statement = yyDollar[1].expression } case 11: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:196 + //line parser.y:202 { yyVAL.statement = yyDollar[1].expression } case 12: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:200 + //line parser.y:206 { yyVAL.statement = yyDollar[1].expression } case 13: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:204 + //line parser.y:210 { yyVAL.statement = yyDollar[1].statement } case 14: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:208 + //line parser.y:214 { yyVAL.statement = yyDollar[1].statement } case 15: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:212 + //line parser.y:218 { yyVAL.statement = yyDollar[1].statement } case 16: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:216 + //line parser.y:222 { yyVAL.statement = yyDollar[1].statement } case 17: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:220 + //line parser.y:226 { yyVAL.statement = yyDollar[1].statement } case 18: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:226 + //line parser.y:232 { yyVAL.statement = yyDollar[1].statement } case 19: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:230 + //line parser.y:236 { yyVAL.statement = yyDollar[1].statement } case 20: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:236 + //line parser.y:242 { yyVAL.statement = VariableDeclaration{Assignments: yyDollar[2].expressions} } case 21: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:240 + //line parser.y:246 { yyVAL.statement = yyDollar[1].expression } case 22: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:246 + //line parser.y:252 { yyVAL.statement = TransactionControl{Token: yyDollar[1].token.Token} } case 23: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:250 + //line parser.y:256 { yyVAL.statement = TransactionControl{Token: yyDollar[1].token.Token} } case 24: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:256 + //line parser.y:262 { yyVAL.statement = CursorDeclaration{Cursor: yyDollar[2].identifier, Query: yyDollar[5].expression.(SelectQuery)} } case 25: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:260 + //line parser.y:266 { yyVAL.statement = OpenCursor{Cursor: yyDollar[2].identifier} } case 26: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:264 + //line parser.y:270 { yyVAL.statement = CloseCursor{Cursor: yyDollar[2].identifier} } case 27: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:268 + //line parser.y:274 { yyVAL.statement = DisposeCursor{Cursor: yyDollar[2].identifier} } case 28: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:272 + //line parser.y:278 { yyVAL.statement = FetchCursor{Cursor: yyDollar[2].identifier, Variables: yyDollar[4].variables} } case 29: yyDollar = yyS[yypt-8 : yypt+1] - //line parser.y:278 + //line parser.y:284 { yyVAL.statement = If{Condition: yyDollar[2].expression, Statements: yyDollar[4].program, Else: yyDollar[5].procexpr} } case 30: yyDollar = yyS[yypt-9 : yypt+1] - //line parser.y:282 + //line parser.y:288 { yyVAL.statement = If{Condition: yyDollar[2].expression, Statements: yyDollar[4].program, ElseIf: yyDollar[5].procexprs, Else: yyDollar[6].procexpr} } case 31: yyDollar = yyS[yypt-7 : yypt+1] - //line parser.y:286 + //line parser.y:292 { yyVAL.statement = While{Condition: yyDollar[2].expression, Statements: yyDollar[4].program} } case 32: yyDollar = yyS[yypt-9 : yypt+1] - //line parser.y:290 + //line parser.y:296 { yyVAL.statement = WhileInCursor{Variables: yyDollar[2].variables, Cursor: yyDollar[4].identifier, Statements: yyDollar[6].program} } case 33: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:294 + //line parser.y:300 { yyVAL.statement = FlowControl{Token: yyDollar[1].token.Token} } case 34: yyDollar = yyS[yypt-8 : yypt+1] - //line parser.y:300 + //line parser.y:306 { yyVAL.statement = If{Condition: yyDollar[2].expression, Statements: yyDollar[4].program, Else: yyDollar[5].procexpr} } case 35: yyDollar = yyS[yypt-9 : yypt+1] - //line parser.y:304 + //line parser.y:310 { yyVAL.statement = If{Condition: yyDollar[2].expression, Statements: yyDollar[4].program, ElseIf: yyDollar[5].procexprs, Else: yyDollar[6].procexpr} } case 36: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:308 + //line parser.y:314 { yyVAL.statement = FlowControl{Token: yyDollar[1].token.Token} } case 37: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:312 + //line parser.y:318 { yyVAL.statement = FlowControl{Token: yyDollar[1].token.Token} } case 38: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:318 + //line parser.y:324 { yyVAL.statement = SetFlag{Name: yyDollar[2].token.Literal, Value: yyDollar[4].primary} } case 39: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:322 + //line parser.y:328 { yyVAL.statement = Print{Value: yyDollar[2].expression} } case 40: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:328 + //line parser.y:334 { yyVAL.expression = SelectQuery{ SelectEntity: yyDollar[1].expression, @@ -1325,7 +1360,7 @@ yydefault: } case 41: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:339 + //line parser.y:345 { yyVAL.expression = SelectEntity{ SelectClause: yyDollar[1].expression, @@ -1337,7 +1372,7 @@ yydefault: } case 42: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:349 + //line parser.y:355 { yyVAL.expression = SelectSet{ LHS: yyDollar[1].expression, @@ -1348,7 +1383,7 @@ yydefault: } case 43: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:358 + //line parser.y:364 { yyVAL.expression = SelectSet{ LHS: yyDollar[1].expression, @@ -1359,7 +1394,7 @@ yydefault: } case 44: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:367 + //line parser.y:373 { yyVAL.expression = SelectSet{ LHS: yyDollar[1].expression, @@ -1370,283 +1405,343 @@ yydefault: } case 45: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:378 + //line parser.y:384 { yyVAL.expression = yyDollar[1].expression } case 46: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:382 + //line parser.y:388 { yyVAL.expression = yyDollar[1].expression } case 47: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:388 + //line parser.y:394 { yyVAL.expression = SelectClause{Select: yyDollar[1].token.Literal, Distinct: yyDollar[2].token, Fields: yyDollar[3].expressions} } case 48: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:394 + //line parser.y:400 { yyVAL.expression = nil } case 49: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:398 + //line parser.y:404 { yyVAL.expression = FromClause{From: yyDollar[1].token.Literal, Tables: yyDollar[2].expressions} } case 50: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:404 + //line parser.y:410 { yyVAL.expression = nil } case 51: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:408 + //line parser.y:414 { yyVAL.expression = WhereClause{Where: yyDollar[1].token.Literal, Filter: yyDollar[2].expression} } case 52: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:414 + //line parser.y:420 { yyVAL.expression = nil } case 53: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:418 + //line parser.y:424 { yyVAL.expression = GroupByClause{GroupBy: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Items: yyDollar[3].expressions} } case 54: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:424 + //line parser.y:430 { yyVAL.expression = nil } case 55: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:428 + //line parser.y:434 { yyVAL.expression = HavingClause{Having: yyDollar[1].token.Literal, Filter: yyDollar[2].expression} } case 56: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:434 + //line parser.y:440 { yyVAL.expression = nil } case 57: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:438 + //line parser.y:444 { yyVAL.expression = OrderByClause{OrderBy: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Items: yyDollar[3].expressions} } case 58: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:444 + //line parser.y:450 { yyVAL.expression = nil } case 59: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:448 + yyDollar = yyS[yypt-3 : yypt+1] + //line parser.y:454 { - yyVAL.expression = LimitClause{Limit: yyDollar[1].token.Literal, Number: StrToInt64(yyDollar[2].token.Literal)} + yyVAL.expression = LimitClause{Limit: yyDollar[1].token.Literal, Value: yyDollar[2].expression, With: yyDollar[3].expression} } case 60: - yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:454 + yyDollar = yyS[yypt-4 : yypt+1] + //line parser.y:458 { - yyVAL.expression = nil + yyVAL.expression = LimitClause{Limit: yyDollar[1].token.Literal, Value: yyDollar[2].expression, Percent: yyDollar[3].token.Literal, With: yyDollar[4].expression} } case 61: - yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:458 + yyDollar = yyS[yypt-0 : yypt+1] + //line parser.y:464 { - yyVAL.expression = OffsetClause{Offset: yyDollar[1].token.Literal, Number: StrToInt64(yyDollar[2].token.Literal)} + yyVAL.expression = nil } case 62: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:464 + yyDollar = yyS[yypt-2 : yypt+1] + //line parser.y:468 { - yyVAL.primary = yyDollar[1].text + yyVAL.expression = LimitWith{With: yyDollar[1].token.Literal, Type: yyDollar[2].token} } case 63: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:468 + yyDollar = yyS[yypt-0 : yypt+1] + //line parser.y:474 { - yyVAL.primary = yyDollar[1].integer + yyVAL.expression = nil } case 64: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:472 + yyDollar = yyS[yypt-2 : yypt+1] + //line parser.y:478 { - yyVAL.primary = yyDollar[1].float + yyVAL.expression = OffsetClause{Offset: yyDollar[1].token.Literal, Value: yyDollar[2].expression} } case 65: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:476 + //line parser.y:484 { - yyVAL.primary = yyDollar[1].ternary + yyVAL.primary = yyDollar[1].text } case 66: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:480 + //line parser.y:488 { - yyVAL.primary = yyDollar[1].datetime + yyVAL.primary = yyDollar[1].integer } case 67: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:484 + //line parser.y:492 { - yyVAL.primary = yyDollar[1].null + yyVAL.primary = yyDollar[1].float } case 68: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:490 + //line parser.y:496 { - yyVAL.expression = FieldReference{Column: yyDollar[1].identifier} + yyVAL.primary = yyDollar[1].ternary } case 69: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:494 + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:500 { - yyVAL.expression = FieldReference{View: yyDollar[1].identifier, Column: yyDollar[3].identifier} + yyVAL.primary = yyDollar[1].datetime } case 70: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:500 + //line parser.y:504 { - yyVAL.expression = yyDollar[1].expression + yyVAL.primary = yyDollar[1].null } case 71: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:504 + //line parser.y:510 { - yyVAL.expression = yyDollar[1].primary + yyVAL.expression = FieldReference{Column: yyDollar[1].identifier} } case 72: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:508 + yyDollar = yyS[yypt-3 : yypt+1] + //line parser.y:514 { - yyVAL.expression = yyDollar[1].expression + yyVAL.expression = FieldReference{View: yyDollar[1].identifier, Column: yyDollar[3].identifier} } case 73: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:512 + //line parser.y:520 { yyVAL.expression = yyDollar[1].expression } case 74: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:516 + //line parser.y:524 { - yyVAL.expression = yyDollar[1].expression + yyVAL.expression = yyDollar[1].primary } case 75: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:520 + //line parser.y:528 { yyVAL.expression = yyDollar[1].expression } case 76: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:524 + //line parser.y:532 { yyVAL.expression = yyDollar[1].expression } case 77: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:528 + //line parser.y:536 { yyVAL.expression = yyDollar[1].expression } case 78: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:532 + //line parser.y:540 { yyVAL.expression = yyDollar[1].expression } case 79: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:536 + //line parser.y:544 { - yyVAL.expression = yyDollar[1].variable + yyVAL.expression = yyDollar[1].expression } case 80: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:540 + //line parser.y:548 { yyVAL.expression = yyDollar[1].expression } case 81: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:552 + { + yyVAL.expression = yyDollar[1].expression + } + case 82: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:556 + { + yyVAL.expression = yyDollar[1].variable + } + case 83: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:560 + { + yyVAL.expression = yyDollar[1].expression + } + case 84: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:544 + //line parser.y:564 { yyVAL.expression = Parentheses{Expr: yyDollar[2].expression} } - case 82: + case 85: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:550 + //line parser.y:570 { yyVAL.expression = RowValue{Value: ValueList{Values: yyDollar[2].expressions}} } - case 83: + case 86: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:554 + //line parser.y:574 { yyVAL.expression = RowValue{Value: yyDollar[1].expression} } - case 84: + case 87: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:560 + //line parser.y:580 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 85: + case 88: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:564 + //line parser.y:584 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 86: + case 89: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:590 + { + yyVAL.expressions = []Expression{yyDollar[1].expression} + } + case 90: + yyDollar = yyS[yypt-3 : yypt+1] + //line parser.y:594 + { + yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) + } + case 91: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:570 + //line parser.y:600 { - yyVAL.expression = OrderItem{Item: yyDollar[1].expression, Direction: yyDollar[2].token} + yyVAL.expression = OrderItem{Value: yyDollar[1].expression, Direction: yyDollar[2].token} } - case 87: + case 92: + yyDollar = yyS[yypt-4 : yypt+1] + //line parser.y:604 + { + yyVAL.expression = OrderItem{Value: yyDollar[1].expression, Direction: yyDollar[2].token, Nulls: yyDollar[3].token.Literal, Position: yyDollar[4].token} + } + case 93: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:610 + { + yyVAL.expression = yyDollar[1].expression + } + case 94: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:614 + { + yyVAL.expression = yyDollar[1].expression + } + case 95: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:576 + //line parser.y:620 { yyVAL.token = Token{} } - case 88: + case 96: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:580 + //line parser.y:624 { yyVAL.token = yyDollar[1].token } - case 89: + case 97: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:584 + //line parser.y:628 { yyVAL.token = yyDollar[1].token } - case 90: + case 98: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:634 + { + yyVAL.token = yyDollar[1].token + } + case 99: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:638 + { + yyVAL.token = yyDollar[1].token + } + case 100: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:590 + //line parser.y:644 { yyVAL.expression = Subquery{Query: yyDollar[2].expression.(SelectQuery)} } - case 91: + case 101: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:596 + //line parser.y:650 { var item1 []Expression var item2 []Expression @@ -1667,883 +1762,901 @@ yydefault: yyVAL.expression = Concat{Items: append(item1, item2...)} } - case 92: + case 102: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:619 + //line parser.y:673 { yyVAL.expression = Comparison{LHS: yyDollar[1].expression, Operator: yyDollar[2].token, RHS: yyDollar[3].expression} } - case 93: + case 103: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:623 + //line parser.y:677 { yyVAL.expression = Comparison{LHS: yyDollar[1].expression, Operator: yyDollar[2].token, RHS: yyDollar[3].expression} } - case 94: + case 104: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:627 + //line parser.y:681 { yyVAL.expression = Comparison{LHS: yyDollar[1].expression, Operator: Token{Token: COMPARISON_OP, Literal: "="}, RHS: yyDollar[3].expression} } - case 95: + case 105: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:631 + //line parser.y:685 { yyVAL.expression = Comparison{LHS: yyDollar[1].expression, Operator: Token{Token: COMPARISON_OP, Literal: "="}, RHS: yyDollar[3].expression} } - case 96: + case 106: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:635 + //line parser.y:689 { yyVAL.expression = Is{Is: yyDollar[2].token.Literal, LHS: yyDollar[1].expression, RHS: yyDollar[4].ternary, Negation: yyDollar[3].token} } - case 97: + case 107: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:639 + //line parser.y:693 { yyVAL.expression = Is{Is: yyDollar[2].token.Literal, LHS: yyDollar[1].expression, RHS: yyDollar[4].null, Negation: yyDollar[3].token} } - case 98: + case 108: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:643 + //line parser.y:697 { yyVAL.expression = Between{Between: yyDollar[3].token.Literal, And: yyDollar[5].token.Literal, LHS: yyDollar[1].expression, Low: yyDollar[4].expression, High: yyDollar[6].expression, Negation: yyDollar[2].token} } - case 99: + case 109: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:647 + //line parser.y:701 { yyVAL.expression = Between{Between: yyDollar[3].token.Literal, And: yyDollar[5].token.Literal, LHS: yyDollar[1].expression, Low: yyDollar[4].expression, High: yyDollar[6].expression, Negation: yyDollar[2].token} } - case 100: + case 110: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:651 + //line parser.y:705 { yyVAL.expression = In{In: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Values: yyDollar[4].expression, Negation: yyDollar[2].token} } - case 101: + case 111: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:655 + //line parser.y:709 { yyVAL.expression = In{In: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Values: RowValueList{RowValues: yyDollar[5].expressions}, Negation: yyDollar[2].token} } - case 102: + case 112: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:659 + //line parser.y:713 { yyVAL.expression = In{In: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Values: yyDollar[4].expression, Negation: yyDollar[2].token} } - case 103: + case 113: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:663 + //line parser.y:717 { yyVAL.expression = Like{Like: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Pattern: yyDollar[4].expression, Negation: yyDollar[2].token} } - case 104: + case 114: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:667 + //line parser.y:721 { yyVAL.expression = Any{Any: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: yyDollar[4].expression} } - case 105: + case 115: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:671 + //line parser.y:725 { yyVAL.expression = Any{Any: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: RowValueList{RowValues: yyDollar[5].expressions}} } - case 106: + case 116: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:675 + //line parser.y:729 { yyVAL.expression = Any{Any: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: yyDollar[4].expression} } - case 107: + case 117: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:679 + //line parser.y:733 { yyVAL.expression = All{All: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: yyDollar[4].expression} } - case 108: + case 118: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:683 + //line parser.y:737 { yyVAL.expression = All{All: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: RowValueList{RowValues: yyDollar[5].expressions}} } - case 109: + case 119: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:687 + //line parser.y:741 { yyVAL.expression = All{All: yyDollar[3].token.Literal, LHS: yyDollar[1].expression, Operator: yyDollar[2].token, Values: yyDollar[4].expression} } - case 110: + case 120: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:691 + //line parser.y:745 { yyVAL.expression = Exists{Exists: yyDollar[1].token.Literal, Query: yyDollar[2].expression.(Subquery)} } - case 111: + case 121: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:697 + //line parser.y:751 { yyVAL.expression = Arithmetic{LHS: yyDollar[1].expression, Operator: int('+'), RHS: yyDollar[3].expression} } - case 112: + case 122: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:701 + //line parser.y:755 { yyVAL.expression = Arithmetic{LHS: yyDollar[1].expression, Operator: int('-'), RHS: yyDollar[3].expression} } - case 113: + case 123: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:705 + //line parser.y:759 { yyVAL.expression = Arithmetic{LHS: yyDollar[1].expression, Operator: int('*'), RHS: yyDollar[3].expression} } - case 114: + case 124: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:709 + //line parser.y:763 { yyVAL.expression = Arithmetic{LHS: yyDollar[1].expression, Operator: int('/'), RHS: yyDollar[3].expression} } - case 115: + case 125: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:713 + //line parser.y:767 { yyVAL.expression = Arithmetic{LHS: yyDollar[1].expression, Operator: int('%'), RHS: yyDollar[3].expression} } - case 116: + case 126: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:719 + //line parser.y:773 { yyVAL.expression = Logic{LHS: yyDollar[1].expression, Operator: yyDollar[2].token, RHS: yyDollar[3].expression} } - case 117: + case 127: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:723 + //line parser.y:777 { yyVAL.expression = Logic{LHS: yyDollar[1].expression, Operator: yyDollar[2].token, RHS: yyDollar[3].expression} } - case 118: + case 128: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:727 + //line parser.y:781 { yyVAL.expression = Logic{LHS: nil, Operator: yyDollar[1].token, RHS: yyDollar[2].expression} } - case 119: + case 129: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:733 + //line parser.y:787 { yyVAL.expression = Function{Name: yyDollar[1].identifier.Literal, Option: yyDollar[3].expression.(Option)} } - case 120: + case 130: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:737 + //line parser.y:791 { yyVAL.expression = yyDollar[1].expression } - case 121: + case 131: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:743 + //line parser.y:797 { yyVAL.expression = Option{} } - case 122: + case 132: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:747 + //line parser.y:801 { yyVAL.expression = Option{Distinct: yyDollar[1].token, Args: []Expression{AllColumns{}}} } - case 123: + case 133: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:751 + //line parser.y:805 { yyVAL.expression = Option{Distinct: yyDollar[1].token, Args: yyDollar[2].expressions} } - case 124: + case 134: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:757 + //line parser.y:811 { yyVAL.expression = GroupConcat{GroupConcat: yyDollar[1].token.Literal, Option: yyDollar[3].expression.(Option), OrderBy: yyDollar[4].expression} } - case 125: + case 135: yyDollar = yyS[yypt-7 : yypt+1] - //line parser.y:761 + //line parser.y:815 { yyVAL.expression = GroupConcat{GroupConcat: yyDollar[1].token.Literal, Option: yyDollar[3].expression.(Option), OrderBy: yyDollar[4].expression, SeparatorLit: yyDollar[5].token.Literal, Separator: yyDollar[6].token.Literal} } - case 126: + case 136: + yyDollar = yyS[yypt-8 : yypt+1] + //line parser.y:821 + { + yyVAL.expression = AnalyticFunction{Name: yyDollar[1].identifier.Literal, Option: yyDollar[3].expression.(Option), Over: yyDollar[5].token.Literal, AnalyticClause: yyDollar[7].expression.(AnalyticClause)} + } + case 137: + yyDollar = yyS[yypt-2 : yypt+1] + //line parser.y:827 + { + yyVAL.expression = AnalyticClause{Partition: yyDollar[1].expression, OrderByClause: yyDollar[2].expression} + } + case 138: + yyDollar = yyS[yypt-0 : yypt+1] + //line parser.y:833 + { + yyVAL.expression = nil + } + case 139: + yyDollar = yyS[yypt-3 : yypt+1] + //line parser.y:837 + { + yyVAL.expression = Partition{PartitionBy: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Values: yyDollar[3].expressions} + } + case 140: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:767 + //line parser.y:843 { yyVAL.expression = Table{Object: yyDollar[1].identifier} } - case 127: + case 141: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:771 + //line parser.y:847 { yyVAL.expression = Table{Object: yyDollar[1].identifier, Alias: yyDollar[2].identifier} } - case 128: + case 142: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:775 + //line parser.y:851 { yyVAL.expression = Table{Object: yyDollar[1].identifier, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 129: + case 143: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:781 + //line parser.y:857 { yyVAL.expression = yyDollar[1].expression } - case 130: + case 144: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:785 + //line parser.y:861 { yyVAL.expression = Stdin{Stdin: yyDollar[1].token.Literal} } - case 131: + case 145: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:791 + //line parser.y:867 { yyVAL.expression = yyDollar[1].expression } - case 132: + case 146: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:795 + //line parser.y:871 { yyVAL.expression = Table{Object: yyDollar[1].expression} } - case 133: + case 147: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:799 + //line parser.y:875 { yyVAL.expression = Table{Object: yyDollar[1].expression, Alias: yyDollar[2].identifier} } - case 134: + case 148: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:803 + //line parser.y:879 { yyVAL.expression = Table{Object: yyDollar[1].expression, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 135: + case 149: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:807 + //line parser.y:883 { yyVAL.expression = Table{Object: yyDollar[1].expression} } - case 136: + case 150: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:811 + //line parser.y:887 { yyVAL.expression = Table{Object: Dual{Dual: yyDollar[1].token.Literal}} } - case 137: + case 151: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:817 + //line parser.y:893 { yyVAL.expression = Join{Join: yyDollar[3].token.Literal, Table: yyDollar[1].expression.(Table), JoinTable: yyDollar[4].expression.(Table), Natural: Token{}, JoinType: yyDollar[2].token, Condition: yyDollar[5].expression} } - case 138: + case 152: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:821 + //line parser.y:897 { yyVAL.expression = Join{Join: yyDollar[4].token.Literal, Table: yyDollar[1].expression.(Table), JoinTable: yyDollar[5].expression.(Table), Natural: yyDollar[2].token, JoinType: yyDollar[3].token, Condition: nil} } - case 139: + case 153: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:825 + //line parser.y:901 { yyVAL.expression = Join{Join: yyDollar[4].token.Literal, Table: yyDollar[1].expression.(Table), JoinTable: yyDollar[5].expression.(Table), Natural: Token{}, JoinType: yyDollar[3].token, Direction: yyDollar[2].token, Condition: yyDollar[6].expression} } - case 140: + case 154: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:829 + //line parser.y:905 { yyVAL.expression = Join{Join: yyDollar[5].token.Literal, Table: yyDollar[1].expression.(Table), JoinTable: yyDollar[6].expression.(Table), Natural: yyDollar[2].token, JoinType: yyDollar[4].token, Direction: yyDollar[3].token, Condition: nil} } - case 141: + case 155: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:833 + //line parser.y:909 { yyVAL.expression = Join{Join: yyDollar[3].token.Literal, Table: yyDollar[1].expression.(Table), JoinTable: yyDollar[4].expression.(Table), Natural: Token{}, JoinType: yyDollar[2].token, Condition: nil} } - case 142: + case 156: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:839 + //line parser.y:915 { yyVAL.expression = nil } - case 143: + case 157: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:843 + //line parser.y:919 { yyVAL.expression = JoinCondition{Literal: yyDollar[1].token.Literal, On: yyDollar[2].expression} } - case 144: + case 158: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:847 + //line parser.y:923 { yyVAL.expression = JoinCondition{Literal: yyDollar[1].token.Literal, Using: yyDollar[3].expressions} } - case 145: + case 159: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:853 + //line parser.y:929 { yyVAL.expression = yyDollar[1].expression } - case 146: + case 160: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:857 + //line parser.y:933 + { + yyVAL.expression = yyDollar[1].expression + } + case 161: + yyDollar = yyS[yypt-1 : yypt+1] + //line parser.y:937 { yyVAL.expression = AllColumns{} } - case 147: + case 162: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:863 + //line parser.y:943 { yyVAL.expression = Field{Object: yyDollar[1].expression} } - case 148: + case 163: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:867 + //line parser.y:947 { yyVAL.expression = Field{Object: yyDollar[1].expression, As: yyDollar[2].token, Alias: yyDollar[3].identifier} } - case 149: + case 164: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:873 + //line parser.y:953 { yyVAL.expression = Case{Case: yyDollar[1].token.Literal, End: yyDollar[5].token.Literal, Value: yyDollar[2].expression, When: yyDollar[3].expressions, Else: yyDollar[4].expression} } - case 150: + case 165: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:879 + //line parser.y:959 { yyVAL.expression = nil } - case 151: + case 166: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:883 + //line parser.y:963 { yyVAL.expression = yyDollar[1].expression } - case 152: + case 167: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:889 + //line parser.y:969 { yyVAL.expression = nil } - case 153: + case 168: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:893 + //line parser.y:973 { yyVAL.expression = CaseElse{Else: yyDollar[1].token.Literal, Result: yyDollar[2].expression} } - case 154: - yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:899 - { - yyVAL.expressions = []Expression{yyDollar[1].expression} - } - case 155: - yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:903 - { - yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) - } - case 156: + case 169: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:909 + //line parser.y:979 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 157: + case 170: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:913 + //line parser.y:983 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 158: + case 171: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:919 + //line parser.y:989 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 159: + case 172: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:923 + //line parser.y:993 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 160: + case 173: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:929 + //line parser.y:999 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 161: + case 174: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:933 + //line parser.y:1003 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 162: + case 175: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:939 + //line parser.y:1009 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 163: + case 176: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:943 + //line parser.y:1013 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 164: + case 177: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:949 + //line parser.y:1019 { yyVAL.expressions = []Expression{yyDollar[1].identifier} } - case 165: + case 178: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:953 + //line parser.y:1023 { yyVAL.expressions = append([]Expression{yyDollar[1].identifier}, yyDollar[3].expressions...) } - case 166: + case 179: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:959 + //line parser.y:1029 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 167: + case 180: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:963 + //line parser.y:1033 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 168: + case 181: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:969 + //line parser.y:1039 { yyVAL.expressions = []Expression{CaseWhen{When: yyDollar[1].token.Literal, Then: yyDollar[3].token.Literal, Condition: yyDollar[2].expression, Result: yyDollar[4].expression}} } - case 169: + case 182: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:973 + //line parser.y:1043 { yyVAL.expressions = append(yyDollar[1].expressions, yyDollar[2].expressions...) } - case 170: + case 183: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:979 + //line parser.y:1049 { yyVAL.expression = InsertQuery{Insert: yyDollar[1].token.Literal, Into: yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Values: yyDollar[4].token.Literal, ValuesList: yyDollar[5].expressions} } - case 171: + case 184: yyDollar = yyS[yypt-8 : yypt+1] - //line parser.y:983 + //line parser.y:1053 { yyVAL.expression = InsertQuery{Insert: yyDollar[1].token.Literal, Into: yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Fields: yyDollar[5].expressions, Values: yyDollar[7].token.Literal, ValuesList: yyDollar[8].expressions} } - case 172: + case 185: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:987 + //line parser.y:1057 { yyVAL.expression = InsertQuery{Insert: yyDollar[1].token.Literal, Into: yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Query: yyDollar[4].expression.(SelectQuery)} } - case 173: + case 186: yyDollar = yyS[yypt-7 : yypt+1] - //line parser.y:991 + //line parser.y:1061 { yyVAL.expression = InsertQuery{Insert: yyDollar[1].token.Literal, Into: yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Fields: yyDollar[5].expressions, Query: yyDollar[7].expression.(SelectQuery)} } - case 174: + case 187: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:997 + //line parser.y:1067 { yyVAL.expression = UpdateQuery{Update: yyDollar[1].token.Literal, Tables: yyDollar[2].expressions, Set: yyDollar[3].token.Literal, SetList: yyDollar[4].expressions, FromClause: yyDollar[5].expression, WhereClause: yyDollar[6].expression} } - case 175: + case 188: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1003 + //line parser.y:1073 { yyVAL.expression = UpdateSet{Field: yyDollar[1].expression.(FieldReference), Value: yyDollar[3].expression} } - case 176: + case 189: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1009 + //line parser.y:1079 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 177: + case 190: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1013 + //line parser.y:1083 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 178: + case 191: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:1019 + //line parser.y:1089 { from := FromClause{From: yyDollar[2].token.Literal, Tables: yyDollar[3].expressions} yyVAL.expression = DeleteQuery{Delete: yyDollar[1].token.Literal, FromClause: from, WhereClause: yyDollar[4].expression} } - case 179: + case 192: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:1024 + //line parser.y:1094 { from := FromClause{From: yyDollar[3].token.Literal, Tables: yyDollar[4].expressions} yyVAL.expression = DeleteQuery{Delete: yyDollar[1].token.Literal, Tables: yyDollar[2].expressions, FromClause: from, WhereClause: yyDollar[5].expression} } - case 180: + case 193: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:1031 + //line parser.y:1101 { yyVAL.expression = CreateTable{CreateTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Fields: yyDollar[5].expressions} } - case 181: + case 194: yyDollar = yyS[yypt-6 : yypt+1] - //line parser.y:1037 + //line parser.y:1107 { yyVAL.expression = AddColumns{AlterTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Add: yyDollar[4].token.Literal, Columns: []Expression{yyDollar[5].expression}, Position: yyDollar[6].expression} } - case 182: + case 195: yyDollar = yyS[yypt-8 : yypt+1] - //line parser.y:1041 + //line parser.y:1111 { yyVAL.expression = AddColumns{AlterTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Add: yyDollar[4].token.Literal, Columns: yyDollar[6].expressions, Position: yyDollar[8].expression} } - case 183: + case 196: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1047 + //line parser.y:1117 { yyVAL.expression = ColumnDefault{Column: yyDollar[1].identifier} } - case 184: + case 197: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1051 + //line parser.y:1121 { yyVAL.expression = ColumnDefault{Column: yyDollar[1].identifier, Default: yyDollar[2].token.Literal, Value: yyDollar[3].expression} } - case 185: + case 198: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1057 + //line parser.y:1127 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 186: + case 199: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1061 + //line parser.y:1131 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 187: + case 200: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1067 + //line parser.y:1137 { yyVAL.expression = nil } - case 188: + case 201: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1071 + //line parser.y:1141 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token} } - case 189: + case 202: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1075 + //line parser.y:1145 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token} } - case 190: + case 203: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1079 + //line parser.y:1149 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token, Column: yyDollar[2].expression} } - case 191: + case 204: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1083 + //line parser.y:1153 { yyVAL.expression = ColumnPosition{Position: yyDollar[1].token, Column: yyDollar[2].expression} } - case 192: + case 205: yyDollar = yyS[yypt-5 : yypt+1] - //line parser.y:1089 + //line parser.y:1159 { yyVAL.expression = DropColumns{AlterTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Drop: yyDollar[4].token.Literal, Columns: []Expression{yyDollar[5].expression}} } - case 193: + case 206: yyDollar = yyS[yypt-7 : yypt+1] - //line parser.y:1093 + //line parser.y:1163 { yyVAL.expression = DropColumns{AlterTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Drop: yyDollar[4].token.Literal, Columns: yyDollar[6].expressions} } - case 194: + case 207: yyDollar = yyS[yypt-7 : yypt+1] - //line parser.y:1099 + //line parser.y:1169 { yyVAL.expression = RenameColumn{AlterTable: yyDollar[1].token.Literal + " " + yyDollar[2].token.Literal, Table: yyDollar[3].identifier, Rename: yyDollar[4].token.Literal, Old: yyDollar[5].expression.(FieldReference), To: yyDollar[6].token.Literal, New: yyDollar[7].identifier} } - case 195: + case 208: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:1105 + //line parser.y:1175 { yyVAL.procexprs = []ProcExpr{ElseIf{Condition: yyDollar[2].expression, Statements: yyDollar[4].program}} } - case 196: + case 209: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1109 + //line parser.y:1179 { yyVAL.procexprs = append(yyDollar[1].procexprs, yyDollar[2].procexprs...) } - case 197: + case 210: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1115 + //line parser.y:1185 { yyVAL.procexpr = nil } - case 198: + case 211: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1119 + //line parser.y:1189 { yyVAL.procexpr = Else{Statements: yyDollar[2].program} } - case 199: + case 212: yyDollar = yyS[yypt-4 : yypt+1] - //line parser.y:1125 + //line parser.y:1195 { yyVAL.procexprs = []ProcExpr{ElseIf{Condition: yyDollar[2].expression, Statements: yyDollar[4].program}} } - case 200: + case 213: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1129 + //line parser.y:1199 { yyVAL.procexprs = append(yyDollar[1].procexprs, yyDollar[2].procexprs...) } - case 201: + case 214: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1135 + //line parser.y:1205 { yyVAL.procexpr = nil } - case 202: + case 215: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1139 + //line parser.y:1209 { yyVAL.procexpr = Else{Statements: yyDollar[2].program} } - case 203: + case 216: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1145 + //line parser.y:1215 { yyVAL.identifier = Identifier{Literal: yyDollar[1].token.Literal, Quoted: yyDollar[1].token.Quoted} } - case 204: + case 217: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1151 + //line parser.y:1221 { yyVAL.text = NewString(yyDollar[1].token.Literal) } - case 205: + case 218: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1157 + //line parser.y:1227 { yyVAL.integer = NewIntegerFromString(yyDollar[1].token.Literal) } - case 206: + case 219: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1161 + //line parser.y:1231 { i := yyDollar[2].integer.Value() * -1 yyVAL.integer = NewInteger(i) } - case 207: + case 220: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1168 + //line parser.y:1238 { yyVAL.float = NewFloatFromString(yyDollar[1].token.Literal) } - case 208: + case 221: yyDollar = yyS[yypt-2 : yypt+1] - //line parser.y:1172 + //line parser.y:1242 { f := yyDollar[2].float.Value() * -1 yyVAL.float = NewFloat(f) } - case 209: + case 222: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1179 + //line parser.y:1249 { yyVAL.ternary = NewTernaryFromString(yyDollar[1].token.Literal) } - case 210: + case 223: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1185 + //line parser.y:1255 { yyVAL.datetime = NewDatetimeFromString(yyDollar[1].token.Literal) } - case 211: + case 224: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1191 + //line parser.y:1261 { yyVAL.null = NewNullFromString(yyDollar[1].token.Literal) } - case 212: + case 225: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1197 + //line parser.y:1267 { yyVAL.variable = Variable{Name: yyDollar[1].token.Literal} } - case 213: + case 226: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1203 + //line parser.y:1273 { yyVAL.variables = []Variable{yyDollar[1].variable} } - case 214: + case 227: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1207 + //line parser.y:1277 { yyVAL.variables = append([]Variable{yyDollar[1].variable}, yyDollar[3].variables...) } - case 215: + case 228: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1213 + //line parser.y:1283 { yyVAL.expression = VariableSubstitution{Variable: yyDollar[1].variable, Value: yyDollar[3].expression} } - case 216: + case 229: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1219 + //line parser.y:1289 { yyVAL.expression = VariableAssignment{Name: yyDollar[1].token.Literal} } - case 217: + case 230: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1223 + //line parser.y:1293 { yyVAL.expression = VariableAssignment{Name: yyDollar[1].token.Literal, Value: yyDollar[3].expression} } - case 218: + case 231: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1229 + //line parser.y:1299 { yyVAL.expressions = []Expression{yyDollar[1].expression} } - case 219: + case 232: yyDollar = yyS[yypt-3 : yypt+1] - //line parser.y:1233 + //line parser.y:1303 { yyVAL.expressions = append([]Expression{yyDollar[1].expression}, yyDollar[3].expressions...) } - case 220: + case 233: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1239 + //line parser.y:1309 { yyVAL.token = Token{} } - case 221: + case 234: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1243 + //line parser.y:1313 { yyVAL.token = yyDollar[1].token } - case 222: + case 235: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1249 + //line parser.y:1319 { yyVAL.token = Token{} } - case 223: + case 236: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1253 + //line parser.y:1323 { yyVAL.token = yyDollar[1].token } - case 224: + case 237: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1259 + //line parser.y:1329 { yyVAL.token = Token{} } - case 225: + case 238: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1263 + //line parser.y:1333 { yyVAL.token = yyDollar[1].token } - case 226: + case 239: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1269 + //line parser.y:1339 { yyVAL.token = Token{} } - case 227: + case 240: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1273 + //line parser.y:1343 { yyVAL.token = yyDollar[1].token } - case 228: + case 241: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1279 + //line parser.y:1349 { yyVAL.token = Token{} } - case 229: + case 242: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1283 + //line parser.y:1353 { yyVAL.token = yyDollar[1].token } - case 230: + case 243: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1287 + //line parser.y:1357 { yyVAL.token = yyDollar[1].token } - case 231: + case 244: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1291 + //line parser.y:1361 { yyVAL.token = yyDollar[1].token } - case 232: + case 245: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1297 + //line parser.y:1367 { yyVAL.token = Token{} } - case 233: + case 246: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1301 + //line parser.y:1371 { yyVAL.token = yyDollar[1].token } - case 234: + case 247: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1307 + //line parser.y:1377 { yyVAL.token = yyDollar[1].token } - case 235: + case 248: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1311 + //line parser.y:1381 { yyVAL.token = Token{Token: COMPARISON_OP, Literal: string('=')} } - case 236: + case 249: yyDollar = yyS[yypt-0 : yypt+1] - //line parser.y:1317 + //line parser.y:1387 { yyVAL.token = Token{} } - case 237: + case 250: yyDollar = yyS[yypt-1 : yypt+1] - //line parser.y:1321 + //line parser.y:1391 { yyVAL.token = Token{Token: ';', Literal: string(';')} } diff --git a/lib/parser/parser.output b/lib/parser/parser.output index 478a714a..e07851fc 100644 --- a/lib/parser/parser.output +++ b/lib/parser/parser.output @@ -24,7 +24,7 @@ state 0 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) program goto 1 statement goto 2 @@ -80,7 +80,7 @@ state 2 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) program goto 43 statement goto 2 @@ -106,104 +106,104 @@ state 2 state 3 statement: select_query.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 44 state 4 statement: insert_query.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 46 state 5 statement: update_query.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 47 state 6 statement: delete_query.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 48 state 7 statement: create_table.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 49 state 8 statement: add_columns.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 50 state 9 statement: drop_columns.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 51 state 10 statement: rename_column.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 52 state 11 statement: variable_statement. (13) - . reduce 13 (src line 203) + . reduce 13 (src line 209) state 12 statement: transaction_statement. (14) - . reduce 14 (src line 207) + . reduce 14 (src line 213) state 13 statement: cursor_statement. (15) - . reduce 15 (src line 211) + . reduce 15 (src line 217) state 14 statement: flow_control_statement. (16) - . reduce 16 (src line 215) + . reduce 16 (src line 221) state 15 statement: command_statement. (17) - . reduce 17 (src line 219) + . reduce 17 (src line 225) state 16 @@ -212,10 +212,10 @@ state 16 order_by_clause: . (56) ORDER shift 54 - UNION reduce 45 (src line 376) - INTERSECT reduce 45 (src line 376) - EXCEPT reduce 45 (src line 376) - . reduce 56 (src line 432) + UNION reduce 45 (src line 382) + INTERSECT reduce 45 (src line 382) + EXCEPT reduce 45 (src line 382) + . reduce 56 (src line 438) order_by_clause goto 53 @@ -280,28 +280,28 @@ state 22 state 23 variable_statement: variable_substitution.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 67 state 24 transaction_statement: COMMIT.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 68 state 25 transaction_statement: ROLLBACK.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 69 @@ -432,10 +432,10 @@ state 32 state 33 flow_control_statement: EXIT.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 111 @@ -492,7 +492,7 @@ state 36 from_clause: . (48) FROM shift 115 - . reduce 48 (src line 392) + . reduce 48 (src line 398) from_clause goto 114 @@ -516,23 +516,23 @@ state 38 state 39 select_clause: SELECT.distinct fields - distinct: . (220) + distinct: . (233) DISTINCT shift 121 - . reduce 220 (src line 1237) + . reduce 233 (src line 1307) distinct goto 120 state 40 select_set_entity: subquery. (46) - . reduce 46 (src line 381) + . reduce 46 (src line 387) state 41 - variable: VARIABLE. (212) + variable: VARIABLE. (225) - . reduce 212 (src line 1195) + . reduce 225 (src line 1265) state 42 @@ -551,61 +551,61 @@ state 42 state 43 program: statement program. (2) - . reduce 2 (src line 152) + . reduce 2 (src line 158) state 44 statement: select_query statement_terminal. (5) - . reduce 5 (src line 170) + . reduce 5 (src line 176) state 45 - statement_terminal: ';'. (237) + statement_terminal: ';'. (250) - . reduce 237 (src line 1320) + . reduce 250 (src line 1390) state 46 statement: insert_query statement_terminal. (6) - . reduce 6 (src line 175) + . reduce 6 (src line 181) state 47 statement: update_query statement_terminal. (7) - . reduce 7 (src line 179) + . reduce 7 (src line 185) state 48 statement: delete_query statement_terminal. (8) - . reduce 8 (src line 183) + . reduce 8 (src line 189) state 49 statement: create_table statement_terminal. (9) - . reduce 9 (src line 187) + . reduce 9 (src line 193) state 50 statement: add_columns statement_terminal. (10) - . reduce 10 (src line 191) + . reduce 10 (src line 197) state 51 statement: drop_columns statement_terminal. (11) - . reduce 11 (src line 195) + . reduce 11 (src line 201) state 52 statement: rename_column statement_terminal. (12) - . reduce 12 (src line 199) + . reduce 12 (src line 205) state 53 @@ -613,7 +613,7 @@ state 53 limit_clause: . (58) LIMIT shift 124 - . reduce 58 (src line 442) + . reduce 58 (src line 448) limit_clause goto 123 @@ -643,28 +643,28 @@ state 56 state 57 - identified_tables: identified_table. (162) + identified_tables: identified_table. (175) identified_tables: identified_table.',' identified_tables ',' shift 128 - . reduce 162 (src line 937) + . reduce 175 (src line 1007) state 58 - identified_table: identifier. (126) + identified_table: identifier. (140) identified_table: identifier.identifier identified_table: identifier.AS identifier IDENTIFIER shift 59 AS shift 130 - . reduce 126 (src line 765) + . reduce 140 (src line 841) identifier goto 129 state 59 - identifier: IDENTIFIER. (203) + identifier: IDENTIFIER. (216) - . reduce 203 (src line 1143) + . reduce 216 (src line 1213) state 60 @@ -713,45 +713,45 @@ state 63 state 64 variable_statement: VAR variable_assignments.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 142 state 65 - variable_assignments: variable_assignment. (218) + variable_assignments: variable_assignment. (231) variable_assignments: variable_assignment.',' variable_assignments ',' shift 143 - . reduce 218 (src line 1227) + . reduce 231 (src line 1297) state 66 - variable_assignment: VARIABLE. (216) + variable_assignment: VARIABLE. (229) variable_assignment: VARIABLE.SUBSTITUTION_OP value SUBSTITUTION_OP shift 144 - . reduce 216 (src line 1217) + . reduce 229 (src line 1287) state 67 variable_statement: variable_substitution statement_terminal. (21) - . reduce 21 (src line 239) + . reduce 21 (src line 245) state 68 transaction_statement: COMMIT statement_terminal. (22) - . reduce 22 (src line 244) + . reduce 22 (src line 250) state 69 transaction_statement: ROLLBACK statement_terminal. (23) - . reduce 23 (src line 249) + . reduce 23 (src line 255) state 70 @@ -763,28 +763,28 @@ state 70 state 71 cursor_statement: OPEN identifier.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 146 state 72 cursor_statement: CLOSE identifier.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 147 state 73 cursor_statement: DISPOSE identifier.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) statement_terminal goto 148 @@ -815,7 +815,7 @@ state 75 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 @@ -830,83 +830,83 @@ state 75 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 state 76 - value: field_reference. (70) + value: field_reference. (73) - . reduce 70 (src line 498) + . reduce 73 (src line 518) state 77 - value: primary. (71) + value: primary. (74) - . reduce 71 (src line 503) + . reduce 74 (src line 523) state 78 - value: arithmetic. (72) + value: arithmetic. (75) - . reduce 72 (src line 507) + . reduce 75 (src line 527) state 79 - value: string_operation. (73) + value: string_operation. (76) - . reduce 73 (src line 511) + . reduce 76 (src line 531) - 80: reduce/reduce conflict (red'ns 74 and 83) on IN - 80: reduce/reduce conflict (red'ns 74 and 83) on NOT - 80: reduce/reduce conflict (red'ns 74 and 83) on BETWEEN - 80: reduce/reduce conflict (red'ns 74 and 83) on COMPARISON_OP - 80: reduce/reduce conflict (red'ns 74 and 83) on '=' + 80: reduce/reduce conflict (red'ns 77 and 86) on IN + 80: reduce/reduce conflict (red'ns 77 and 86) on NOT + 80: reduce/reduce conflict (red'ns 77 and 86) on BETWEEN + 80: reduce/reduce conflict (red'ns 77 and 86) on COMPARISON_OP + 80: reduce/reduce conflict (red'ns 77 and 86) on '=' state 80 - value: subquery. (74) - row_value: subquery. (83) + value: subquery. (77) + row_value: subquery. (86) - . reduce 74 (src line 515) + . reduce 77 (src line 535) state 81 - value: function. (75) + value: function. (78) - . reduce 75 (src line 519) + . reduce 78 (src line 539) state 82 - value: case. (76) + value: case. (79) - . reduce 76 (src line 523) + . reduce 79 (src line 543) state 83 - value: comparison. (77) + value: comparison. (80) - . reduce 77 (src line 527) + . reduce 80 (src line 547) state 84 - value: logic. (78) + value: logic. (81) - . reduce 78 (src line 531) + . reduce 81 (src line 551) state 85 - value: variable. (79) + value: variable. (82) variable_substitution: variable.SUBSTITUTION_OP value SUBSTITUTION_OP shift 119 - . reduce 79 (src line 535) + . reduce 82 (src line 555) state 86 - value: variable_substitution. (80) + value: variable_substitution. (83) - . reduce 80 (src line 539) + . reduce 83 (src line 559) state 87 @@ -958,62 +958,62 @@ state 87 variable goto 85 variable_substitution goto 86 -88: shift/reduce conflict (shift 169(0), red'n 68(0)) on '(' +88: shift/reduce conflict (shift 169(0), red'n 71(0)) on '(' state 88 - field_reference: identifier. (68) + field_reference: identifier. (71) field_reference: identifier.'.' identifier function: identifier.'(' option ')' '.' shift 168 '(' shift 169 - . reduce 68 (src line 488) + . reduce 71 (src line 508) state 89 - primary: text. (62) + primary: text. (65) - . reduce 62 (src line 462) + . reduce 65 (src line 482) state 90 - primary: integer. (63) + primary: integer. (66) - . reduce 63 (src line 467) + . reduce 66 (src line 487) state 91 - primary: float. (64) + primary: float. (67) - . reduce 64 (src line 471) + . reduce 67 (src line 491) state 92 - primary: ternary. (65) + primary: ternary. (68) - . reduce 65 (src line 475) + . reduce 68 (src line 495) state 93 - primary: datetime. (66) + primary: datetime. (69) - . reduce 66 (src line 479) + . reduce 69 (src line 499) state 94 - primary: null. (67) + primary: null. (70) - . reduce 67 (src line 483) + . reduce 70 (src line 503) state 95 - function: group_concat. (120) + function: group_concat. (130) - . reduce 120 (src line 736) + . reduce 130 (src line 790) state 96 case: CASE.case_value case_when case_else END - case_value: . (150) + case_value: . (165) IDENTIFIER shift 59 STRING shift 100 @@ -1029,7 +1029,7 @@ state 96 GROUP_CONCAT shift 107 '-' shift 102 '(' shift 87 - . reduce 150 (src line 877) + . reduce 165 (src line 957) primary goto 77 field_reference goto 76 @@ -1064,12 +1064,12 @@ state 97 comparison: row_value.comparison_operator ANY subquery comparison: row_value.comparison_operator ALL '(' row_values ')' comparison: row_value.comparison_operator ALL subquery - negation: . (222) + negation: . (235) NOT shift 164 COMPARISON_OP shift 172 '=' shift 173 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 174 comparison_operator goto 175 @@ -1124,15 +1124,15 @@ state 99 variable_substitution goto 86 state 100 - text: STRING. (204) + text: STRING. (217) - . reduce 204 (src line 1149) + . reduce 217 (src line 1219) state 101 - integer: INTEGER. (205) + integer: INTEGER. (218) - . reduce 205 (src line 1155) + . reduce 218 (src line 1225) state 102 @@ -1148,27 +1148,27 @@ state 102 float goto 179 state 103 - float: FLOAT. (207) + float: FLOAT. (220) - . reduce 207 (src line 1166) + . reduce 220 (src line 1236) state 104 - ternary: TERNARY. (209) + ternary: TERNARY. (222) - . reduce 209 (src line 1177) + . reduce 222 (src line 1247) state 105 - datetime: DATETIME. (210) + datetime: DATETIME. (223) - . reduce 210 (src line 1183) + . reduce 223 (src line 1253) state 106 - null: NULL. (211) + null: NULL. (224) - . reduce 211 (src line 1189) + . reduce 224 (src line 1259) state 107 @@ -1198,7 +1198,7 @@ state 108 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 @@ -1213,7 +1213,7 @@ state 108 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 @@ -1225,22 +1225,22 @@ state 109 . error - 110: reduce/reduce conflict (red'ns 79 and 213) on IN + 110: reduce/reduce conflict (red'ns 82 and 226) on IN state 110 - value: variable. (79) - variables: variable. (213) + value: variable. (82) + variables: variable. (226) variables: variable.',' variables variable_substitution: variable.SUBSTITUTION_OP value SUBSTITUTION_OP shift 119 ',' shift 183 - . reduce 79 (src line 535) + . reduce 82 (src line 555) state 111 flow_control_statement: EXIT statement_terminal. (33) - . reduce 33 (src line 293) + . reduce 33 (src line 299) state 112 @@ -1269,15 +1269,15 @@ state 113 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - statement_terminal: . (236) - negation: . (222) + statement_terminal: . (249) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -1288,7 +1288,7 @@ state 113 '/' shift 160 '%' shift 161 ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) negation goto 155 comparison_operator goto 156 @@ -1299,7 +1299,7 @@ state 114 where_clause: . (50) WHERE shift 187 - . reduce 50 (src line 402) + . reduce 50 (src line 408) where_clause goto 186 @@ -1322,28 +1322,28 @@ state 115 state 116 select_entity: select_set_entity UNION.all select_set_entity - all: . (232) + all: . (245) ALL shift 190 - . reduce 232 (src line 1295) + . reduce 245 (src line 1365) all goto 189 state 117 select_entity: select_set_entity INTERSECT.all select_set_entity - all: . (232) + all: . (245) ALL shift 190 - . reduce 232 (src line 1295) + . reduce 245 (src line 1365) all goto 191 state 118 select_entity: select_set_entity EXCEPT.all select_set_entity - all: . (232) + all: . (245) ALL shift 190 - . reduce 232 (src line 1295) + . reduce 245 (src line 1365) all goto 192 @@ -1404,7 +1404,7 @@ state 120 CASE shift 96 GROUP_CONCAT shift 107 '-' shift 102 - '*' shift 198 + '*' shift 199 '(' shift 87 . error @@ -1419,11 +1419,12 @@ state 120 logic goto 84 function goto 81 group_concat goto 95 + analytic_function goto 198 field_object goto 196 field goto 195 case goto 82 fields goto 194 - identifier goto 88 + identifier goto 200 text goto 89 integer goto 90 float goto 91 @@ -1434,33 +1435,68 @@ state 120 variable_substitution goto 86 state 121 - distinct: DISTINCT. (221) + distinct: DISTINCT. (234) - . reduce 221 (src line 1242) + . reduce 234 (src line 1312) state 122 subquery: '(' select_query.')' - ')' shift 199 + ')' shift 201 . error state 123 select_query: select_entity order_by_clause limit_clause.offset_clause - offset_clause: . (60) + offset_clause: . (63) - OFFSET shift 201 - . reduce 60 (src line 452) + OFFSET shift 203 + . reduce 63 (src line 472) - offset_clause goto 200 + offset_clause goto 202 state 124 - limit_clause: LIMIT.INTEGER + limit_clause: LIMIT.value limit_with + limit_clause: LIMIT.value PERCENT limit_with - INTEGER shift 202 + IDENTIFIER shift 59 + STRING shift 100 + INTEGER shift 101 + FLOAT shift 103 + TERNARY shift 104 + DATETIME shift 105 + VARIABLE shift 41 + EXISTS shift 98 + NOT shift 99 + NULL shift 106 + CASE shift 96 + GROUP_CONCAT shift 107 + '-' shift 102 + '(' shift 87 . error + primary goto 77 + field_reference goto 76 + value goto 204 + row_value goto 97 + subquery goto 80 + string_operation goto 79 + comparison goto 83 + arithmetic goto 78 + logic goto 84 + function goto 81 + group_concat goto 95 + case goto 82 + identifier goto 88 + text goto 89 + integer goto 90 + float goto 91 + ternary goto 92 + datetime goto 93 + null goto 94 + variable goto 85 + variable_substitution goto 86 state 125 order_by_clause: ORDER BY.order_items @@ -1483,9 +1519,11 @@ state 125 primary goto 77 field_reference goto 76 - value goto 205 + value goto 208 row_value goto 97 - order_item goto 204 + order_items goto 205 + order_item goto 206 + order_value goto 207 subquery goto 80 string_operation goto 79 comparison goto 83 @@ -1493,9 +1531,9 @@ state 125 logic goto 84 function goto 81 group_concat goto 95 + analytic_function goto 209 case goto 82 - order_items goto 203 - identifier goto 88 + identifier goto 200 text goto 89 integer goto 90 float goto 91 @@ -1512,11 +1550,11 @@ state 126 insert_query: INSERT INTO identifier.'(' field_references ')' select_query SELECT shift 39 - VALUES shift 206 - '(' shift 207 + VALUES shift 210 + '(' shift 211 . error - select_query goto 208 + select_query goto 212 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 @@ -1528,10 +1566,10 @@ state 127 IDENTIFIER shift 59 . error - field_reference goto 211 - update_set goto 210 - update_set_list goto 209 - identifier goto 212 + field_reference goto 215 + update_set goto 214 + update_set_list goto 213 + identifier goto 216 state 128 identified_tables: identified_table ','.identified_tables @@ -1540,13 +1578,13 @@ state 128 . error identified_table goto 57 - identified_tables goto 213 + identified_tables goto 217 identifier goto 58 state 129 - identified_table: identifier identifier. (127) + identified_table: identifier identifier. (141) - . reduce 127 (src line 770) + . reduce 141 (src line 846) state 130 @@ -1555,82 +1593,82 @@ state 130 IDENTIFIER shift 59 . error - identifier goto 214 + identifier goto 218 state 131 delete_query: DELETE FROM tables.where_clause where_clause: . (50) WHERE shift 187 - . reduce 50 (src line 402) + . reduce 50 (src line 408) - where_clause goto 215 + where_clause goto 219 - 132: reduce/reduce conflict (red'ns 224 and 228) on JOIN + 132: reduce/reduce conflict (red'ns 237 and 241) on JOIN state 132 join: table.join_inner JOIN table join_condition join: table.NATURAL join_inner JOIN table join: table.join_direction join_outer JOIN table join_condition join: table.NATURAL join_direction join_outer JOIN table join: table.CROSS JOIN table - tables: table. (160) + tables: table. (173) tables: table.',' tables - join_inner: . (224) - join_direction: . (228) - - JOIN reduce 224 (src line 1257) - INNER shift 221 - OUTER reduce 228 (src line 1277) - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - NATURAL shift 217 - ',' shift 220 - . reduce 160 (src line 927) - - join_inner goto 216 - join_direction goto 218 + join_inner: . (237) + join_direction: . (241) + + JOIN reduce 237 (src line 1327) + INNER shift 225 + OUTER reduce 241 (src line 1347) + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + NATURAL shift 221 + ',' shift 224 + . reduce 173 (src line 997) + + join_inner goto 220 + join_direction goto 222 state 133 - table: identified_table. (131) + table: identified_table. (145) - . reduce 131 (src line 789) + . reduce 145 (src line 865) state 134 - table: virtual_table. (132) + table: virtual_table. (146) table: virtual_table.identifier table: virtual_table.AS identifier IDENTIFIER shift 59 - AS shift 226 - . reduce 132 (src line 794) + AS shift 230 + . reduce 146 (src line 870) - identifier goto 225 + identifier goto 229 state 135 - table: join. (135) + table: join. (149) - . reduce 135 (src line 806) + . reduce 149 (src line 882) state 136 - table: DUAL. (136) + table: DUAL. (150) - . reduce 136 (src line 810) + . reduce 150 (src line 886) state 137 - virtual_table: subquery. (129) + virtual_table: subquery. (143) - . reduce 129 (src line 779) + . reduce 143 (src line 855) state 138 - virtual_table: STDIN. (130) + virtual_table: STDIN. (144) - . reduce 130 (src line 784) + . reduce 144 (src line 860) state 139 @@ -1647,13 +1685,13 @@ state 139 virtual_table goto 134 table goto 132 join goto 135 - tables goto 227 + tables goto 231 identifier goto 58 state 140 create_table: CREATE TABLE identifier.'(' using_fields ')' - '(' shift 228 + '(' shift 232 . error @@ -1664,16 +1702,16 @@ state 141 drop_columns: ALTER TABLE identifier.DROP '(' field_references ')' rename_column: ALTER TABLE identifier.RENAME field_reference TO identifier - ADD shift 229 - DROP shift 230 - RENAME shift 231 + ADD shift 233 + DROP shift 234 + RENAME shift 235 . error state 142 variable_statement: VAR variable_assignments statement_terminal. (20) - . reduce 20 (src line 234) + . reduce 20 (src line 240) state 143 @@ -1683,7 +1721,7 @@ state 143 . error variable_assignment goto 65 - variable_assignments goto 232 + variable_assignments goto 236 state 144 variable_assignment: VARIABLE SUBSTITUTION_OP.value @@ -1706,7 +1744,7 @@ state 144 primary goto 77 field_reference goto 76 - value goto 233 + value goto 237 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -1729,26 +1767,26 @@ state 144 state 145 cursor_statement: DECLARE identifier CURSOR.FOR select_query statement_terminal - FOR shift 234 + FOR shift 238 . error state 146 cursor_statement: OPEN identifier statement_terminal. (25) - . reduce 25 (src line 259) + . reduce 25 (src line 265) state 147 cursor_statement: CLOSE identifier statement_terminal. (26) - . reduce 26 (src line 263) + . reduce 26 (src line 269) state 148 cursor_statement: DISPOSE identifier statement_terminal. (27) - . reduce 27 (src line 267) + . reduce 27 (src line 273) state 149 @@ -1757,8 +1795,8 @@ state 149 VARIABLE shift 41 . error - variable goto 236 - variables goto 235 + variable goto 240 + variables goto 239 state 150 flow_control_statement: IF value THEN.program else END IF statement_terminal @@ -1786,9 +1824,9 @@ state 150 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) - program goto 237 + program goto 241 statement goto 2 variable_statement goto 11 transaction_statement goto 12 @@ -1831,7 +1869,7 @@ state 151 primary goto 77 field_reference goto 76 - value goto 238 + value goto 242 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -1853,7 +1891,7 @@ state 151 state 152 comparison: value COMPARISON_OP.value - comparison_operator: COMPARISON_OP. (234) + comparison_operator: COMPARISON_OP. (247) IDENTIFIER shift 59 STRING shift 100 @@ -1869,11 +1907,11 @@ state 152 GROUP_CONCAT shift 107 '-' shift 102 '(' shift 87 - . reduce 234 (src line 1305) + . reduce 247 (src line 1375) primary goto 77 field_reference goto 76 - value goto 239 + value goto 243 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -1895,7 +1933,7 @@ state 152 state 153 comparison: value '='.value - comparison_operator: '='. (235) + comparison_operator: '='. (248) IDENTIFIER shift 59 STRING shift 100 @@ -1911,11 +1949,11 @@ state 153 GROUP_CONCAT shift 107 '-' shift 102 '(' shift 87 - . reduce 235 (src line 1310) + . reduce 248 (src line 1380) primary goto 77 field_reference goto 76 - value goto 240 + value goto 244 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -1938,21 +1976,21 @@ state 153 state 154 comparison: value IS.negation ternary comparison: value IS.negation null - negation: . (222) + negation: . (235) NOT shift 164 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) - negation goto 241 + negation goto 245 state 155 comparison: value negation.BETWEEN value AND value comparison: value negation.IN row_value comparison: value negation.LIKE value - IN shift 243 - BETWEEN shift 242 - LIKE shift 244 + IN shift 247 + BETWEEN shift 246 + LIKE shift 248 . error @@ -1960,8 +1998,8 @@ state 156 comparison: value comparison_operator.ANY row_value comparison: value comparison_operator.ALL row_value - ALL shift 246 - ANY shift 245 + ALL shift 250 + ANY shift 249 . error @@ -1986,7 +2024,7 @@ state 157 primary goto 77 field_reference goto 76 - value goto 247 + value goto 251 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2027,7 +2065,7 @@ state 158 primary goto 77 field_reference goto 76 - value goto 248 + value goto 252 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2068,7 +2106,7 @@ state 159 primary goto 77 field_reference goto 76 - value goto 249 + value goto 253 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2109,7 +2147,7 @@ state 160 primary goto 77 field_reference goto 76 - value goto 250 + value goto 254 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2150,7 +2188,7 @@ state 161 primary goto 77 field_reference goto 76 - value goto 251 + value goto 255 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2191,7 +2229,7 @@ state 162 primary goto 77 field_reference goto 76 - value goto 252 + value goto 256 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2232,7 +2270,7 @@ state 163 primary goto 77 field_reference goto 76 - value goto 253 + value goto 257 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2253,12 +2291,12 @@ state 163 variable_substitution goto 86 state 164 - negation: NOT. (223) + negation: NOT. (236) - . reduce 223 (src line 1252) + . reduce 236 (src line 1322) -165: shift/reduce conflict (shift 254(0), red'n 156(0)) on ')' +165: shift/reduce conflict (shift 258(0), red'n 171(0)) on ')' state 165 value: '(' value.')' string_operation: value.STRING_OP value @@ -2278,9 +2316,9 @@ state 165 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - values: value. (156) + values: value. (171) values: value.',' values - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 @@ -2294,9 +2332,9 @@ state 165 '*' shift 159 '/' shift 160 '%' shift 161 - ')' shift 254 - ',' shift 255 - . reduce 222 (src line 1247) + ')' shift 258 + ',' shift 259 + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 @@ -2304,24 +2342,24 @@ state 165 state 166 row_value: '(' values.')' - ')' shift 256 + ')' shift 260 . error - 167: reduce/reduce conflict (red'ns 74 and 83) on IN - 167: reduce/reduce conflict (red'ns 74 and 83) on NOT - 167: reduce/reduce conflict (red'ns 74 and 83) on BETWEEN - 167: reduce/reduce conflict (red'ns 74 and 83) on COMPARISON_OP - 167: reduce/reduce conflict (red'ns 74 and 83) on '=' + 167: reduce/reduce conflict (red'ns 77 and 86) on IN + 167: reduce/reduce conflict (red'ns 77 and 86) on NOT + 167: reduce/reduce conflict (red'ns 77 and 86) on BETWEEN + 167: reduce/reduce conflict (red'ns 77 and 86) on COMPARISON_OP + 167: reduce/reduce conflict (red'ns 77 and 86) on '=' state 167 select_set_entity: subquery. (46) - value: subquery. (74) - row_value: subquery. (83) + value: subquery. (77) + row_value: subquery. (86) - UNION reduce 46 (src line 381) - INTERSECT reduce 46 (src line 381) - EXCEPT reduce 46 (src line 381) - . reduce 74 (src line 515) + UNION reduce 46 (src line 387) + INTERSECT reduce 46 (src line 387) + EXCEPT reduce 46 (src line 387) + . reduce 77 (src line 535) state 168 @@ -2330,27 +2368,27 @@ state 168 IDENTIFIER shift 59 . error - identifier goto 257 + identifier goto 261 state 169 function: identifier '('.option ')' - option: . (121) - distinct: . (220) + option: . (131) + distinct: . (233) DISTINCT shift 121 - ')' reduce 121 (src line 741) - . reduce 220 (src line 1237) + ')' reduce 131 (src line 795) + . reduce 233 (src line 1307) - option goto 258 - distinct goto 259 + option goto 262 + distinct goto 263 state 170 case: CASE case_value.case_when case_else END - WHEN shift 261 + WHEN shift 265 . error - case_when goto 260 + case_when goto 264 state 171 string_operation: value.STRING_OP value @@ -2370,14 +2408,14 @@ state 171 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - case_value: value. (151) - negation: . (222) + case_value: value. (166) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - WHEN reduce 151 (src line 882) + WHEN reduce 166 (src line 962) COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -2386,38 +2424,38 @@ state 171 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 state 172 comparison: row_value COMPARISON_OP.row_value - comparison_operator: COMPARISON_OP. (234) + comparison_operator: COMPARISON_OP. (247) - '(' shift 263 - . reduce 234 (src line 1305) + '(' shift 267 + . reduce 247 (src line 1375) - row_value goto 262 - subquery goto 264 + row_value goto 266 + subquery goto 268 state 173 comparison: row_value '='.row_value - comparison_operator: '='. (235) + comparison_operator: '='. (248) - '(' shift 263 - . reduce 235 (src line 1310) + '(' shift 267 + . reduce 248 (src line 1380) - row_value goto 265 - subquery goto 264 + row_value goto 269 + subquery goto 268 state 174 comparison: row_value negation.BETWEEN row_value AND row_value comparison: row_value negation.IN '(' row_values ')' comparison: row_value negation.IN subquery - IN shift 267 - BETWEEN shift 266 + IN shift 271 + BETWEEN shift 270 . error @@ -2427,20 +2465,20 @@ state 175 comparison: row_value comparison_operator.ALL '(' row_values ')' comparison: row_value comparison_operator.ALL subquery - ALL shift 269 - ANY shift 268 + ALL shift 273 + ANY shift 272 . error state 176 - comparison: EXISTS subquery. (110) + comparison: EXISTS subquery. (120) - . reduce 110 (src line 690) + . reduce 120 (src line 744) - 177: reduce/reduce conflict (red'ns 118 and 222) on IN - 177: reduce/reduce conflict (red'ns 118 and 222) on BETWEEN - 177: reduce/reduce conflict (red'ns 118 and 222) on LIKE + 177: reduce/reduce conflict (red'ns 128 and 235) on IN + 177: reduce/reduce conflict (red'ns 128 and 235) on BETWEEN + 177: reduce/reduce conflict (red'ns 128 and 235) on LIKE state 177 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value @@ -2459,8 +2497,8 @@ state 177 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - logic: NOT value. (118) - negation: . (222) + logic: NOT value. (128) + negation: . (235) NOT shift 164 IS shift 154 @@ -2472,37 +2510,37 @@ state 177 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 118 (src line 726) + . reduce 128 (src line 780) negation goto 155 comparison_operator goto 156 state 178 - integer: '-' integer. (206) + integer: '-' integer. (219) - . reduce 206 (src line 1160) + . reduce 219 (src line 1230) state 179 - float: '-' float. (208) + float: '-' float. (221) - . reduce 208 (src line 1171) + . reduce 221 (src line 1241) state 180 group_concat: GROUP_CONCAT '('.option order_by_clause ')' group_concat: GROUP_CONCAT '('.option order_by_clause SEPARATOR STRING ')' - option: . (121) - distinct: . (220) + option: . (131) + distinct: . (233) - ORDER reduce 121 (src line 741) + ORDER reduce 131 (src line 795) DISTINCT shift 121 - SEPARATOR reduce 121 (src line 741) - ')' reduce 121 (src line 741) - . reduce 220 (src line 1237) + SEPARATOR reduce 131 (src line 795) + ')' reduce 131 (src line 795) + . reduce 233 (src line 1307) - option goto 270 - distinct goto 259 + option goto 274 + distinct goto 263 state 181 flow_control_statement: WHILE value DO.in_loop_program END WHILE statement_terminal @@ -2516,7 +2554,7 @@ state 181 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -2525,22 +2563,22 @@ state 181 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 3 (src line 158) + . reduce 3 (src line 164) - in_loop_program goto 271 - statement goto 273 - in_loop_statement goto 272 + in_loop_program goto 275 + statement goto 277 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -2563,7 +2601,7 @@ state 182 IDENTIFIER shift 59 . error - identifier goto 278 + identifier goto 282 state 183 variables: variable ','.variables @@ -2571,8 +2609,8 @@ state 183 VARIABLE shift 41 . error - variable goto 236 - variables goto 279 + variable goto 240 + variables goto 283 state 184 command_statement: SET FLAG '='.primary statement_terminal @@ -2586,7 +2624,7 @@ state 184 '-' shift 102 . error - primary goto 280 + primary goto 284 text goto 89 integer goto 90 float goto 91 @@ -2597,17 +2635,17 @@ state 184 state 185 command_statement: PRINT value statement_terminal. (39) - . reduce 39 (src line 321) + . reduce 39 (src line 327) state 186 select_entity: select_clause from_clause where_clause.group_by_clause having_clause group_by_clause: . (52) - GROUP shift 282 - . reduce 52 (src line 412) + GROUP shift 286 + . reduce 52 (src line 418) - group_by_clause goto 281 + group_by_clause goto 285 state 187 where_clause: WHERE.value @@ -2630,7 +2668,7 @@ state 187 primary goto 77 field_reference goto 76 - value goto 283 + value goto 287 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -2653,7 +2691,7 @@ state 187 state 188 from_clause: FROM tables. (49) - . reduce 49 (src line 397) + . reduce 49 (src line 403) state 189 @@ -2663,15 +2701,15 @@ state 189 '(' shift 42 . error - select_entity goto 285 - select_set_entity goto 284 + select_entity goto 289 + select_set_entity goto 288 select_clause goto 36 subquery goto 40 state 190 - all: ALL. (233) + all: ALL. (246) - . reduce 233 (src line 1300) + . reduce 246 (src line 1370) state 191 @@ -2681,8 +2719,8 @@ state 191 '(' shift 42 . error - select_entity goto 285 - select_set_entity goto 286 + select_entity goto 289 + select_set_entity goto 290 select_clause goto 36 subquery goto 40 @@ -2693,26 +2731,26 @@ state 192 '(' shift 42 . error - select_entity goto 285 - select_set_entity goto 287 + select_entity goto 289 + select_set_entity goto 291 select_clause goto 36 subquery goto 40 -193: shift/reduce conflict (shift 163(4), red'n 215(0)) on AND -193: shift/reduce conflict (shift 162(3), red'n 215(0)) on OR -193: shift/reduce conflict (shift 164(5), red'n 215(0)) on NOT -193: shift/reduce conflict (shift 154(6), red'n 215(0)) on IS -193: shift/reduce conflict (shift 152(6), red'n 215(0)) on COMPARISON_OP -193: shift/reduce conflict (shift 151(7), red'n 215(0)) on STRING_OP -193: shift/reduce conflict (shift 153(6), red'n 215(0)) on '=' -193: shift/reduce conflict (shift 157(8), red'n 215(0)) on '+' -193: shift/reduce conflict (shift 158(8), red'n 215(0)) on '-' -193: shift/reduce conflict (shift 159(9), red'n 215(0)) on '*' -193: shift/reduce conflict (shift 160(9), red'n 215(0)) on '/' -193: shift/reduce conflict (shift 161(9), red'n 215(0)) on '%' - 193: reduce/reduce conflict (red'ns 215 and 222) on IN - 193: reduce/reduce conflict (red'ns 215 and 222) on BETWEEN - 193: reduce/reduce conflict (red'ns 215 and 222) on LIKE +193: shift/reduce conflict (shift 163(4), red'n 228(0)) on AND +193: shift/reduce conflict (shift 162(3), red'n 228(0)) on OR +193: shift/reduce conflict (shift 164(5), red'n 228(0)) on NOT +193: shift/reduce conflict (shift 154(6), red'n 228(0)) on IS +193: shift/reduce conflict (shift 152(6), red'n 228(0)) on COMPARISON_OP +193: shift/reduce conflict (shift 151(7), red'n 228(0)) on STRING_OP +193: shift/reduce conflict (shift 153(6), red'n 228(0)) on '=' +193: shift/reduce conflict (shift 157(8), red'n 228(0)) on '+' +193: shift/reduce conflict (shift 158(8), red'n 228(0)) on '-' +193: shift/reduce conflict (shift 159(9), red'n 228(0)) on '*' +193: shift/reduce conflict (shift 160(9), red'n 228(0)) on '/' +193: shift/reduce conflict (shift 161(9), red'n 228(0)) on '%' + 193: reduce/reduce conflict (red'ns 228 and 235) on IN + 193: reduce/reduce conflict (red'ns 228 and 235) on BETWEEN + 193: reduce/reduce conflict (red'ns 228 and 235) on LIKE state 193 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value @@ -2731,8 +2769,8 @@ state 193 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - variable_substitution: variable SUBSTITUTION_OP value. (215) - negation: . (222) + variable_substitution: variable SUBSTITUTION_OP value. (228) + negation: . (235) AND shift 163 OR shift 162 @@ -2746,7 +2784,7 @@ state 193 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 215 (src line 1211) + . reduce 228 (src line 1281) negation goto 155 comparison_operator goto 156 @@ -2754,23 +2792,23 @@ state 193 state 194 select_clause: SELECT distinct fields. (47) - . reduce 47 (src line 386) + . reduce 47 (src line 392) state 195 - fields: field. (166) + fields: field. (179) fields: field.',' fields - ',' shift 288 - . reduce 166 (src line 957) + ',' shift 292 + . reduce 179 (src line 1027) state 196 - field: field_object. (147) + field: field_object. (162) field: field_object.AS identifier - AS shift 289 - . reduce 147 (src line 861) + AS shift 293 + . reduce 162 (src line 941) state 197 @@ -2791,15 +2829,15 @@ state 197 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - field_object: value. (145) - negation: . (222) + field_object: value. (159) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -2809,58 +2847,161 @@ state 197 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 145 (src line 851) + . reduce 159 (src line 927) negation goto 155 comparison_operator goto 156 state 198 - field_object: '*'. (146) + field_object: analytic_function. (160) - . reduce 146 (src line 856) + . reduce 160 (src line 932) state 199 - subquery: '(' select_query ')'. (90) + field_object: '*'. (161) - . reduce 90 (src line 588) + . reduce 161 (src line 936) +200: shift/reduce conflict (shift 294(0), red'n 71(0)) on '(' state 200 - select_query: select_entity order_by_clause limit_clause offset_clause. (40) + field_reference: identifier. (71) + field_reference: identifier.'.' identifier + function: identifier.'(' option ')' + analytic_function: identifier.'(' option ')' OVER '(' analytic_clause ')' - . reduce 40 (src line 326) + '.' shift 168 + '(' shift 294 + . reduce 71 (src line 508) state 201 - offset_clause: OFFSET.INTEGER + subquery: '(' select_query ')'. (100) - INTEGER shift 290 - . error + . reduce 100 (src line 642) state 202 - limit_clause: LIMIT INTEGER. (59) + select_query: select_entity order_by_clause limit_clause offset_clause. (40) - . reduce 59 (src line 447) + . reduce 40 (src line 332) state 203 - order_by_clause: ORDER BY order_items. (57) + offset_clause: OFFSET.value - . reduce 57 (src line 437) + IDENTIFIER shift 59 + STRING shift 100 + INTEGER shift 101 + FLOAT shift 103 + TERNARY shift 104 + DATETIME shift 105 + VARIABLE shift 41 + EXISTS shift 98 + NOT shift 99 + NULL shift 106 + CASE shift 96 + GROUP_CONCAT shift 107 + '-' shift 102 + '(' shift 87 + . error + primary goto 77 + field_reference goto 76 + value goto 295 + row_value goto 97 + subquery goto 80 + string_operation goto 79 + comparison goto 83 + arithmetic goto 78 + logic goto 84 + function goto 81 + group_concat goto 95 + case goto 82 + identifier goto 88 + text goto 89 + integer goto 90 + float goto 91 + ternary goto 92 + datetime goto 93 + null goto 94 + variable goto 85 + variable_substitution goto 86 state 204 - order_items: order_item. (158) - order_items: order_item.',' order_items + limit_clause: LIMIT value.limit_with + limit_clause: LIMIT value.PERCENT limit_with + string_operation: value.STRING_OP value + comparison: value.COMPARISON_OP value + comparison: value.'=' value + comparison: value.IS negation ternary + comparison: value.IS negation null + comparison: value.negation BETWEEN value AND value + comparison: value.negation IN row_value + comparison: value.negation LIKE value + comparison: value.comparison_operator ANY row_value + comparison: value.comparison_operator ALL row_value + arithmetic: value.'+' value + arithmetic: value.'-' value + arithmetic: value.'*' value + arithmetic: value.'/' value + arithmetic: value.'%' value + logic: value.OR value + logic: value.AND value + limit_with: . (61) + negation: . (235) - ',' shift 291 - . reduce 158 (src line 917) + PERCENT shift 297 + IN reduce 235 (src line 1317) + AND shift 163 + OR shift 162 + NOT shift 164 + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) + IS shift 154 + WITH shift 298 + COMPARISON_OP shift 152 + STRING_OP shift 151 + '=' shift 153 + '+' shift 157 + '-' shift 158 + '*' shift 159 + '/' shift 160 + '%' shift 161 + . reduce 61 (src line 462) + limit_with goto 296 + negation goto 155 + comparison_operator goto 156 state 205 - order_item: value.order_direction + order_by_clause: ORDER BY order_items. (57) + + . reduce 57 (src line 443) + + +state 206 + order_items: order_item. (89) + order_items: order_item.',' order_items + + ',' shift 299 + . reduce 89 (src line 588) + + +state 207 + order_item: order_value.order_direction + order_item: order_value.order_direction NULLS order_null_position + order_direction: . (95) + + ASC shift 301 + DESC shift 302 + . reduce 95 (src line 618) + + order_direction goto 300 + +state 208 + order_value: value. (93) string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -2878,17 +3019,14 @@ state 205 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - order_direction: . (87) - negation: . (222) + negation: . (235) - ASC shift 293 - DESC shift 294 - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -2898,23 +3036,28 @@ state 205 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 87 (src line 574) + . reduce 93 (src line 608) negation goto 155 - order_direction goto 292 comparison_operator goto 156 -state 206 +state 209 + order_value: analytic_function. (94) + + . reduce 94 (src line 613) + + +state 210 insert_query: INSERT INTO identifier VALUES.row_values - '(' shift 263 + '(' shift 267 . error - row_value goto 296 - row_values goto 295 - subquery goto 264 + row_value goto 304 + row_values goto 303 + subquery goto 268 -state 207 +state 211 subquery: '('.select_query ')' insert_query: INSERT INTO identifier '('.field_references ')' VALUES row_values insert_query: INSERT INTO identifier '('.field_references ')' select_query @@ -2928,108 +3071,108 @@ state 207 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 - field_reference goto 298 + field_reference goto 306 subquery goto 40 - field_references goto 297 - identifier goto 212 + field_references goto 305 + identifier goto 216 -state 208 - insert_query: INSERT INTO identifier select_query. (172) +state 212 + insert_query: INSERT INTO identifier select_query. (185) - . reduce 172 (src line 986) + . reduce 185 (src line 1056) -state 209 +state 213 update_query: UPDATE identified_tables SET update_set_list.from_clause where_clause from_clause: . (48) FROM shift 115 - . reduce 48 (src line 392) + . reduce 48 (src line 398) - from_clause goto 299 + from_clause goto 307 -state 210 - update_set_list: update_set. (176) +state 214 + update_set_list: update_set. (189) update_set_list: update_set.',' update_set_list - ',' shift 300 - . reduce 176 (src line 1007) + ',' shift 308 + . reduce 189 (src line 1077) -state 211 +state 215 update_set: field_reference.'=' value - '=' shift 301 + '=' shift 309 . error -state 212 - field_reference: identifier. (68) +state 216 + field_reference: identifier. (71) field_reference: identifier.'.' identifier '.' shift 168 - . reduce 68 (src line 488) + . reduce 71 (src line 508) -state 213 - identified_tables: identified_table ',' identified_tables. (163) +state 217 + identified_tables: identified_table ',' identified_tables. (176) - . reduce 163 (src line 942) + . reduce 176 (src line 1012) -state 214 - identified_table: identifier AS identifier. (128) +state 218 + identified_table: identifier AS identifier. (142) - . reduce 128 (src line 774) + . reduce 142 (src line 850) -state 215 - delete_query: DELETE FROM tables where_clause. (178) +state 219 + delete_query: DELETE FROM tables where_clause. (191) - . reduce 178 (src line 1017) + . reduce 191 (src line 1087) -state 216 +state 220 join: table join_inner.JOIN table join_condition - JOIN shift 302 + JOIN shift 310 . error - 217: reduce/reduce conflict (red'ns 224 and 228) on JOIN -state 217 + 221: reduce/reduce conflict (red'ns 237 and 241) on JOIN +state 221 join: table NATURAL.join_inner JOIN table join: table NATURAL.join_direction join_outer JOIN table - join_inner: . (224) - join_direction: . (228) + join_inner: . (237) + join_direction: . (241) - INNER shift 221 - OUTER reduce 228 (src line 1277) - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - . reduce 224 (src line 1257) + INNER shift 225 + OUTER reduce 241 (src line 1347) + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + . reduce 237 (src line 1327) - join_inner goto 303 - join_direction goto 304 + join_inner goto 311 + join_direction goto 312 -state 218 +state 222 join: table join_direction.join_outer JOIN table join_condition - join_outer: . (226) + join_outer: . (239) - OUTER shift 306 - . reduce 226 (src line 1267) + OUTER shift 314 + . reduce 239 (src line 1337) - join_outer goto 305 + join_outer goto 313 -state 219 +state 223 join: table CROSS.JOIN table - JOIN shift 307 + JOIN shift 315 . error -state 220 +state 224 tables: table ','.tables IDENTIFIER shift 59 @@ -3043,103 +3186,103 @@ state 220 virtual_table goto 134 table goto 132 join goto 135 - tables goto 308 + tables goto 316 identifier goto 58 -state 221 - join_inner: INNER. (225) +state 225 + join_inner: INNER. (238) - . reduce 225 (src line 1262) + . reduce 238 (src line 1332) -state 222 - join_direction: LEFT. (229) +state 226 + join_direction: LEFT. (242) - . reduce 229 (src line 1282) + . reduce 242 (src line 1352) -state 223 - join_direction: RIGHT. (230) +state 227 + join_direction: RIGHT. (243) - . reduce 230 (src line 1286) + . reduce 243 (src line 1356) -state 224 - join_direction: FULL. (231) +state 228 + join_direction: FULL. (244) - . reduce 231 (src line 1290) + . reduce 244 (src line 1360) -state 225 - table: virtual_table identifier. (133) +state 229 + table: virtual_table identifier. (147) - . reduce 133 (src line 798) + . reduce 147 (src line 874) -state 226 +state 230 table: virtual_table AS.identifier IDENTIFIER shift 59 . error - identifier goto 309 + identifier goto 317 -state 227 +state 231 delete_query: DELETE identified_tables FROM tables.where_clause where_clause: . (50) WHERE shift 187 - . reduce 50 (src line 402) + . reduce 50 (src line 408) - where_clause goto 310 + where_clause goto 318 -state 228 +state 232 create_table: CREATE TABLE identifier '('.using_fields ')' IDENTIFIER shift 59 . error - using_fields goto 311 - identifier goto 312 + using_fields goto 319 + identifier goto 320 -state 229 +state 233 add_columns: ALTER TABLE identifier ADD.column_default column_position add_columns: ALTER TABLE identifier ADD.'(' column_defaults ')' column_position IDENTIFIER shift 59 - '(' shift 314 + '(' shift 322 . error - column_default goto 313 - identifier goto 315 + column_default goto 321 + identifier goto 323 -state 230 +state 234 drop_columns: ALTER TABLE identifier DROP.field_reference drop_columns: ALTER TABLE identifier DROP.'(' field_references ')' IDENTIFIER shift 59 - '(' shift 317 + '(' shift 325 . error - field_reference goto 316 - identifier goto 212 + field_reference goto 324 + identifier goto 216 -state 231 +state 235 rename_column: ALTER TABLE identifier RENAME.field_reference TO identifier IDENTIFIER shift 59 . error - field_reference goto 318 - identifier goto 212 + field_reference goto 326 + identifier goto 216 -state 232 - variable_assignments: variable_assignment ',' variable_assignments. (219) +state 236 + variable_assignments: variable_assignment ',' variable_assignments. (232) - . reduce 219 (src line 1232) + . reduce 232 (src line 1302) -state 233 +state 237 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3157,15 +3300,15 @@ state 233 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - variable_assignment: VARIABLE SUBSTITUTION_OP value. (217) - negation: . (222) + variable_assignment: VARIABLE SUBSTITUTION_OP value. (230) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -3175,59 +3318,59 @@ state 233 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 217 (src line 1222) + . reduce 230 (src line 1292) negation goto 155 comparison_operator goto 156 -state 234 +state 238 cursor_statement: DECLARE identifier CURSOR FOR.select_query statement_terminal SELECT shift 39 '(' shift 42 . error - select_query goto 319 + select_query goto 327 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 subquery goto 40 -state 235 +state 239 cursor_statement: FETCH identifier INTO variables.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 320 + statement_terminal goto 328 -state 236 - variables: variable. (213) +state 240 + variables: variable. (226) variables: variable.',' variables ',' shift 183 - . reduce 213 (src line 1201) + . reduce 226 (src line 1271) -state 237 +state 241 flow_control_statement: IF value THEN program.else END IF statement_terminal flow_control_statement: IF value THEN program.elseif else END IF statement_terminal - else: . (197) + else: . (210) - ELSEIF shift 324 - ELSE shift 323 - . reduce 197 (src line 1113) + ELSEIF shift 332 + ELSE shift 331 + . reduce 210 (src line 1183) - elseif goto 322 - else goto 321 + elseif goto 330 + else goto 329 - 238: reduce/reduce conflict (red'ns 91 and 222) on IN - 238: reduce/reduce conflict (red'ns 91 and 222) on BETWEEN - 238: reduce/reduce conflict (red'ns 91 and 222) on LIKE -state 238 + 242: reduce/reduce conflict (red'ns 101 and 235) on IN + 242: reduce/reduce conflict (red'ns 101 and 235) on BETWEEN + 242: reduce/reduce conflict (red'ns 101 and 235) on LIKE +state 242 string_operation: value.STRING_OP value - string_operation: value STRING_OP value. (91) + string_operation: value STRING_OP value. (101) comparison: value.COMPARISON_OP value comparison: value.'=' value comparison: value.IS negation ternary @@ -3244,25 +3387,25 @@ state 238 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) '+' shift 157 '-' shift 158 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 91 (src line 594) + . reduce 101 (src line 648) negation goto 155 comparison_operator goto 156 - 239: reduce/reduce conflict (red'ns 92 and 222) on IN - 239: reduce/reduce conflict (red'ns 92 and 222) on BETWEEN - 239: reduce/reduce conflict (red'ns 92 and 222) on LIKE -state 239 + 243: reduce/reduce conflict (red'ns 102 and 235) on IN + 243: reduce/reduce conflict (red'ns 102 and 235) on BETWEEN + 243: reduce/reduce conflict (red'ns 102 and 235) on LIKE +state 243 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value - comparison: value COMPARISON_OP value. (92) + comparison: value COMPARISON_OP value. (102) comparison: value.'=' value comparison: value.IS negation ternary comparison: value.IS negation null @@ -3278,7 +3421,7 @@ state 239 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) IS error COMPARISON_OP error @@ -3289,19 +3432,19 @@ state 239 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 92 (src line 617) + . reduce 102 (src line 671) negation goto 155 comparison_operator goto 156 - 240: reduce/reduce conflict (red'ns 94 and 222) on IN - 240: reduce/reduce conflict (red'ns 94 and 222) on BETWEEN - 240: reduce/reduce conflict (red'ns 94 and 222) on LIKE -state 240 + 244: reduce/reduce conflict (red'ns 104 and 235) on IN + 244: reduce/reduce conflict (red'ns 104 and 235) on BETWEEN + 244: reduce/reduce conflict (red'ns 104 and 235) on LIKE +state 244 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value - comparison: value '=' value. (94) + comparison: value '=' value. (104) comparison: value.IS negation ternary comparison: value.IS negation null comparison: value.negation BETWEEN value AND value @@ -3316,7 +3459,7 @@ state 240 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) IS error COMPARISON_OP error @@ -3327,12 +3470,12 @@ state 240 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 94 (src line 626) + . reduce 104 (src line 680) negation goto 155 comparison_operator goto 156 -state 241 +state 245 comparison: value IS negation.ternary comparison: value IS negation.null @@ -3340,10 +3483,10 @@ state 241 NULL shift 106 . error - ternary goto 325 - null goto 326 + ternary goto 333 + null goto 334 -state 242 +state 246 comparison: value negation BETWEEN.value AND value IDENTIFIER shift 59 @@ -3364,7 +3507,7 @@ state 242 primary goto 77 field_reference goto 76 - value goto 327 + value goto 335 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -3384,16 +3527,16 @@ state 242 variable goto 85 variable_substitution goto 86 -state 243 +state 247 comparison: value negation IN.row_value - '(' shift 263 + '(' shift 267 . error - row_value goto 328 - subquery goto 264 + row_value goto 336 + subquery goto 268 -state 244 +state 248 comparison: value negation LIKE.value IDENTIFIER shift 59 @@ -3414,7 +3557,7 @@ state 244 primary goto 77 field_reference goto 76 - value goto 329 + value goto 337 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -3434,28 +3577,28 @@ state 244 variable goto 85 variable_substitution goto 86 -state 245 +state 249 comparison: value comparison_operator ANY.row_value - '(' shift 263 + '(' shift 267 . error - row_value goto 330 - subquery goto 264 + row_value goto 338 + subquery goto 268 -state 246 +state 250 comparison: value comparison_operator ALL.row_value - '(' shift 263 + '(' shift 267 . error - row_value goto 331 - subquery goto 264 + row_value goto 339 + subquery goto 268 - 247: reduce/reduce conflict (red'ns 111 and 222) on IN - 247: reduce/reduce conflict (red'ns 111 and 222) on BETWEEN - 247: reduce/reduce conflict (red'ns 111 and 222) on LIKE -state 247 + 251: reduce/reduce conflict (red'ns 121 and 235) on IN + 251: reduce/reduce conflict (red'ns 121 and 235) on BETWEEN + 251: reduce/reduce conflict (red'ns 121 and 235) on LIKE +state 251 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3467,27 +3610,27 @@ state 247 comparison: value.comparison_operator ANY row_value comparison: value.comparison_operator ALL row_value arithmetic: value.'+' value - arithmetic: value '+' value. (111) + arithmetic: value '+' value. (121) arithmetic: value.'-' value arithmetic: value.'*' value arithmetic: value.'/' value arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 111 (src line 695) + . reduce 121 (src line 749) negation goto 155 comparison_operator goto 156 - 248: reduce/reduce conflict (red'ns 112 and 222) on IN - 248: reduce/reduce conflict (red'ns 112 and 222) on BETWEEN - 248: reduce/reduce conflict (red'ns 112 and 222) on LIKE -state 248 + 252: reduce/reduce conflict (red'ns 122 and 235) on IN + 252: reduce/reduce conflict (red'ns 122 and 235) on BETWEEN + 252: reduce/reduce conflict (red'ns 122 and 235) on LIKE +state 252 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3500,26 +3643,26 @@ state 248 comparison: value.comparison_operator ALL row_value arithmetic: value.'+' value arithmetic: value.'-' value - arithmetic: value '-' value. (112) + arithmetic: value '-' value. (122) arithmetic: value.'*' value arithmetic: value.'/' value arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 112 (src line 700) + . reduce 122 (src line 754) negation goto 155 comparison_operator goto 156 - 249: reduce/reduce conflict (red'ns 113 and 222) on IN - 249: reduce/reduce conflict (red'ns 113 and 222) on BETWEEN - 249: reduce/reduce conflict (red'ns 113 and 222) on LIKE -state 249 + 253: reduce/reduce conflict (red'ns 123 and 235) on IN + 253: reduce/reduce conflict (red'ns 123 and 235) on BETWEEN + 253: reduce/reduce conflict (red'ns 123 and 235) on LIKE +state 253 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3533,22 +3676,22 @@ state 249 arithmetic: value.'+' value arithmetic: value.'-' value arithmetic: value.'*' value - arithmetic: value '*' value. (113) + arithmetic: value '*' value. (123) arithmetic: value.'/' value arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - . reduce 113 (src line 704) + . reduce 123 (src line 758) negation goto 155 comparison_operator goto 156 - 250: reduce/reduce conflict (red'ns 114 and 222) on IN - 250: reduce/reduce conflict (red'ns 114 and 222) on BETWEEN - 250: reduce/reduce conflict (red'ns 114 and 222) on LIKE -state 250 + 254: reduce/reduce conflict (red'ns 124 and 235) on IN + 254: reduce/reduce conflict (red'ns 124 and 235) on BETWEEN + 254: reduce/reduce conflict (red'ns 124 and 235) on LIKE +state 254 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3563,21 +3706,21 @@ state 250 arithmetic: value.'-' value arithmetic: value.'*' value arithmetic: value.'/' value - arithmetic: value '/' value. (114) + arithmetic: value '/' value. (124) arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - . reduce 114 (src line 708) + . reduce 124 (src line 762) negation goto 155 comparison_operator goto 156 - 251: reduce/reduce conflict (red'ns 115 and 222) on IN - 251: reduce/reduce conflict (red'ns 115 and 222) on BETWEEN - 251: reduce/reduce conflict (red'ns 115 and 222) on LIKE -state 251 + 255: reduce/reduce conflict (red'ns 125 and 235) on IN + 255: reduce/reduce conflict (red'ns 125 and 235) on BETWEEN + 255: reduce/reduce conflict (red'ns 125 and 235) on LIKE +state 255 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3593,20 +3736,20 @@ state 251 arithmetic: value.'*' value arithmetic: value.'/' value arithmetic: value.'%' value - arithmetic: value '%' value. (115) + arithmetic: value '%' value. (125) logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - . reduce 115 (src line 712) + . reduce 125 (src line 766) negation goto 155 comparison_operator goto 156 - 252: reduce/reduce conflict (red'ns 116 and 222) on IN - 252: reduce/reduce conflict (red'ns 116 and 222) on BETWEEN - 252: reduce/reduce conflict (red'ns 116 and 222) on LIKE -state 252 + 256: reduce/reduce conflict (red'ns 126 and 235) on IN + 256: reduce/reduce conflict (red'ns 126 and 235) on BETWEEN + 256: reduce/reduce conflict (red'ns 126 and 235) on LIKE +state 256 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3623,9 +3766,9 @@ state 252 arithmetic: value.'/' value arithmetic: value.'%' value logic: value.OR value - logic: value OR value. (116) + logic: value OR value. (126) logic: value.AND value - negation: . (222) + negation: . (235) AND shift 163 NOT shift 164 @@ -3638,15 +3781,15 @@ state 252 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 116 (src line 717) + . reduce 126 (src line 771) negation goto 155 comparison_operator goto 156 - 253: reduce/reduce conflict (red'ns 117 and 222) on IN - 253: reduce/reduce conflict (red'ns 117 and 222) on BETWEEN - 253: reduce/reduce conflict (red'ns 117 and 222) on LIKE -state 253 + 257: reduce/reduce conflict (red'ns 127 and 235) on IN + 257: reduce/reduce conflict (red'ns 127 and 235) on BETWEEN + 257: reduce/reduce conflict (red'ns 127 and 235) on LIKE +state 257 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -3664,8 +3807,8 @@ state 253 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - logic: value AND value. (117) - negation: . (222) + logic: value AND value. (127) + negation: . (235) NOT shift 164 IS shift 154 @@ -3677,18 +3820,18 @@ state 253 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 117 (src line 722) + . reduce 127 (src line 776) negation goto 155 comparison_operator goto 156 -state 254 - value: '(' value ')'. (81) +state 258 + value: '(' value ')'. (84) - . reduce 81 (src line 543) + . reduce 84 (src line 563) -state 255 +state 259 values: value ','.values IDENTIFIER shift 59 @@ -3709,7 +3852,7 @@ state 255 primary goto 77 field_reference goto 76 - value goto 333 + value goto 341 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -3719,7 +3862,7 @@ state 255 function goto 81 group_concat goto 95 case goto 82 - values goto 332 + values goto 340 identifier goto 88 text goto 89 integer goto 90 @@ -3730,26 +3873,26 @@ state 255 variable goto 85 variable_substitution goto 86 -state 256 - row_value: '(' values ')'. (82) +state 260 + row_value: '(' values ')'. (85) - . reduce 82 (src line 548) + . reduce 85 (src line 568) -state 257 - field_reference: identifier '.' identifier. (69) +state 261 + field_reference: identifier '.' identifier. (72) - . reduce 69 (src line 493) + . reduce 72 (src line 513) -state 258 +state 262 function: identifier '(' option.')' - ')' shift 334 + ')' shift 342 . error -state 259 +state 263 option: distinct.'*' option: distinct.values @@ -3766,13 +3909,13 @@ state 259 CASE shift 96 GROUP_CONCAT shift 107 '-' shift 102 - '*' shift 335 + '*' shift 343 '(' shift 87 . error primary goto 77 field_reference goto 76 - value goto 333 + value goto 341 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -3782,7 +3925,7 @@ state 259 function goto 81 group_concat goto 95 case goto 82 - values goto 336 + values goto 344 identifier goto 88 text goto 89 integer goto 90 @@ -3793,19 +3936,19 @@ state 259 variable goto 85 variable_substitution goto 86 -state 260 +state 264 case: CASE case_value case_when.case_else END case_when: case_when.case_when - case_else: . (152) + case_else: . (167) - WHEN shift 261 - ELSE shift 339 - . reduce 152 (src line 887) + WHEN shift 265 + ELSE shift 347 + . reduce 167 (src line 967) - case_else goto 337 - case_when goto 338 + case_else goto 345 + case_when goto 346 -state 261 +state 265 case_when: WHEN.value THEN value IDENTIFIER shift 59 @@ -3826,7 +3969,7 @@ state 261 primary goto 77 field_reference goto 76 - value goto 340 + value goto 348 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -3846,13 +3989,13 @@ state 261 variable goto 85 variable_substitution goto 86 -state 262 - comparison: row_value COMPARISON_OP row_value. (93) +state 266 + comparison: row_value COMPARISON_OP row_value. (103) - . reduce 93 (src line 622) + . reduce 103 (src line 676) -state 263 +state 267 row_value: '('.values ')' subquery: '('.select_query ')' @@ -3879,7 +4022,7 @@ state 263 select_clause goto 36 primary goto 77 field_reference goto 76 - value goto 333 + value goto 341 row_value goto 97 subquery goto 167 string_operation goto 79 @@ -3900,72 +4043,72 @@ state 263 variable goto 85 variable_substitution goto 86 -state 264 - row_value: subquery. (83) +state 268 + row_value: subquery. (86) - . reduce 83 (src line 553) + . reduce 86 (src line 573) -state 265 - comparison: row_value '=' row_value. (95) +state 269 + comparison: row_value '=' row_value. (105) - . reduce 95 (src line 630) + . reduce 105 (src line 684) -state 266 +state 270 comparison: row_value negation BETWEEN.row_value AND row_value - '(' shift 263 + '(' shift 267 . error - row_value goto 341 - subquery goto 264 + row_value goto 349 + subquery goto 268 -state 267 +state 271 comparison: row_value negation IN.'(' row_values ')' comparison: row_value negation IN.subquery - '(' shift 342 + '(' shift 350 . error - subquery goto 343 + subquery goto 351 -state 268 +state 272 comparison: row_value comparison_operator ANY.'(' row_values ')' comparison: row_value comparison_operator ANY.subquery - '(' shift 344 + '(' shift 352 . error - subquery goto 345 + subquery goto 353 -state 269 +state 273 comparison: row_value comparison_operator ALL.'(' row_values ')' comparison: row_value comparison_operator ALL.subquery - '(' shift 346 + '(' shift 354 . error - subquery goto 347 + subquery goto 355 -state 270 +state 274 group_concat: GROUP_CONCAT '(' option.order_by_clause ')' group_concat: GROUP_CONCAT '(' option.order_by_clause SEPARATOR STRING ')' order_by_clause: . (56) ORDER shift 54 - . reduce 56 (src line 432) + . reduce 56 (src line 438) - order_by_clause goto 348 + order_by_clause goto 356 -state 271 +state 275 flow_control_statement: WHILE value DO in_loop_program.END WHILE statement_terminal - END shift 349 + END shift 357 . error -state 272 +state 276 in_loop_program: in_loop_statement.in_loop_program in_loop_program: . (3) @@ -3977,7 +4120,7 @@ state 272 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -3986,22 +4129,22 @@ state 272 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 3 (src line 158) + . reduce 3 (src line 164) - in_loop_program goto 350 - statement goto 273 - in_loop_statement goto 272 + in_loop_program goto 358 + statement goto 277 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -4018,19 +4161,19 @@ state 272 variable goto 38 variable_substitution goto 23 -state 273 +state 277 in_loop_statement: statement. (18) - . reduce 18 (src line 224) + . reduce 18 (src line 230) -state 274 +state 278 in_loop_statement: in_loop_flow_control_statement. (19) - . reduce 19 (src line 229) + . reduce 19 (src line 235) -state 275 +state 279 flow_control_statement: IF.value THEN program else END IF statement_terminal flow_control_statement: IF.value THEN program elseif else END IF statement_terminal in_loop_flow_control_statement: IF.value THEN in_loop_program in_loop_else END IF statement_terminal @@ -4054,7 +4197,7 @@ state 275 primary goto 77 field_reference goto 76 - value goto 351 + value goto 359 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -4074,63 +4217,63 @@ state 275 variable goto 85 variable_substitution goto 86 -state 276 +state 280 in_loop_flow_control_statement: CONTINUE.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 352 + statement_terminal goto 360 -state 277 +state 281 in_loop_flow_control_statement: BREAK.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 353 + statement_terminal goto 361 -state 278 +state 282 flow_control_statement: WHILE variables IN identifier.DO in_loop_program END WHILE statement_terminal - DO shift 354 + DO shift 362 . error -state 279 - variables: variable ',' variables. (214) +state 283 + variables: variable ',' variables. (227) - . reduce 214 (src line 1206) + . reduce 227 (src line 1276) -state 280 +state 284 command_statement: SET FLAG '=' primary.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 355 + statement_terminal goto 363 -state 281 +state 285 select_entity: select_clause from_clause where_clause group_by_clause.having_clause having_clause: . (54) - HAVING shift 357 - . reduce 54 (src line 422) + HAVING shift 365 + . reduce 54 (src line 428) - having_clause goto 356 + having_clause goto 364 -state 282 +state 286 group_by_clause: GROUP.BY values - BY shift 358 + BY shift 366 . error -state 283 +state 287 where_clause: WHERE value. (51) string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value @@ -4149,14 +4292,14 @@ state 283 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -4166,47 +4309,47 @@ state 283 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 51 (src line 407) + . reduce 51 (src line 413) negation goto 155 comparison_operator goto 156 -state 284 +state 288 select_entity: select_set_entity.UNION all select_set_entity select_entity: select_set_entity UNION all select_set_entity. (42) select_entity: select_set_entity.INTERSECT all select_set_entity select_entity: select_set_entity.EXCEPT all select_set_entity INTERSECT shift 117 - . reduce 42 (src line 348) + . reduce 42 (src line 354) -state 285 +state 289 select_set_entity: select_entity. (45) - . reduce 45 (src line 376) + . reduce 45 (src line 382) -state 286 +state 290 select_entity: select_set_entity.UNION all select_set_entity select_entity: select_set_entity.INTERSECT all select_set_entity select_entity: select_set_entity INTERSECT all select_set_entity. (43) select_entity: select_set_entity.EXCEPT all select_set_entity - . reduce 43 (src line 357) + . reduce 43 (src line 363) -state 287 +state 291 select_entity: select_set_entity.UNION all select_set_entity select_entity: select_set_entity.INTERSECT all select_set_entity select_entity: select_set_entity.EXCEPT all select_set_entity select_entity: select_set_entity EXCEPT all select_set_entity. (44) INTERSECT shift 117 - . reduce 44 (src line 366) + . reduce 44 (src line 372) -state 288 +state 292 fields: field ','.fields IDENTIFIER shift 59 @@ -4222,7 +4365,7 @@ state 288 CASE shift 96 GROUP_CONCAT shift 107 '-' shift 102 - '*' shift 198 + '*' shift 199 '(' shift 87 . error @@ -4237,11 +4380,12 @@ state 288 logic goto 84 function goto 81 group_concat goto 95 + analytic_function goto 198 field_object goto 196 field goto 195 case goto 82 - fields goto 359 - identifier goto 88 + fields goto 367 + identifier goto 200 text goto 89 integer goto 90 float goto 91 @@ -4251,21 +4395,91 @@ state 288 variable goto 85 variable_substitution goto 86 -state 289 +state 293 field: field_object AS.identifier IDENTIFIER shift 59 . error - identifier goto 360 + identifier goto 368 -state 290 - offset_clause: OFFSET INTEGER. (61) +state 294 + function: identifier '('.option ')' + analytic_function: identifier '('.option ')' OVER '(' analytic_clause ')' + option: . (131) + distinct: . (233) - . reduce 61 (src line 457) + DISTINCT shift 121 + ')' reduce 131 (src line 795) + . reduce 233 (src line 1307) + option goto 369 + distinct goto 263 -state 291 +state 295 + offset_clause: OFFSET value. (64) + string_operation: value.STRING_OP value + comparison: value.COMPARISON_OP value + comparison: value.'=' value + comparison: value.IS negation ternary + comparison: value.IS negation null + comparison: value.negation BETWEEN value AND value + comparison: value.negation IN row_value + comparison: value.negation LIKE value + comparison: value.comparison_operator ANY row_value + comparison: value.comparison_operator ALL row_value + arithmetic: value.'+' value + arithmetic: value.'-' value + arithmetic: value.'*' value + arithmetic: value.'/' value + arithmetic: value.'%' value + logic: value.OR value + logic: value.AND value + negation: . (235) + + IN reduce 235 (src line 1317) + AND shift 163 + OR shift 162 + NOT shift 164 + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) + IS shift 154 + COMPARISON_OP shift 152 + STRING_OP shift 151 + '=' shift 153 + '+' shift 157 + '-' shift 158 + '*' shift 159 + '/' shift 160 + '%' shift 161 + . reduce 64 (src line 477) + + negation goto 155 + comparison_operator goto 156 + +state 296 + limit_clause: LIMIT value limit_with. (59) + + . reduce 59 (src line 453) + + +state 297 + limit_clause: LIMIT value PERCENT.limit_with + limit_with: . (61) + + WITH shift 298 + . reduce 61 (src line 462) + + limit_with goto 370 + +state 298 + limit_with: WITH.TIES + + TIES shift 371 + . error + + +state 299 order_items: order_item ','.order_items IDENTIFIER shift 59 @@ -4286,9 +4500,11 @@ state 291 primary goto 77 field_reference goto 76 - value goto 205 + value goto 208 row_value goto 97 - order_item goto 204 + order_items goto 372 + order_item goto 206 + order_value goto 207 subquery goto 80 string_operation goto 79 comparison goto 83 @@ -4296,9 +4512,9 @@ state 291 logic goto 84 function goto 81 group_concat goto 95 + analytic_function goto 209 case goto 82 - order_items goto 361 - identifier goto 88 + identifier goto 200 text goto 89 integer goto 90 float goto 91 @@ -4308,75 +4524,77 @@ state 291 variable goto 85 variable_substitution goto 86 -state 292 - order_item: value order_direction. (86) +state 300 + order_item: order_value order_direction. (91) + order_item: order_value order_direction.NULLS order_null_position - . reduce 86 (src line 568) + NULLS shift 373 + . reduce 91 (src line 598) -state 293 - order_direction: ASC. (88) +state 301 + order_direction: ASC. (96) - . reduce 88 (src line 579) + . reduce 96 (src line 623) -state 294 - order_direction: DESC. (89) +state 302 + order_direction: DESC. (97) - . reduce 89 (src line 583) + . reduce 97 (src line 627) -state 295 - insert_query: INSERT INTO identifier VALUES row_values. (170) +state 303 + insert_query: INSERT INTO identifier VALUES row_values. (183) - . reduce 170 (src line 977) + . reduce 183 (src line 1047) -state 296 - row_values: row_value. (84) +state 304 + row_values: row_value. (87) row_values: row_value.',' row_values - ',' shift 362 - . reduce 84 (src line 558) + ',' shift 374 + . reduce 87 (src line 578) -state 297 +state 305 insert_query: INSERT INTO identifier '(' field_references.')' VALUES row_values insert_query: INSERT INTO identifier '(' field_references.')' select_query - ')' shift 363 + ')' shift 375 . error -state 298 - field_references: field_reference. (154) +state 306 + field_references: field_reference. (169) field_references: field_reference.',' field_references - ',' shift 364 - . reduce 154 (src line 897) + ',' shift 376 + . reduce 169 (src line 977) -state 299 +state 307 update_query: UPDATE identified_tables SET update_set_list from_clause.where_clause where_clause: . (50) WHERE shift 187 - . reduce 50 (src line 402) + . reduce 50 (src line 408) - where_clause goto 365 + where_clause goto 377 -state 300 +state 308 update_set_list: update_set ','.update_set_list IDENTIFIER shift 59 . error - field_reference goto 211 - update_set goto 210 - update_set_list goto 366 - identifier goto 212 + field_reference goto 215 + update_set goto 214 + update_set_list goto 378 + identifier goto 216 -state 301 +state 309 update_set: field_reference '='.value IDENTIFIER shift 59 @@ -4397,7 +4615,7 @@ state 301 primary goto 77 field_reference goto 76 - value goto 367 + value goto 379 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -4417,7 +4635,7 @@ state 301 variable goto 85 variable_substitution goto 86 -state 302 +state 310 join: table join_inner JOIN.table join_condition IDENTIFIER shift 59 @@ -4429,40 +4647,40 @@ state 302 subquery goto 137 identified_table goto 133 virtual_table goto 134 - table goto 368 + table goto 380 join goto 135 identifier goto 58 -state 303 +state 311 join: table NATURAL join_inner.JOIN table - JOIN shift 369 + JOIN shift 381 . error -state 304 +state 312 join: table NATURAL join_direction.join_outer JOIN table - join_outer: . (226) + join_outer: . (239) - OUTER shift 306 - . reduce 226 (src line 1267) + OUTER shift 314 + . reduce 239 (src line 1337) - join_outer goto 370 + join_outer goto 382 -state 305 +state 313 join: table join_direction join_outer.JOIN table join_condition - JOIN shift 371 + JOIN shift 383 . error -state 306 - join_outer: OUTER. (227) +state 314 + join_outer: OUTER. (240) - . reduce 227 (src line 1272) + . reduce 240 (src line 1342) -state 307 +state 315 join: table CROSS JOIN.table IDENTIFIER shift 59 @@ -4474,131 +4692,131 @@ state 307 subquery goto 137 identified_table goto 133 virtual_table goto 134 - table goto 372 + table goto 384 join goto 135 identifier goto 58 -state 308 - tables: table ',' tables. (161) +state 316 + tables: table ',' tables. (174) - . reduce 161 (src line 932) + . reduce 174 (src line 1002) -state 309 - table: virtual_table AS identifier. (134) +state 317 + table: virtual_table AS identifier. (148) - . reduce 134 (src line 802) + . reduce 148 (src line 878) -state 310 - delete_query: DELETE identified_tables FROM tables where_clause. (179) +state 318 + delete_query: DELETE identified_tables FROM tables where_clause. (192) - . reduce 179 (src line 1023) + . reduce 192 (src line 1093) -state 311 +state 319 create_table: CREATE TABLE identifier '(' using_fields.')' - ')' shift 373 + ')' shift 385 . error -state 312 - using_fields: identifier. (164) +state 320 + using_fields: identifier. (177) using_fields: identifier.',' using_fields - ',' shift 374 - . reduce 164 (src line 947) + ',' shift 386 + . reduce 177 (src line 1017) -state 313 +state 321 add_columns: ALTER TABLE identifier ADD column_default.column_position - column_position: . (187) + column_position: . (200) - FIRST shift 376 - LAST shift 377 - AFTER shift 378 - BEFORE shift 379 - . reduce 187 (src line 1065) + FIRST shift 388 + LAST shift 389 + AFTER shift 390 + BEFORE shift 391 + . reduce 200 (src line 1135) - column_position goto 375 + column_position goto 387 -state 314 +state 322 add_columns: ALTER TABLE identifier ADD '('.column_defaults ')' column_position IDENTIFIER shift 59 . error - column_default goto 381 - column_defaults goto 380 - identifier goto 315 + column_default goto 393 + column_defaults goto 392 + identifier goto 323 -state 315 - column_default: identifier. (183) +state 323 + column_default: identifier. (196) column_default: identifier.DEFAULT value - DEFAULT shift 382 - . reduce 183 (src line 1045) + DEFAULT shift 394 + . reduce 196 (src line 1115) -state 316 - drop_columns: ALTER TABLE identifier DROP field_reference. (192) +state 324 + drop_columns: ALTER TABLE identifier DROP field_reference. (205) - . reduce 192 (src line 1087) + . reduce 205 (src line 1157) -state 317 +state 325 drop_columns: ALTER TABLE identifier DROP '('.field_references ')' IDENTIFIER shift 59 . error - field_reference goto 298 - field_references goto 383 - identifier goto 212 + field_reference goto 306 + field_references goto 395 + identifier goto 216 -state 318 +state 326 rename_column: ALTER TABLE identifier RENAME field_reference.TO identifier - TO shift 384 + TO shift 396 . error -state 319 +state 327 cursor_statement: DECLARE identifier CURSOR FOR select_query.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 385 + statement_terminal goto 397 -state 320 +state 328 cursor_statement: FETCH identifier INTO variables statement_terminal. (28) - . reduce 28 (src line 271) + . reduce 28 (src line 277) -state 321 +state 329 flow_control_statement: IF value THEN program else.END IF statement_terminal - END shift 386 + END shift 398 . error -state 322 +state 330 flow_control_statement: IF value THEN program elseif.else END IF statement_terminal elseif: elseif.elseif - else: . (197) + else: . (210) - ELSEIF shift 324 - ELSE shift 323 - . reduce 197 (src line 1113) + ELSEIF shift 332 + ELSE shift 331 + . reduce 210 (src line 1183) - elseif goto 388 - else goto 387 + elseif goto 400 + else goto 399 -state 323 +state 331 else: ELSE.program program: . (1) @@ -4623,9 +4841,9 @@ state 323 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) - program goto 389 + program goto 401 statement goto 2 variable_statement goto 11 transaction_statement goto 12 @@ -4647,7 +4865,7 @@ state 323 variable goto 38 variable_substitution goto 23 -state 324 +state 332 elseif: ELSEIF.value THEN program IDENTIFIER shift 59 @@ -4668,7 +4886,7 @@ state 324 primary goto 77 field_reference goto 76 - value goto 390 + value goto 402 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -4688,19 +4906,19 @@ state 324 variable goto 85 variable_substitution goto 86 -state 325 - comparison: value IS negation ternary. (96) +state 333 + comparison: value IS negation ternary. (106) - . reduce 96 (src line 634) + . reduce 106 (src line 688) -state 326 - comparison: value IS negation null. (97) +state 334 + comparison: value IS negation null. (107) - . reduce 97 (src line 638) + . reduce 107 (src line 692) -state 327 +state 335 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -4719,9 +4937,9 @@ state 327 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - AND shift 391 + AND shift 403 OR shift 162 NOT shift 164 IS shift 154 @@ -4733,21 +4951,21 @@ state 327 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 328 - comparison: value negation IN row_value. (100) +state 336 + comparison: value negation IN row_value. (110) - . reduce 100 (src line 650) + . reduce 110 (src line 704) - 329: reduce/reduce conflict (red'ns 103 and 222) on IN - 329: reduce/reduce conflict (red'ns 103 and 222) on BETWEEN - 329: reduce/reduce conflict (red'ns 103 and 222) on LIKE -state 329 + 337: reduce/reduce conflict (red'ns 113 and 235) on IN + 337: reduce/reduce conflict (red'ns 113 and 235) on BETWEEN + 337: reduce/reduce conflict (red'ns 113 and 235) on LIKE +state 337 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -4756,7 +4974,7 @@ state 329 comparison: value.negation BETWEEN value AND value comparison: value.negation IN row_value comparison: value.negation LIKE value - comparison: value negation LIKE value. (103) + comparison: value negation LIKE value. (113) comparison: value.comparison_operator ANY row_value comparison: value.comparison_operator ALL row_value arithmetic: value.'+' value @@ -4766,7 +4984,7 @@ state 329 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) IS error COMPARISON_OP error @@ -4777,30 +4995,30 @@ state 329 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 103 (src line 662) + . reduce 113 (src line 716) negation goto 155 comparison_operator goto 156 -state 330 - comparison: value comparison_operator ANY row_value. (104) +state 338 + comparison: value comparison_operator ANY row_value. (114) - . reduce 104 (src line 666) + . reduce 114 (src line 720) -state 331 - comparison: value comparison_operator ALL row_value. (107) +state 339 + comparison: value comparison_operator ALL row_value. (117) - . reduce 107 (src line 678) + . reduce 117 (src line 732) -state 332 - values: value ',' values. (157) +state 340 + values: value ',' values. (172) - . reduce 157 (src line 912) + . reduce 172 (src line 992) -state 333 +state 341 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -4818,16 +5036,16 @@ state 333 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - values: value. (156) + values: value. (171) values: value.',' values - negation: . (222) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -4837,48 +5055,48 @@ state 333 '*' shift 159 '/' shift 160 '%' shift 161 - ',' shift 255 - . reduce 156 (src line 907) + ',' shift 259 + . reduce 171 (src line 987) negation goto 155 comparison_operator goto 156 -state 334 - function: identifier '(' option ')'. (119) +state 342 + function: identifier '(' option ')'. (129) - . reduce 119 (src line 731) + . reduce 129 (src line 785) -state 335 - option: distinct '*'. (122) +state 343 + option: distinct '*'. (132) - . reduce 122 (src line 746) + . reduce 132 (src line 800) -state 336 - option: distinct values. (123) +state 344 + option: distinct values. (133) - . reduce 123 (src line 750) + . reduce 133 (src line 804) -state 337 +state 345 case: CASE case_value case_when case_else.END - END shift 392 + END shift 404 . error -338: shift/reduce conflict (shift 261(0), red'n 169(0)) on WHEN -state 338 +346: shift/reduce conflict (shift 265(0), red'n 182(0)) on WHEN +state 346 case_when: case_when.case_when - case_when: case_when case_when. (169) + case_when: case_when case_when. (182) - WHEN shift 261 - . reduce 169 (src line 972) + WHEN shift 265 + . reduce 182 (src line 1042) - case_when goto 338 + case_when goto 346 -state 339 +state 347 case_else: ELSE.value IDENTIFIER shift 59 @@ -4899,7 +5117,7 @@ state 339 primary goto 77 field_reference goto 76 - value goto 393 + value goto 405 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -4919,7 +5137,7 @@ state 339 variable goto 85 variable_substitution goto 86 -state 340 +state 348 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -4938,13 +5156,13 @@ state 340 logic: value.OR value logic: value.AND value case_when: WHEN value.THEN value - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - THEN shift 394 + THEN shift 406 COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -4953,107 +5171,107 @@ state 340 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 341 +state 349 comparison: row_value negation BETWEEN row_value.AND row_value - AND shift 395 + AND shift 407 . error -state 342 +state 350 subquery: '('.select_query ')' comparison: row_value negation IN '('.row_values ')' SELECT shift 39 - '(' shift 263 + '(' shift 267 . error select_query goto 122 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 - row_value goto 296 - row_values goto 396 - subquery goto 397 + row_value goto 304 + row_values goto 408 + subquery goto 409 -state 343 - comparison: row_value negation IN subquery. (102) +state 351 + comparison: row_value negation IN subquery. (112) - . reduce 102 (src line 658) + . reduce 112 (src line 712) -state 344 +state 352 subquery: '('.select_query ')' comparison: row_value comparison_operator ANY '('.row_values ')' SELECT shift 39 - '(' shift 263 + '(' shift 267 . error select_query goto 122 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 - row_value goto 296 - row_values goto 398 - subquery goto 397 + row_value goto 304 + row_values goto 410 + subquery goto 409 -state 345 - comparison: row_value comparison_operator ANY subquery. (106) +state 353 + comparison: row_value comparison_operator ANY subquery. (116) - . reduce 106 (src line 674) + . reduce 116 (src line 728) -state 346 +state 354 subquery: '('.select_query ')' comparison: row_value comparison_operator ALL '('.row_values ')' SELECT shift 39 - '(' shift 263 + '(' shift 267 . error select_query goto 122 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 - row_value goto 296 - row_values goto 399 - subquery goto 397 + row_value goto 304 + row_values goto 411 + subquery goto 409 -state 347 - comparison: row_value comparison_operator ALL subquery. (109) +state 355 + comparison: row_value comparison_operator ALL subquery. (119) - . reduce 109 (src line 686) + . reduce 119 (src line 740) -state 348 +state 356 group_concat: GROUP_CONCAT '(' option order_by_clause.')' group_concat: GROUP_CONCAT '(' option order_by_clause.SEPARATOR STRING ')' - SEPARATOR shift 401 - ')' shift 400 + SEPARATOR shift 413 + ')' shift 412 . error -state 349 +state 357 flow_control_statement: WHILE value DO in_loop_program END.WHILE statement_terminal - WHILE shift 402 + WHILE shift 414 . error -state 350 +state 358 in_loop_program: in_loop_statement in_loop_program. (4) - . reduce 4 (src line 164) + . reduce 4 (src line 170) -state 351 +state 359 flow_control_statement: IF value.THEN program else END IF statement_terminal flow_control_statement: IF value.THEN program elseif else END IF statement_terminal in_loop_flow_control_statement: IF value.THEN in_loop_program in_loop_else END IF statement_terminal @@ -5075,13 +5293,13 @@ state 351 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - THEN shift 403 + THEN shift 415 COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -5090,24 +5308,24 @@ state 351 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 352 +state 360 in_loop_flow_control_statement: CONTINUE statement_terminal. (36) - . reduce 36 (src line 307) + . reduce 36 (src line 313) -state 353 +state 361 in_loop_flow_control_statement: BREAK statement_terminal. (37) - . reduce 37 (src line 311) + . reduce 37 (src line 317) -state 354 +state 362 flow_control_statement: WHILE variables IN identifier DO.in_loop_program END WHILE statement_terminal in_loop_program: . (3) @@ -5119,7 +5337,7 @@ state 354 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -5128,22 +5346,22 @@ state 354 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 3 (src line 158) + . reduce 3 (src line 164) - in_loop_program goto 404 - statement goto 273 - in_loop_statement goto 272 + in_loop_program goto 416 + statement goto 277 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -5160,19 +5378,19 @@ state 354 variable goto 38 variable_substitution goto 23 -state 355 +state 363 command_statement: SET FLAG '=' primary statement_terminal. (38) - . reduce 38 (src line 316) + . reduce 38 (src line 322) -state 356 +state 364 select_entity: select_clause from_clause where_clause group_by_clause having_clause. (41) - . reduce 41 (src line 337) + . reduce 41 (src line 343) -state 357 +state 365 having_clause: HAVING.value IDENTIFIER shift 59 @@ -5193,7 +5411,7 @@ state 357 primary goto 77 field_reference goto 76 - value goto 405 + value goto 417 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -5213,7 +5431,7 @@ state 357 variable goto 85 variable_substitution goto 86 -state 358 +state 366 group_by_clause: GROUP BY.values IDENTIFIER shift 59 @@ -5234,7 +5452,7 @@ state 358 primary goto 77 field_reference goto 76 - value goto 333 + value goto 341 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -5244,7 +5462,7 @@ state 358 function goto 81 group_concat goto 95 case goto 82 - values goto 406 + values goto 418 identifier goto 88 text goto 89 integer goto 90 @@ -5255,72 +5473,101 @@ state 358 variable goto 85 variable_substitution goto 86 -state 359 - fields: field ',' fields. (167) +state 367 + fields: field ',' fields. (180) - . reduce 167 (src line 962) + . reduce 180 (src line 1032) -state 360 - field: field_object AS identifier. (148) +state 368 + field: field_object AS identifier. (163) - . reduce 148 (src line 866) + . reduce 163 (src line 946) -state 361 - order_items: order_item ',' order_items. (159) +state 369 + function: identifier '(' option.')' + analytic_function: identifier '(' option.')' OVER '(' analytic_clause ')' - . reduce 159 (src line 922) + ')' shift 419 + . error -state 362 +state 370 + limit_clause: LIMIT value PERCENT limit_with. (60) + + . reduce 60 (src line 457) + + +state 371 + limit_with: WITH TIES. (62) + + . reduce 62 (src line 467) + + +state 372 + order_items: order_item ',' order_items. (90) + + . reduce 90 (src line 593) + + +state 373 + order_item: order_value order_direction NULLS.order_null_position + + FIRST shift 421 + LAST shift 422 + . error + + order_null_position goto 420 + +state 374 row_values: row_value ','.row_values - '(' shift 263 + '(' shift 267 . error - row_value goto 296 - row_values goto 407 - subquery goto 264 + row_value goto 304 + row_values goto 423 + subquery goto 268 -state 363 +state 375 insert_query: INSERT INTO identifier '(' field_references ')'.VALUES row_values insert_query: INSERT INTO identifier '(' field_references ')'.select_query SELECT shift 39 - VALUES shift 408 + VALUES shift 424 '(' shift 42 . error - select_query goto 409 + select_query goto 425 select_entity goto 16 select_set_entity goto 37 select_clause goto 36 subquery goto 40 -state 364 +state 376 field_references: field_reference ','.field_references IDENTIFIER shift 59 . error - field_reference goto 298 - field_references goto 410 - identifier goto 212 + field_reference goto 306 + field_references goto 426 + identifier goto 216 -state 365 - update_query: UPDATE identified_tables SET update_set_list from_clause where_clause. (174) +state 377 + update_query: UPDATE identified_tables SET update_set_list from_clause where_clause. (187) - . reduce 174 (src line 995) + . reduce 187 (src line 1065) -state 366 - update_set_list: update_set ',' update_set_list. (177) +state 378 + update_set_list: update_set ',' update_set_list. (190) - . reduce 177 (src line 1012) + . reduce 190 (src line 1082) -state 367 +state 379 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -5338,15 +5585,15 @@ state 367 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - update_set: field_reference '=' value. (175) - negation: . (222) + update_set: field_reference '=' value. (188) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -5356,48 +5603,48 @@ state 367 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 175 (src line 1001) + . reduce 188 (src line 1071) negation goto 155 comparison_operator goto 156 - 368: reduce/reduce conflict (red'ns 224 and 142) on JOIN -368: shift/reduce conflict (shift 221(0), red'n 142(0)) on INNER -368: shift/reduce conflict (shift 222(0), red'n 142(0)) on LEFT -368: shift/reduce conflict (shift 223(0), red'n 142(0)) on RIGHT -368: shift/reduce conflict (shift 224(0), red'n 142(0)) on FULL -368: shift/reduce conflict (shift 219(0), red'n 142(0)) on CROSS -368: shift/reduce conflict (shift 412(0), red'n 142(0)) on ON -368: shift/reduce conflict (shift 413(0), red'n 142(0)) on USING -368: shift/reduce conflict (shift 217(0), red'n 142(0)) on NATURAL - 368: reduce/reduce conflict (red'ns 142 and 228) on JOIN - 368: reduce/reduce conflict (red'ns 142 and 228) on OUTER -state 368 + 380: reduce/reduce conflict (red'ns 237 and 156) on JOIN +380: shift/reduce conflict (shift 225(0), red'n 156(0)) on INNER +380: shift/reduce conflict (shift 226(0), red'n 156(0)) on LEFT +380: shift/reduce conflict (shift 227(0), red'n 156(0)) on RIGHT +380: shift/reduce conflict (shift 228(0), red'n 156(0)) on FULL +380: shift/reduce conflict (shift 223(0), red'n 156(0)) on CROSS +380: shift/reduce conflict (shift 428(0), red'n 156(0)) on ON +380: shift/reduce conflict (shift 429(0), red'n 156(0)) on USING +380: shift/reduce conflict (shift 221(0), red'n 156(0)) on NATURAL + 380: reduce/reduce conflict (red'ns 156 and 241) on JOIN + 380: reduce/reduce conflict (red'ns 156 and 241) on OUTER +state 380 join: table.join_inner JOIN table join_condition join: table join_inner JOIN table.join_condition join: table.NATURAL join_inner JOIN table join: table.join_direction join_outer JOIN table join_condition join: table.NATURAL join_direction join_outer JOIN table join: table.CROSS JOIN table - join_inner: . (224) - join_condition: . (142) - join_direction: . (228) - - INNER shift 221 - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - ON shift 412 - USING shift 413 - NATURAL shift 217 - . reduce 142 (src line 837) - - join_condition goto 411 - join_inner goto 216 - join_direction goto 218 + join_inner: . (237) + join_condition: . (156) + join_direction: . (241) + + INNER shift 225 + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + ON shift 428 + USING shift 429 + NATURAL shift 221 + . reduce 156 (src line 913) + + join_condition goto 427 + join_inner goto 220 + join_direction goto 222 -state 369 +state 381 join: table NATURAL join_inner JOIN.table IDENTIFIER shift 59 @@ -5409,18 +5656,18 @@ state 369 subquery goto 137 identified_table goto 133 virtual_table goto 134 - table goto 414 + table goto 430 join goto 135 identifier goto 58 -state 370 +state 382 join: table NATURAL join_direction join_outer.JOIN table - JOIN shift 415 + JOIN shift 431 . error -state 371 +state 383 join: table join_direction join_outer JOIN.table join_condition IDENTIFIER shift 59 @@ -5432,107 +5679,107 @@ state 371 subquery goto 137 identified_table goto 133 virtual_table goto 134 - table goto 416 + table goto 432 join goto 135 identifier goto 58 -372: shift/reduce conflict (shift 221(0), red'n 141(0)) on INNER -372: shift/reduce conflict (shift 222(0), red'n 141(0)) on LEFT -372: shift/reduce conflict (shift 223(0), red'n 141(0)) on RIGHT -372: shift/reduce conflict (shift 224(0), red'n 141(0)) on FULL -372: shift/reduce conflict (shift 219(0), red'n 141(0)) on CROSS -372: shift/reduce conflict (shift 217(0), red'n 141(0)) on NATURAL - 372: reduce/reduce conflict (red'ns 141 and 224) on JOIN - 372: reduce/reduce conflict (red'ns 141 and 228) on JOIN - 372: reduce/reduce conflict (red'ns 141 and 228) on OUTER -state 372 +384: shift/reduce conflict (shift 225(0), red'n 155(0)) on INNER +384: shift/reduce conflict (shift 226(0), red'n 155(0)) on LEFT +384: shift/reduce conflict (shift 227(0), red'n 155(0)) on RIGHT +384: shift/reduce conflict (shift 228(0), red'n 155(0)) on FULL +384: shift/reduce conflict (shift 223(0), red'n 155(0)) on CROSS +384: shift/reduce conflict (shift 221(0), red'n 155(0)) on NATURAL + 384: reduce/reduce conflict (red'ns 155 and 237) on JOIN + 384: reduce/reduce conflict (red'ns 155 and 241) on JOIN + 384: reduce/reduce conflict (red'ns 155 and 241) on OUTER +state 384 join: table.join_inner JOIN table join_condition join: table.NATURAL join_inner JOIN table join: table.join_direction join_outer JOIN table join_condition join: table.NATURAL join_direction join_outer JOIN table join: table.CROSS JOIN table - join: table CROSS JOIN table. (141) - join_inner: . (224) - join_direction: . (228) + join: table CROSS JOIN table. (155) + join_inner: . (237) + join_direction: . (241) - INNER shift 221 - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - NATURAL shift 217 - . reduce 141 (src line 832) + INNER shift 225 + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + NATURAL shift 221 + . reduce 155 (src line 908) - join_inner goto 216 - join_direction goto 218 + join_inner goto 220 + join_direction goto 222 -state 373 - create_table: CREATE TABLE identifier '(' using_fields ')'. (180) +state 385 + create_table: CREATE TABLE identifier '(' using_fields ')'. (193) - . reduce 180 (src line 1029) + . reduce 193 (src line 1099) -state 374 +state 386 using_fields: identifier ','.using_fields IDENTIFIER shift 59 . error - using_fields goto 417 - identifier goto 312 + using_fields goto 433 + identifier goto 320 -state 375 - add_columns: ALTER TABLE identifier ADD column_default column_position. (181) +state 387 + add_columns: ALTER TABLE identifier ADD column_default column_position. (194) - . reduce 181 (src line 1035) + . reduce 194 (src line 1105) -state 376 - column_position: FIRST. (188) +state 388 + column_position: FIRST. (201) - . reduce 188 (src line 1070) + . reduce 201 (src line 1140) -state 377 - column_position: LAST. (189) +state 389 + column_position: LAST. (202) - . reduce 189 (src line 1074) + . reduce 202 (src line 1144) -state 378 +state 390 column_position: AFTER.field_reference IDENTIFIER shift 59 . error - field_reference goto 418 - identifier goto 212 + field_reference goto 434 + identifier goto 216 -state 379 +state 391 column_position: BEFORE.field_reference IDENTIFIER shift 59 . error - field_reference goto 419 - identifier goto 212 + field_reference goto 435 + identifier goto 216 -state 380 +state 392 add_columns: ALTER TABLE identifier ADD '(' column_defaults.')' column_position - ')' shift 420 + ')' shift 436 . error -state 381 - column_defaults: column_default. (185) +state 393 + column_defaults: column_default. (198) column_defaults: column_default.',' column_defaults - ',' shift 421 - . reduce 185 (src line 1055) + ',' shift 437 + . reduce 198 (src line 1125) -state 382 +state 394 column_default: identifier DEFAULT.value IDENTIFIER shift 59 @@ -5553,7 +5800,7 @@ state 382 primary goto 77 field_reference goto 76 - value goto 422 + value goto 438 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -5573,58 +5820,58 @@ state 382 variable goto 85 variable_substitution goto 86 -state 383 +state 395 drop_columns: ALTER TABLE identifier DROP '(' field_references.')' - ')' shift 423 + ')' shift 439 . error -state 384 +state 396 rename_column: ALTER TABLE identifier RENAME field_reference TO.identifier IDENTIFIER shift 59 . error - identifier goto 424 + identifier goto 440 -state 385 +state 397 cursor_statement: DECLARE identifier CURSOR FOR select_query statement_terminal. (24) - . reduce 24 (src line 254) + . reduce 24 (src line 260) -state 386 +state 398 flow_control_statement: IF value THEN program else END.IF statement_terminal - IF shift 425 + IF shift 441 . error -state 387 +state 399 flow_control_statement: IF value THEN program elseif else.END IF statement_terminal - END shift 426 + END shift 442 . error -388: shift/reduce conflict (shift 324(0), red'n 196(0)) on ELSEIF -state 388 +400: shift/reduce conflict (shift 332(0), red'n 209(0)) on ELSEIF +state 400 elseif: elseif.elseif - elseif: elseif elseif. (196) + elseif: elseif elseif. (209) - ELSEIF shift 324 - . reduce 196 (src line 1108) + ELSEIF shift 332 + . reduce 209 (src line 1178) - elseif goto 388 + elseif goto 400 -state 389 - else: ELSE program. (198) +state 401 + else: ELSE program. (211) - . reduce 198 (src line 1118) + . reduce 211 (src line 1188) -state 390 +state 402 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -5643,13 +5890,13 @@ state 390 logic: value.OR value logic: value.AND value elseif: ELSEIF value.THEN program - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - THEN shift 427 + THEN shift 443 COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -5658,12 +5905,12 @@ state 390 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 391 +state 403 comparison: value negation BETWEEN value AND.value logic: value AND.value @@ -5685,7 +5932,7 @@ state 391 primary goto 77 field_reference goto 76 - value goto 428 + value goto 444 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -5705,13 +5952,13 @@ state 391 variable goto 85 variable_substitution goto 86 -state 392 - case: CASE case_value case_when case_else END. (149) +state 404 + case: CASE case_value case_when case_else END. (164) - . reduce 149 (src line 871) + . reduce 164 (src line 951) -state 393 +state 405 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -5729,14 +5976,14 @@ state 393 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - case_else: ELSE value. (153) - negation: . (222) + case_else: ELSE value. (168) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - END reduce 153 (src line 892) + END reduce 168 (src line 972) COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -5745,12 +5992,12 @@ state 393 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 394 +state 406 case_when: WHEN value THEN.value IDENTIFIER shift 59 @@ -5771,7 +6018,7 @@ state 394 primary goto 77 field_reference goto 76 - value goto 429 + value goto 445 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -5791,71 +6038,71 @@ state 394 variable goto 85 variable_substitution goto 86 -state 395 +state 407 comparison: row_value negation BETWEEN row_value AND.row_value - '(' shift 263 + '(' shift 267 . error - row_value goto 430 - subquery goto 264 + row_value goto 446 + subquery goto 268 -state 396 +state 408 comparison: row_value negation IN '(' row_values.')' - ')' shift 431 + ')' shift 447 . error -state 397 +state 409 select_set_entity: subquery. (46) - row_value: subquery. (83) + row_value: subquery. (86) - ')' reduce 83 (src line 553) - ',' reduce 83 (src line 553) - . reduce 46 (src line 381) + ')' reduce 86 (src line 573) + ',' reduce 86 (src line 573) + . reduce 46 (src line 387) -state 398 +state 410 comparison: row_value comparison_operator ANY '(' row_values.')' - ')' shift 432 + ')' shift 448 . error -state 399 +state 411 comparison: row_value comparison_operator ALL '(' row_values.')' - ')' shift 433 + ')' shift 449 . error -state 400 - group_concat: GROUP_CONCAT '(' option order_by_clause ')'. (124) +state 412 + group_concat: GROUP_CONCAT '(' option order_by_clause ')'. (134) - . reduce 124 (src line 755) + . reduce 134 (src line 809) -state 401 +state 413 group_concat: GROUP_CONCAT '(' option order_by_clause SEPARATOR.STRING ')' - STRING shift 434 + STRING shift 450 . error -state 402 +state 414 flow_control_statement: WHILE value DO in_loop_program END WHILE.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 435 + statement_terminal goto 451 - 403: reduce/reduce conflict (red'ns 1 and 3) on ELSEIF - 403: reduce/reduce conflict (red'ns 1 and 3) on ELSE - 403: reduce/reduce conflict (red'ns 1 and 3) on END -state 403 + 415: reduce/reduce conflict (red'ns 1 and 3) on ELSEIF + 415: reduce/reduce conflict (red'ns 1 and 3) on ELSE + 415: reduce/reduce conflict (red'ns 1 and 3) on END +state 415 flow_control_statement: IF value THEN.program else END IF statement_terminal flow_control_statement: IF value THEN.program elseif else END IF statement_terminal in_loop_flow_control_statement: IF value THEN.in_loop_program in_loop_else END IF statement_terminal @@ -5871,7 +6118,7 @@ state 403 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -5880,23 +6127,23 @@ state 403 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) - program goto 237 - in_loop_program goto 436 - statement goto 437 - in_loop_statement goto 272 + program goto 241 + in_loop_program goto 452 + statement goto 453 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -5913,14 +6160,14 @@ state 403 variable goto 38 variable_substitution goto 23 -state 404 +state 416 flow_control_statement: WHILE variables IN identifier DO in_loop_program.END WHILE statement_terminal - END shift 438 + END shift 454 . error -state 405 +state 417 having_clause: HAVING value. (55) string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value @@ -5939,14 +6186,14 @@ state 405 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - negation: . (222) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -5956,52 +6203,78 @@ state 405 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 55 (src line 427) + . reduce 55 (src line 433) negation goto 155 comparison_operator goto 156 -state 406 +state 418 group_by_clause: GROUP BY values. (53) - . reduce 53 (src line 417) + . reduce 53 (src line 423) -state 407 - row_values: row_value ',' row_values. (85) +state 419 + function: identifier '(' option ')'. (129) + analytic_function: identifier '(' option ')'.OVER '(' analytic_clause ')' - . reduce 85 (src line 563) + OVER shift 455 + . reduce 129 (src line 785) -state 408 +state 420 + order_item: order_value order_direction NULLS order_null_position. (92) + + . reduce 92 (src line 603) + + +state 421 + order_null_position: FIRST. (98) + + . reduce 98 (src line 632) + + +state 422 + order_null_position: LAST. (99) + + . reduce 99 (src line 637) + + +state 423 + row_values: row_value ',' row_values. (88) + + . reduce 88 (src line 583) + + +state 424 insert_query: INSERT INTO identifier '(' field_references ')' VALUES.row_values - '(' shift 263 + '(' shift 267 . error - row_value goto 296 - row_values goto 439 - subquery goto 264 + row_value goto 304 + row_values goto 456 + subquery goto 268 -state 409 - insert_query: INSERT INTO identifier '(' field_references ')' select_query. (173) +state 425 + insert_query: INSERT INTO identifier '(' field_references ')' select_query. (186) - . reduce 173 (src line 990) + . reduce 186 (src line 1060) -state 410 - field_references: field_reference ',' field_references. (155) +state 426 + field_references: field_reference ',' field_references. (170) - . reduce 155 (src line 902) + . reduce 170 (src line 982) -state 411 - join: table join_inner JOIN table join_condition. (137) +state 427 + join: table join_inner JOIN table join_condition. (151) - . reduce 137 (src line 815) + . reduce 151 (src line 891) -state 412 +state 428 join_condition: ON.value IDENTIFIER shift 59 @@ -6022,7 +6295,7 @@ state 412 primary goto 77 field_reference goto 76 - value goto 440 + value goto 457 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -6042,44 +6315,44 @@ state 412 variable goto 85 variable_substitution goto 86 -state 413 +state 429 join_condition: USING.'(' using_fields ')' - '(' shift 441 + '(' shift 458 . error -414: shift/reduce conflict (shift 221(0), red'n 138(0)) on INNER -414: shift/reduce conflict (shift 222(0), red'n 138(0)) on LEFT -414: shift/reduce conflict (shift 223(0), red'n 138(0)) on RIGHT -414: shift/reduce conflict (shift 224(0), red'n 138(0)) on FULL -414: shift/reduce conflict (shift 219(0), red'n 138(0)) on CROSS -414: shift/reduce conflict (shift 217(0), red'n 138(0)) on NATURAL - 414: reduce/reduce conflict (red'ns 138 and 224) on JOIN - 414: reduce/reduce conflict (red'ns 138 and 228) on JOIN - 414: reduce/reduce conflict (red'ns 138 and 228) on OUTER -state 414 +430: shift/reduce conflict (shift 225(0), red'n 152(0)) on INNER +430: shift/reduce conflict (shift 226(0), red'n 152(0)) on LEFT +430: shift/reduce conflict (shift 227(0), red'n 152(0)) on RIGHT +430: shift/reduce conflict (shift 228(0), red'n 152(0)) on FULL +430: shift/reduce conflict (shift 223(0), red'n 152(0)) on CROSS +430: shift/reduce conflict (shift 221(0), red'n 152(0)) on NATURAL + 430: reduce/reduce conflict (red'ns 152 and 237) on JOIN + 430: reduce/reduce conflict (red'ns 152 and 241) on JOIN + 430: reduce/reduce conflict (red'ns 152 and 241) on OUTER +state 430 join: table.join_inner JOIN table join_condition join: table.NATURAL join_inner JOIN table - join: table NATURAL join_inner JOIN table. (138) + join: table NATURAL join_inner JOIN table. (152) join: table.join_direction join_outer JOIN table join_condition join: table.NATURAL join_direction join_outer JOIN table join: table.CROSS JOIN table - join_inner: . (224) - join_direction: . (228) + join_inner: . (237) + join_direction: . (241) - INNER shift 221 - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - NATURAL shift 217 - . reduce 138 (src line 820) + INNER shift 225 + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + NATURAL shift 221 + . reduce 152 (src line 896) - join_inner goto 216 - join_direction goto 218 + join_inner goto 220 + join_direction goto 222 -state 415 +state 431 join: table NATURAL join_direction join_outer JOIN.table IDENTIFIER shift 59 @@ -6091,87 +6364,87 @@ state 415 subquery goto 137 identified_table goto 133 virtual_table goto 134 - table goto 442 + table goto 459 join goto 135 identifier goto 58 - 416: reduce/reduce conflict (red'ns 224 and 228) on JOIN - 416: reduce/reduce conflict (red'ns 224 and 142) on JOIN -416: shift/reduce conflict (shift 221(0), red'n 142(0)) on INNER - 416: reduce/reduce conflict (red'ns 228 and 142) on OUTER -416: shift/reduce conflict (shift 222(0), red'n 142(0)) on LEFT -416: shift/reduce conflict (shift 223(0), red'n 142(0)) on RIGHT -416: shift/reduce conflict (shift 224(0), red'n 142(0)) on FULL -416: shift/reduce conflict (shift 219(0), red'n 142(0)) on CROSS -416: shift/reduce conflict (shift 412(0), red'n 142(0)) on ON -416: shift/reduce conflict (shift 413(0), red'n 142(0)) on USING -416: shift/reduce conflict (shift 217(0), red'n 142(0)) on NATURAL -state 416 + 432: reduce/reduce conflict (red'ns 237 and 241) on JOIN + 432: reduce/reduce conflict (red'ns 237 and 156) on JOIN +432: shift/reduce conflict (shift 225(0), red'n 156(0)) on INNER + 432: reduce/reduce conflict (red'ns 241 and 156) on OUTER +432: shift/reduce conflict (shift 226(0), red'n 156(0)) on LEFT +432: shift/reduce conflict (shift 227(0), red'n 156(0)) on RIGHT +432: shift/reduce conflict (shift 228(0), red'n 156(0)) on FULL +432: shift/reduce conflict (shift 223(0), red'n 156(0)) on CROSS +432: shift/reduce conflict (shift 428(0), red'n 156(0)) on ON +432: shift/reduce conflict (shift 429(0), red'n 156(0)) on USING +432: shift/reduce conflict (shift 221(0), red'n 156(0)) on NATURAL +state 432 join: table.join_inner JOIN table join_condition join: table.NATURAL join_inner JOIN table join: table.join_direction join_outer JOIN table join_condition join: table join_direction join_outer JOIN table.join_condition join: table.NATURAL join_direction join_outer JOIN table join: table.CROSS JOIN table - join_inner: . (224) - join_direction: . (228) - join_condition: . (142) - - INNER shift 221 - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - ON shift 412 - USING shift 413 - NATURAL shift 217 - . reduce 142 (src line 837) - - join_condition goto 443 - join_inner goto 216 - join_direction goto 218 + join_inner: . (237) + join_direction: . (241) + join_condition: . (156) + + INNER shift 225 + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + ON shift 428 + USING shift 429 + NATURAL shift 221 + . reduce 156 (src line 913) + + join_condition goto 460 + join_inner goto 220 + join_direction goto 222 -state 417 - using_fields: identifier ',' using_fields. (165) +state 433 + using_fields: identifier ',' using_fields. (178) - . reduce 165 (src line 952) + . reduce 178 (src line 1022) -state 418 - column_position: AFTER field_reference. (190) +state 434 + column_position: AFTER field_reference. (203) - . reduce 190 (src line 1078) + . reduce 203 (src line 1148) -state 419 - column_position: BEFORE field_reference. (191) +state 435 + column_position: BEFORE field_reference. (204) - . reduce 191 (src line 1082) + . reduce 204 (src line 1152) -state 420 +state 436 add_columns: ALTER TABLE identifier ADD '(' column_defaults ')'.column_position - column_position: . (187) + column_position: . (200) - FIRST shift 376 - LAST shift 377 - AFTER shift 378 - BEFORE shift 379 - . reduce 187 (src line 1065) + FIRST shift 388 + LAST shift 389 + AFTER shift 390 + BEFORE shift 391 + . reduce 200 (src line 1135) - column_position goto 444 + column_position goto 461 -state 421 +state 437 column_defaults: column_default ','.column_defaults IDENTIFIER shift 59 . error - column_default goto 381 - column_defaults goto 445 - identifier goto 315 + column_default goto 393 + column_defaults goto 462 + identifier goto 323 -state 422 +state 438 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -6189,15 +6462,15 @@ state 422 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - column_default: identifier DEFAULT value. (184) - negation: . (222) + column_default: identifier DEFAULT value. (197) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -6207,40 +6480,40 @@ state 422 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 184 (src line 1050) + . reduce 197 (src line 1120) negation goto 155 comparison_operator goto 156 -state 423 - drop_columns: ALTER TABLE identifier DROP '(' field_references ')'. (193) +state 439 + drop_columns: ALTER TABLE identifier DROP '(' field_references ')'. (206) - . reduce 193 (src line 1092) + . reduce 206 (src line 1162) -state 424 - rename_column: ALTER TABLE identifier RENAME field_reference TO identifier. (194) +state 440 + rename_column: ALTER TABLE identifier RENAME field_reference TO identifier. (207) - . reduce 194 (src line 1097) + . reduce 207 (src line 1167) -state 425 +state 441 flow_control_statement: IF value THEN program else END IF.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 446 + statement_terminal goto 463 -state 426 +state 442 flow_control_statement: IF value THEN program elseif else END.IF statement_terminal - IF shift 447 + IF shift 464 . error -state 427 +state 443 elseif: ELSEIF value THEN.program program: . (1) @@ -6265,9 +6538,9 @@ state 427 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) - program goto 448 + program goto 465 statement goto 2 variable_statement goto 11 transaction_statement goto 12 @@ -6289,22 +6562,22 @@ state 427 variable goto 38 variable_substitution goto 23 - 428: reduce/reduce conflict (red'ns 98 and 117) on IN - 428: reduce/reduce conflict (red'ns 98 and 117) on AND - 428: reduce/reduce conflict (red'ns 98 and 117) on OR - 428: reduce/reduce conflict (red'ns 98 and 117) on BETWEEN - 428: reduce/reduce conflict (red'ns 98 and 117) on LIKE - 428: reduce/reduce conflict (red'ns 98 and 222) on IN - 428: reduce/reduce conflict (red'ns 98 and 222) on BETWEEN - 428: reduce/reduce conflict (red'ns 98 and 222) on LIKE -state 428 + 444: reduce/reduce conflict (red'ns 108 and 127) on IN + 444: reduce/reduce conflict (red'ns 108 and 127) on AND + 444: reduce/reduce conflict (red'ns 108 and 127) on OR + 444: reduce/reduce conflict (red'ns 108 and 127) on BETWEEN + 444: reduce/reduce conflict (red'ns 108 and 127) on LIKE + 444: reduce/reduce conflict (red'ns 108 and 235) on IN + 444: reduce/reduce conflict (red'ns 108 and 235) on BETWEEN + 444: reduce/reduce conflict (red'ns 108 and 235) on LIKE +state 444 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value comparison: value.IS negation ternary comparison: value.IS negation null comparison: value.negation BETWEEN value AND value - comparison: value negation BETWEEN value AND value. (98) + comparison: value negation BETWEEN value AND value. (108) comparison: value.negation IN row_value comparison: value.negation LIKE value comparison: value.comparison_operator ANY row_value @@ -6316,8 +6589,8 @@ state 428 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - logic: value AND value. (117) - negation: . (222) + logic: value AND value. (127) + negation: . (235) NOT shift 164 IS shift 154 @@ -6329,12 +6602,12 @@ state 428 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 98 (src line 642) + . reduce 108 (src line 696) negation goto 155 comparison_operator goto 156 -state 429 +state 445 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -6352,16 +6625,16 @@ state 429 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - case_when: WHEN value THEN value. (168) - negation: . (222) + case_when: WHEN value THEN value. (181) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - WHEN reduce 168 (src line 967) - ELSE reduce 168 (src line 967) - END reduce 168 (src line 967) + WHEN reduce 181 (src line 1037) + ELSE reduce 181 (src line 1037) + END reduce 181 (src line 1037) COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -6370,85 +6643,85 @@ state 429 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 430 - comparison: row_value negation BETWEEN row_value AND row_value. (99) +state 446 + comparison: row_value negation BETWEEN row_value AND row_value. (109) - . reduce 99 (src line 646) + . reduce 109 (src line 700) -state 431 - comparison: row_value negation IN '(' row_values ')'. (101) +state 447 + comparison: row_value negation IN '(' row_values ')'. (111) - . reduce 101 (src line 654) + . reduce 111 (src line 708) -state 432 - comparison: row_value comparison_operator ANY '(' row_values ')'. (105) +state 448 + comparison: row_value comparison_operator ANY '(' row_values ')'. (115) - . reduce 105 (src line 670) + . reduce 115 (src line 724) -state 433 - comparison: row_value comparison_operator ALL '(' row_values ')'. (108) +state 449 + comparison: row_value comparison_operator ALL '(' row_values ')'. (118) - . reduce 108 (src line 682) + . reduce 118 (src line 736) -state 434 +state 450 group_concat: GROUP_CONCAT '(' option order_by_clause SEPARATOR STRING.')' - ')' shift 449 + ')' shift 466 . error -state 435 +state 451 flow_control_statement: WHILE value DO in_loop_program END WHILE statement_terminal. (31) - . reduce 31 (src line 285) + . reduce 31 (src line 291) -state 436 +state 452 in_loop_flow_control_statement: IF value THEN in_loop_program.in_loop_else END IF statement_terminal in_loop_flow_control_statement: IF value THEN in_loop_program.in_loop_elseif in_loop_else END IF statement_terminal - in_loop_else: . (201) - - ELSEIF shift 453 - ELSE shift 452 - . reduce 201 (src line 1133) - - in_loop_elseif goto 451 - in_loop_else goto 450 - -437: shift/reduce conflict (shift 41(0), red'n 18(0)) on VARIABLE -437: shift/reduce conflict (shift 39(0), red'n 18(0)) on SELECT -437: shift/reduce conflict (shift 18(0), red'n 18(0)) on UPDATE -437: shift/reduce conflict (shift 34(0), red'n 18(0)) on SET -437: shift/reduce conflict (shift 19(0), red'n 18(0)) on DELETE -437: shift/reduce conflict (shift 17(0), red'n 18(0)) on INSERT -437: shift/reduce conflict (shift 20(0), red'n 18(0)) on CREATE -437: shift/reduce conflict (shift 21(0), red'n 18(0)) on ALTER -437: shift/reduce conflict (shift 31(0), red'n 18(0)) on IF -437: shift/reduce conflict (shift 32(0), red'n 18(0)) on WHILE -437: shift/reduce conflict (shift 26(0), red'n 18(0)) on DECLARE -437: shift/reduce conflict (shift 30(0), red'n 18(0)) on FETCH -437: shift/reduce conflict (shift 27(0), red'n 18(0)) on OPEN -437: shift/reduce conflict (shift 28(0), red'n 18(0)) on CLOSE -437: shift/reduce conflict (shift 29(0), red'n 18(0)) on DISPOSE -437: shift/reduce conflict (shift 24(0), red'n 18(0)) on COMMIT -437: shift/reduce conflict (shift 25(0), red'n 18(0)) on ROLLBACK -437: shift/reduce conflict (shift 33(0), red'n 18(0)) on EXIT -437: shift/reduce conflict (shift 35(0), red'n 18(0)) on PRINT -437: shift/reduce conflict (shift 22(0), red'n 18(0)) on VAR -437: shift/reduce conflict (shift 42(0), red'n 18(0)) on '(' - 437: reduce/reduce conflict (red'ns 18 and 1) on ELSEIF - 437: reduce/reduce conflict (red'ns 18 and 1) on ELSE - 437: reduce/reduce conflict (red'ns 18 and 1) on END -state 437 + in_loop_else: . (214) + + ELSEIF shift 470 + ELSE shift 469 + . reduce 214 (src line 1203) + + in_loop_elseif goto 468 + in_loop_else goto 467 + +453: shift/reduce conflict (shift 41(0), red'n 18(0)) on VARIABLE +453: shift/reduce conflict (shift 39(0), red'n 18(0)) on SELECT +453: shift/reduce conflict (shift 18(0), red'n 18(0)) on UPDATE +453: shift/reduce conflict (shift 34(0), red'n 18(0)) on SET +453: shift/reduce conflict (shift 19(0), red'n 18(0)) on DELETE +453: shift/reduce conflict (shift 17(0), red'n 18(0)) on INSERT +453: shift/reduce conflict (shift 20(0), red'n 18(0)) on CREATE +453: shift/reduce conflict (shift 21(0), red'n 18(0)) on ALTER +453: shift/reduce conflict (shift 31(0), red'n 18(0)) on IF +453: shift/reduce conflict (shift 32(0), red'n 18(0)) on WHILE +453: shift/reduce conflict (shift 26(0), red'n 18(0)) on DECLARE +453: shift/reduce conflict (shift 30(0), red'n 18(0)) on FETCH +453: shift/reduce conflict (shift 27(0), red'n 18(0)) on OPEN +453: shift/reduce conflict (shift 28(0), red'n 18(0)) on CLOSE +453: shift/reduce conflict (shift 29(0), red'n 18(0)) on DISPOSE +453: shift/reduce conflict (shift 24(0), red'n 18(0)) on COMMIT +453: shift/reduce conflict (shift 25(0), red'n 18(0)) on ROLLBACK +453: shift/reduce conflict (shift 33(0), red'n 18(0)) on EXIT +453: shift/reduce conflict (shift 35(0), red'n 18(0)) on PRINT +453: shift/reduce conflict (shift 22(0), red'n 18(0)) on VAR +453: shift/reduce conflict (shift 42(0), red'n 18(0)) on '(' + 453: reduce/reduce conflict (red'ns 18 and 1) on ELSEIF + 453: reduce/reduce conflict (red'ns 18 and 1) on ELSE + 453: reduce/reduce conflict (red'ns 18 and 1) on END +state 453 program: statement.program in_loop_statement: statement. (18) program: . (1) @@ -6470,13 +6743,13 @@ state 437 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE reduce 18 (src line 224) - BREAK reduce 18 (src line 224) + CONTINUE reduce 18 (src line 230) + BREAK reduce 18 (src line 230) EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 1 (src line 146) + . reduce 1 (src line 152) program goto 43 statement goto 2 @@ -6500,20 +6773,27 @@ state 437 variable goto 38 variable_substitution goto 23 -state 438 +state 454 flow_control_statement: WHILE variables IN identifier DO in_loop_program END.WHILE statement_terminal - WHILE shift 454 + WHILE shift 471 . error -state 439 - insert_query: INSERT INTO identifier '(' field_references ')' VALUES row_values. (171) +state 455 + analytic_function: identifier '(' option ')' OVER.'(' analytic_clause ')' + + '(' shift 472 + . error - . reduce 171 (src line 982) +state 456 + insert_query: INSERT INTO identifier '(' field_references ')' VALUES row_values. (184) -state 440 + . reduce 184 (src line 1052) + + +state 457 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -6531,15 +6811,15 @@ state 440 arithmetic: value.'%' value logic: value.OR value logic: value.AND value - join_condition: ON value. (143) - negation: . (222) + join_condition: ON value. (157) + negation: . (235) - IN reduce 222 (src line 1247) + IN reduce 235 (src line 1317) AND shift 163 OR shift 162 NOT shift 164 - BETWEEN reduce 222 (src line 1247) - LIKE reduce 222 (src line 1247) + BETWEEN reduce 235 (src line 1317) + LIKE reduce 235 (src line 1317) IS shift 154 COMPARISON_OP shift 152 STRING_OP shift 151 @@ -6549,115 +6829,115 @@ state 440 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 143 (src line 842) + . reduce 157 (src line 918) negation goto 155 comparison_operator goto 156 -state 441 +state 458 join_condition: USING '('.using_fields ')' IDENTIFIER shift 59 . error - using_fields goto 455 - identifier goto 312 + using_fields goto 473 + identifier goto 320 -442: shift/reduce conflict (shift 221(0), red'n 140(0)) on INNER -442: shift/reduce conflict (shift 222(0), red'n 140(0)) on LEFT -442: shift/reduce conflict (shift 223(0), red'n 140(0)) on RIGHT -442: shift/reduce conflict (shift 224(0), red'n 140(0)) on FULL -442: shift/reduce conflict (shift 219(0), red'n 140(0)) on CROSS -442: shift/reduce conflict (shift 217(0), red'n 140(0)) on NATURAL - 442: reduce/reduce conflict (red'ns 140 and 224) on JOIN - 442: reduce/reduce conflict (red'ns 140 and 228) on JOIN - 442: reduce/reduce conflict (red'ns 140 and 228) on OUTER -state 442 +459: shift/reduce conflict (shift 225(0), red'n 154(0)) on INNER +459: shift/reduce conflict (shift 226(0), red'n 154(0)) on LEFT +459: shift/reduce conflict (shift 227(0), red'n 154(0)) on RIGHT +459: shift/reduce conflict (shift 228(0), red'n 154(0)) on FULL +459: shift/reduce conflict (shift 223(0), red'n 154(0)) on CROSS +459: shift/reduce conflict (shift 221(0), red'n 154(0)) on NATURAL + 459: reduce/reduce conflict (red'ns 154 and 237) on JOIN + 459: reduce/reduce conflict (red'ns 154 and 241) on JOIN + 459: reduce/reduce conflict (red'ns 154 and 241) on OUTER +state 459 join: table.join_inner JOIN table join_condition join: table.NATURAL join_inner JOIN table join: table.join_direction join_outer JOIN table join_condition join: table.NATURAL join_direction join_outer JOIN table - join: table NATURAL join_direction join_outer JOIN table. (140) + join: table NATURAL join_direction join_outer JOIN table. (154) join: table.CROSS JOIN table - join_inner: . (224) - join_direction: . (228) + join_inner: . (237) + join_direction: . (241) - INNER shift 221 - LEFT shift 222 - RIGHT shift 223 - FULL shift 224 - CROSS shift 219 - NATURAL shift 217 - . reduce 140 (src line 828) + INNER shift 225 + LEFT shift 226 + RIGHT shift 227 + FULL shift 228 + CROSS shift 223 + NATURAL shift 221 + . reduce 154 (src line 904) - join_inner goto 216 - join_direction goto 218 + join_inner goto 220 + join_direction goto 222 -state 443 - join: table join_direction join_outer JOIN table join_condition. (139) +state 460 + join: table join_direction join_outer JOIN table join_condition. (153) - . reduce 139 (src line 824) + . reduce 153 (src line 900) -state 444 - add_columns: ALTER TABLE identifier ADD '(' column_defaults ')' column_position. (182) +state 461 + add_columns: ALTER TABLE identifier ADD '(' column_defaults ')' column_position. (195) - . reduce 182 (src line 1040) + . reduce 195 (src line 1110) -state 445 - column_defaults: column_default ',' column_defaults. (186) +state 462 + column_defaults: column_default ',' column_defaults. (199) - . reduce 186 (src line 1060) + . reduce 199 (src line 1130) -state 446 +state 463 flow_control_statement: IF value THEN program else END IF statement_terminal. (29) - . reduce 29 (src line 276) + . reduce 29 (src line 282) -state 447 +state 464 flow_control_statement: IF value THEN program elseif else END IF.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 456 + statement_terminal goto 474 -state 448 - elseif: ELSEIF value THEN program. (195) +state 465 + elseif: ELSEIF value THEN program. (208) - . reduce 195 (src line 1103) + . reduce 208 (src line 1173) -state 449 - group_concat: GROUP_CONCAT '(' option order_by_clause SEPARATOR STRING ')'. (125) +state 466 + group_concat: GROUP_CONCAT '(' option order_by_clause SEPARATOR STRING ')'. (135) - . reduce 125 (src line 760) + . reduce 135 (src line 814) -state 450 +state 467 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_else.END IF statement_terminal - END shift 457 + END shift 475 . error -state 451 +state 468 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_elseif.in_loop_else END IF statement_terminal in_loop_elseif: in_loop_elseif.in_loop_elseif - in_loop_else: . (201) + in_loop_else: . (214) - ELSEIF shift 453 - ELSE shift 452 - . reduce 201 (src line 1133) + ELSEIF shift 470 + ELSE shift 469 + . reduce 214 (src line 1203) - in_loop_elseif goto 459 - in_loop_else goto 458 + in_loop_elseif goto 477 + in_loop_else goto 476 -state 452 +state 469 in_loop_else: ELSE.in_loop_program in_loop_program: . (3) @@ -6669,7 +6949,7 @@ state 452 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -6678,22 +6958,22 @@ state 452 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 3 (src line 158) + . reduce 3 (src line 164) - in_loop_program goto 460 - statement goto 273 - in_loop_statement goto 272 + in_loop_program goto 478 + statement goto 277 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -6710,7 +6990,7 @@ state 452 variable goto 38 variable_substitution goto 23 -state 453 +state 470 in_loop_elseif: ELSEIF.value THEN in_loop_program IDENTIFIER shift 59 @@ -6731,7 +7011,7 @@ state 453 primary goto 77 field_reference goto 76 - value goto 461 + value goto 479 row_value goto 97 subquery goto 80 string_operation goto 79 @@ -6751,59 +7031,69 @@ state 453 variable goto 85 variable_substitution goto 86 -state 454 +state 471 flow_control_statement: WHILE variables IN identifier DO in_loop_program END WHILE.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 462 + statement_terminal goto 480 -state 455 +state 472 + analytic_function: identifier '(' option ')' OVER '('.analytic_clause ')' + partition: . (138) + + PARTITION shift 483 + . reduce 138 (src line 831) + + analytic_clause goto 481 + partition goto 482 + +state 473 join_condition: USING '(' using_fields.')' - ')' shift 463 + ')' shift 484 . error -state 456 +state 474 flow_control_statement: IF value THEN program elseif else END IF statement_terminal. (30) - . reduce 30 (src line 281) + . reduce 30 (src line 287) -state 457 +state 475 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_else END.IF statement_terminal - IF shift 464 + IF shift 485 . error -state 458 +state 476 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_elseif in_loop_else.END IF statement_terminal - END shift 465 + END shift 486 . error -459: shift/reduce conflict (shift 453(0), red'n 200(0)) on ELSEIF -state 459 +477: shift/reduce conflict (shift 470(0), red'n 213(0)) on ELSEIF +state 477 in_loop_elseif: in_loop_elseif.in_loop_elseif - in_loop_elseif: in_loop_elseif in_loop_elseif. (200) + in_loop_elseif: in_loop_elseif in_loop_elseif. (213) - ELSEIF shift 453 - . reduce 200 (src line 1128) + ELSEIF shift 470 + . reduce 213 (src line 1198) - in_loop_elseif goto 459 + in_loop_elseif goto 477 -state 460 - in_loop_else: ELSE in_loop_program. (202) +state 478 + in_loop_else: ELSE in_loop_program. (215) - . reduce 202 (src line 1138) + . reduce 215 (src line 1208) -state 461 +state 479 string_operation: value.STRING_OP value comparison: value.COMPARISON_OP value comparison: value.'=' value @@ -6822,13 +7112,13 @@ state 461 logic: value.OR value logic: value.AND value in_loop_elseif: ELSEIF value.THEN in_loop_program - negation: . (222) + negation: . (235) AND shift 163 OR shift 162 NOT shift 164 IS shift 154 - THEN shift 466 + THEN shift 487 COMPARISON_OP shift 152 STRING_OP shift 151 '=' shift 153 @@ -6837,40 +7127,63 @@ state 461 '*' shift 159 '/' shift 160 '%' shift 161 - . reduce 222 (src line 1247) + . reduce 235 (src line 1317) negation goto 155 comparison_operator goto 156 -state 462 +state 480 flow_control_statement: WHILE variables IN identifier DO in_loop_program END WHILE statement_terminal. (32) - . reduce 32 (src line 289) + . reduce 32 (src line 295) -state 463 - join_condition: USING '(' using_fields ')'. (144) +state 481 + analytic_function: identifier '(' option ')' OVER '(' analytic_clause.')' - . reduce 144 (src line 846) + ')' shift 488 + . error -state 464 +state 482 + analytic_clause: partition.order_by_clause + order_by_clause: . (56) + + ORDER shift 54 + . reduce 56 (src line 438) + + order_by_clause goto 489 + +state 483 + partition: PARTITION.BY values + + BY shift 490 + . error + + +state 484 + join_condition: USING '(' using_fields ')'. (158) + + . reduce 158 (src line 922) + + +state 485 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_else END IF.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 467 + statement_terminal goto 491 -state 465 +state 486 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_elseif in_loop_else END.IF statement_terminal - IF shift 468 + IF shift 492 . error -state 466 +state 487 in_loop_elseif: ELSEIF value THEN.in_loop_program in_loop_program: . (3) @@ -6882,7 +7195,7 @@ state 466 INSERT shift 17 CREATE shift 20 ALTER shift 21 - IF shift 275 + IF shift 279 WHILE shift 32 DECLARE shift 26 FETCH shift 30 @@ -6891,22 +7204,22 @@ state 466 DISPOSE shift 29 COMMIT shift 24 ROLLBACK shift 25 - CONTINUE shift 276 - BREAK shift 277 + CONTINUE shift 280 + BREAK shift 281 EXIT shift 33 PRINT shift 35 VAR shift 22 '(' shift 42 - . reduce 3 (src line 158) + . reduce 3 (src line 164) - in_loop_program goto 469 - statement goto 273 - in_loop_statement goto 272 + in_loop_program goto 493 + statement goto 277 + in_loop_statement goto 276 variable_statement goto 11 transaction_statement goto 12 cursor_statement goto 13 flow_control_statement goto 14 - in_loop_flow_control_statement goto 274 + in_loop_flow_control_statement goto 278 command_statement goto 15 select_query goto 3 select_entity goto 16 @@ -6923,42 +7236,102 @@ state 466 variable goto 38 variable_substitution goto 23 -state 467 +state 488 + analytic_function: identifier '(' option ')' OVER '(' analytic_clause ')'. (136) + + . reduce 136 (src line 819) + + +state 489 + analytic_clause: partition order_by_clause. (137) + + . reduce 137 (src line 825) + + +state 490 + partition: PARTITION BY.values + + IDENTIFIER shift 59 + STRING shift 100 + INTEGER shift 101 + FLOAT shift 103 + TERNARY shift 104 + DATETIME shift 105 + VARIABLE shift 41 + EXISTS shift 98 + NOT shift 99 + NULL shift 106 + CASE shift 96 + GROUP_CONCAT shift 107 + '-' shift 102 + '(' shift 87 + . error + + primary goto 77 + field_reference goto 76 + value goto 341 + row_value goto 97 + subquery goto 80 + string_operation goto 79 + comparison goto 83 + arithmetic goto 78 + logic goto 84 + function goto 81 + group_concat goto 95 + case goto 82 + values goto 494 + identifier goto 88 + text goto 89 + integer goto 90 + float goto 91 + ternary goto 92 + datetime goto 93 + null goto 94 + variable goto 85 + variable_substitution goto 86 + +state 491 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_else END IF statement_terminal. (34) - . reduce 34 (src line 298) + . reduce 34 (src line 304) -state 468 +state 492 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_elseif in_loop_else END IF.statement_terminal - statement_terminal: . (236) + statement_terminal: . (249) ';' shift 45 - . reduce 236 (src line 1315) + . reduce 249 (src line 1385) - statement_terminal goto 470 + statement_terminal goto 495 -state 469 - in_loop_elseif: ELSEIF value THEN in_loop_program. (199) +state 493 + in_loop_elseif: ELSEIF value THEN in_loop_program. (212) - . reduce 199 (src line 1123) + . reduce 212 (src line 1193) -state 470 +state 494 + partition: PARTITION BY values. (139) + + . reduce 139 (src line 836) + + +state 495 in_loop_flow_control_statement: IF value THEN in_loop_program in_loop_elseif in_loop_else END IF statement_terminal. (35) - . reduce 35 (src line 303) - - -109 terminals, 91 nonterminals -238 grammar rules, 471/8000 states -72 shift/reduce, 81 reduce/reduce conflicts reported -140 working sets used -memory: parser 2161/120000 -560 extra closures -1514 shift entries, 62 exceptions -385 goto entries -1127 entries saved by goto default -Optimizer space used: output 1132/120000 -1132 table entries, 263 zero -maximum spread: 109, maximum offset: 468 + . reduce 35 (src line 309) + + +114 terminals, 97 nonterminals +251 grammar rules, 496/8000 states +73 shift/reduce, 81 reduce/reduce conflicts reported +146 working sets used +memory: parser 2303/120000 +580 extra closures +1595 shift entries, 69 exceptions +403 goto entries +1191 entries saved by goto default +Optimizer space used: output 1142/120000 +1142 table entries, 242 zero +maximum spread: 114, maximum offset: 492 diff --git a/lib/parser/parser.y b/lib/parser/parser.y index f780ae70..0b825a09 100644 --- a/lib/parser/parser.y +++ b/lib/parser/parser.y @@ -42,13 +42,18 @@ package parser %type having_clause %type order_by_clause %type limit_clause +%type limit_with %type offset_clause %type primary %type field_reference %type value %type row_value %type row_values +%type order_items %type order_item +%type order_value +%type order_direction +%type order_null_position %type subquery %type string_operation %type comparison @@ -57,6 +62,9 @@ package parser %type function %type option %type group_concat +%type analytic_function +%type analytic_clause +%type partition %type identified_table %type virtual_table %type table @@ -69,7 +77,6 @@ package parser %type case_else %type field_references %type values -%type order_items %type tables %type identified_tables %type using_fields @@ -105,7 +112,6 @@ package parser %type variable_assignments %type distinct %type negation -%type order_direction %type join_inner %type join_outer %type join_direction @@ -116,15 +122,15 @@ package parser %token IDENTIFIER STRING INTEGER FLOAT BOOLEAN TERNARY DATETIME VARIABLE FLAG %token SELECT FROM UPDATE SET DELETE WHERE INSERT INTO VALUES AS DUAL STDIN %token CREATE ADD DROP ALTER TABLE FIRST LAST AFTER BEFORE DEFAULT RENAME TO -%token ORDER GROUP HAVING BY ASC DESC LIMIT OFFSET +%token ORDER GROUP HAVING BY ASC DESC LIMIT OFFSET TIES PERCENT %token JOIN INNER OUTER LEFT RIGHT FULL CROSS ON USING NATURAL %token UNION INTERSECT EXCEPT %token ALL ANY EXISTS IN -%token AND OR NOT BETWEEN LIKE IS NULL +%token AND OR NOT BETWEEN LIKE IS NULL NULLS %token DISTINCT WITH %token CASE IF ELSEIF WHILE WHEN THEN ELSE DO END %token DECLARE CURSOR FOR FETCH OPEN CLOSE DISPOSE -%token GROUP_CONCAT SEPARATOR +%token GROUP_CONCAT SEPARATOR PARTITION OVER %token COMMIT ROLLBACK %token CONTINUE BREAK EXIT %token PRINT @@ -444,9 +450,23 @@ limit_clause { $$ = nil } - | LIMIT INTEGER + | LIMIT value limit_with { - $$ = LimitClause{Limit: $1.Literal, Number: StrToInt64($2.Literal)} + $$ = LimitClause{Limit: $1.Literal, Value: $2, With: $3} + } + | LIMIT value PERCENT limit_with + { + $$ = LimitClause{Limit: $1.Literal, Value: $2, Percent: $3.Literal, With: $4} + } + +limit_with + : + { + $$ = nil + } + | WITH TIES + { + $$ = LimitWith{With: $1.Literal, Type: $2} } offset_clause @@ -454,9 +474,9 @@ offset_clause { $$ = nil } - | OFFSET INTEGER + | OFFSET value { - $$ = OffsetClause{Offset: $1.Literal, Number: StrToInt64($2.Literal)} + $$ = OffsetClause{Offset: $1.Literal, Value: $2} } primary @@ -565,10 +585,34 @@ row_values $$ = append([]Expression{$1}, $3...) } +order_items + : order_item + { + $$ = []Expression{$1} + } + | order_item ',' order_items + { + $$ = append([]Expression{$1}, $3...) + } + order_item - : value order_direction + : order_value order_direction + { + $$ = OrderItem{Value: $1, Direction: $2} + } + | order_value order_direction NULLS order_null_position { - $$ = OrderItem{Item: $1, Direction: $2} + $$ = OrderItem{Value: $1, Direction: $2, Nulls: $3.Literal, Position: $4} + } + +order_value + : value + { + $$ = $1 + } + | analytic_function + { + $$ = $1 } order_direction @@ -585,6 +629,16 @@ order_direction $$ = $1 } +order_null_position + : FIRST + { + $$ = $1 + } + | LAST + { + $$ = $1 + } + subquery : '(' select_query ')' { @@ -762,6 +816,28 @@ group_concat $$ = GroupConcat{GroupConcat: $1.Literal, Option: $3.(Option), OrderBy: $4, SeparatorLit: $5.Literal, Separator: $6.Literal} } +analytic_function + : identifier '(' option ')' OVER '(' analytic_clause ')' + { + $$ = AnalyticFunction{Name: $1.Literal, Option: $3.(Option), Over: $5.Literal, AnalyticClause: $7.(AnalyticClause)} + } + +analytic_clause + : partition order_by_clause + { + $$ = AnalyticClause{Partition: $1, OrderByClause: $2} + } + +partition + : + { + $$ = nil + } + | PARTITION BY values + { + $$ = Partition{PartitionBy: $1.Literal + " " + $2.Literal, Values: $3} + } + identified_table : identifier { @@ -853,6 +929,10 @@ field_object { $$ = $1 } + | analytic_function + { + $$ = $1 + } | '*' { $$ = AllColumns{} @@ -914,16 +994,6 @@ values $$ = append([]Expression{$1}, $3...) } -order_items - : order_item - { - $$ = []Expression{$1} - } - | order_item ',' order_items - { - $$ = append([]Expression{$1}, $3...) - } - tables : table { diff --git a/lib/parser/parser_test.go b/lib/parser/parser_test.go index 0c99f2a9..e6a0e26f 100644 --- a/lib/parser/parser_test.go +++ b/lib/parser/parser_test.go @@ -209,7 +209,7 @@ var parseTests = []struct { " where 1 = 1" + " group by column1, column2 " + " having 1 > 1 " + - " order by column4, column5 desc, column6 asc " + + " order by column4, column5 desc, column6 asc, column7 nulls first, column8 desc nulls last, avg() over () " + " limit 10 " + " offset 10 ", Output: []Statement{ @@ -244,18 +244,65 @@ var parseTests = []struct { OrderByClause: OrderByClause{ OrderBy: "order by", Items: []Expression{ - OrderItem{Item: FieldReference{Column: Identifier{Literal: "column4"}}}, - OrderItem{Item: FieldReference{Column: Identifier{Literal: "column5"}}, Direction: Token{Token: DESC, Literal: "desc"}}, - OrderItem{Item: FieldReference{Column: Identifier{Literal: "column6"}}, Direction: Token{Token: ASC, Literal: "asc"}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column4"}}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column5"}}, Direction: Token{Token: DESC, Literal: "desc"}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column6"}}, Direction: Token{Token: ASC, Literal: "asc"}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column7"}}, Nulls: "nulls", Position: Token{Token: FIRST, Literal: "first"}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column8"}}, Direction: Token{Token: DESC, Literal: "desc"}, Nulls: "nulls", Position: Token{Token: LAST, Literal: "last"}}, + OrderItem{Value: AnalyticFunction{ + Name: "avg", + Option: Option{}, + Over: "over", + AnalyticClause: AnalyticClause{ + Partition: nil, + OrderByClause: nil, + }, + }}, }, }, LimitClause: LimitClause{ - Limit: "limit", - Number: 10, + Limit: "limit", + Value: NewInteger(10), }, OffsetClause: OffsetClause{ Offset: "offset", - Number: 10, + Value: NewInteger(10), + }, + }, + }, + }, + { + Input: "select 1 " + + " from dual " + + " limit 10 percent", + Output: []Statement{ + SelectQuery{ + SelectEntity: SelectEntity{ + SelectClause: SelectClause{Select: "select", Fields: []Expression{Field{Object: NewIntegerFromString("1")}}}, + FromClause: FromClause{From: "from", Tables: []Expression{Table{Object: Dual{Dual: "dual"}}}}, + }, + LimitClause: LimitClause{ + Limit: "limit", + Value: NewInteger(10), + Percent: "percent", + }, + }, + }, + }, + { + Input: "select 1 " + + " from dual " + + " limit 10 with ties", + Output: []Statement{ + SelectQuery{ + SelectEntity: SelectEntity{ + SelectClause: SelectClause{Select: "select", Fields: []Expression{Field{Object: NewIntegerFromString("1")}}}, + FromClause: FromClause{From: "from", Tables: []Expression{Table{Object: Dual{Dual: "dual"}}}}, + }, + LimitClause: LimitClause{ + Limit: "limit", + Value: NewInteger(10), + With: LimitWith{With: "with", Type: Token{Token: TIES, Literal: "ties"}}, }, }, }, @@ -1283,7 +1330,7 @@ var parseTests = []struct { OrderBy: OrderByClause{ OrderBy: "order by", Items: []Expression{ - OrderItem{Item: FieldReference{Column: Identifier{Literal: "column1"}}}, + OrderItem{Value: FieldReference{Column: Identifier{Literal: "column1"}}}, }, }, }}, @@ -1313,6 +1360,64 @@ var parseTests = []struct { }, }, }, + { + Input: "select rank() over (partition by column1 order by column2)", + Output: []Statement{ + SelectQuery{ + SelectEntity: SelectEntity{ + SelectClause: SelectClause{ + Select: "select", + Fields: []Expression{ + Field{Object: AnalyticFunction{ + Name: "rank", + Option: Option{}, + Over: "over", + AnalyticClause: AnalyticClause{ + Partition: Partition{ + PartitionBy: "partition by", + Values: []Expression{ + FieldReference{Column: Identifier{Literal: "column1"}}, + }, + }, + OrderByClause: OrderByClause{ + OrderBy: "order by", + Items: []Expression{ + OrderItem{ + Value: FieldReference{Column: Identifier{Literal: "column2"}}, + }, + }, + }, + }, + }}, + }, + }, + }, + }, + }, + }, + { + Input: "select avg() over ()", + Output: []Statement{ + SelectQuery{ + SelectEntity: SelectEntity{ + SelectClause: SelectClause{ + Select: "select", + Fields: []Expression{ + Field{Object: AnalyticFunction{ + Name: "avg", + Option: Option{}, + Over: "over", + AnalyticClause: AnalyticClause{ + Partition: nil, + OrderByClause: nil, + }, + }}, + }, + }, + }, + }, + }, + }, { Input: "select 1 from table1 cross join table2", Output: []Statement{ diff --git a/lib/query/aggregate.go b/lib/query/aggregate_function.go similarity index 100% rename from lib/query/aggregate.go rename to lib/query/aggregate_function.go diff --git a/lib/query/aggregate_test.go b/lib/query/aggregate_function_test.go similarity index 100% rename from lib/query/aggregate_test.go rename to lib/query/aggregate_function_test.go diff --git a/lib/query/analytic_function.go b/lib/query/analytic_function.go new file mode 100644 index 00000000..7d8a528b --- /dev/null +++ b/lib/query/analytic_function.go @@ -0,0 +1,133 @@ +package query + +import ( + "errors" + + "github.com/mithrandie/csvq/lib/parser" + "github.com/mithrandie/csvq/lib/ternary" +) + +var AnalyticFunctions = map[string]func(*View, []parser.Expression, []partitionValue) error{ + "ROW_NUMBER": RowNumber, + "RANK": Rank, + "DENSE_RANK": DenseRank, +} + +type partitionValue struct { + values []parser.Primary + orderValues []parser.Primary + number float64 + rank float64 +} + +func (pv partitionValue) match(values []parser.Primary) bool { + for i, v := range pv.values { + if EquivalentTo(v, values[i]) != ternary.TRUE { + return false + } + } + return true +} + +func (pv partitionValue) isSameRank(orderValues []parser.Primary) bool { + for i, v := range pv.orderValues { + if EquivalentTo(v, orderValues[i]) != ternary.TRUE { + return false + } + } + return true +} + +type partitionValues []partitionValue + +func (pv partitionValues) searchIndex(values []parser.Primary) int { + for idx, v := range pv { + if v.match(values) { + return idx + } + } + return -1 +} + +func RowNumber(view *View, args []parser.Expression, partitinList []partitionValue) error { + if args != nil { + return errors.New("function ROW_NUMBER takes no argument") + } + + partitions := partitionValues{} + + for i := range view.Records { + var idx int + if idx = partitions.searchIndex(partitinList[i].values); -1 < idx { + partitions[idx].number++ + } else { + partitions = append(partitions, partitionValue{ + values: partitinList[i].values, + number: 1, + }) + idx = len(partitions) - 1 + } + + view.Records[i] = append(view.Records[i], NewCell(parser.NewInteger(int64(partitions[idx].number)))) + } + + return nil +} + +func Rank(view *View, args []parser.Expression, partitinList []partitionValue) error { + if args != nil { + return errors.New("function RANK takes no argument") + } + + partitions := partitionValues{} + + for i := range view.Records { + var idx int + if idx = partitions.searchIndex(partitinList[i].values); -1 < idx { + partitions[idx].number++ + if !partitions[idx].isSameRank(partitinList[i].orderValues) { + partitions[idx].rank = partitions[idx].number + } + } else { + partitions = append(partitions, partitionValue{ + values: partitinList[i].values, + orderValues: partitinList[i].orderValues, + number: 1, + rank: 1, + }) + idx = len(partitions) - 1 + } + + view.Records[i] = append(view.Records[i], NewCell(parser.NewInteger(int64(partitions[idx].rank)))) + } + + return nil +} + +func DenseRank(view *View, args []parser.Expression, partitinList []partitionValue) error { + if args != nil { + return errors.New("function DENSE_RANK takes no argument") + } + + partitions := partitionValues{} + + for i := range view.Records { + var idx int + if idx = partitions.searchIndex(partitinList[i].values); -1 < idx { + if !partitions[idx].isSameRank(partitinList[i].orderValues) { + partitions[idx].rank++ + } + } else { + partitions = append(partitions, partitionValue{ + values: partitinList[i].values, + orderValues: partitinList[i].orderValues, + rank: 1, + }) + idx = len(partitions) - 1 + } + + view.Records[i] = append(view.Records[i], NewCell(parser.NewInteger(int64(partitions[idx].rank)))) + } + + return nil +} diff --git a/lib/query/analytic_function_test.go b/lib/query/analytic_function_test.go new file mode 100644 index 00000000..58d5237b --- /dev/null +++ b/lib/query/analytic_function_test.go @@ -0,0 +1,454 @@ +package query + +import ( + "reflect" + "testing" + + "github.com/mithrandie/csvq/lib/parser" +) + +type analyticFunctionTest struct { + Name string + View *View + Args []parser.Expression + PartitionList []partitionValue + Result *View + Error string +} + +func testAnalyticFunction(t *testing.T, f func(*View, []parser.Expression, []partitionValue) error, tests []analyticFunctionTest) { + for _, v := range tests { + ViewCache.Clear() + err := f(v.View, v.Args, v.PartitionList) + if err != nil { + if len(v.Error) < 1 { + t.Errorf("%s: unexpected error %q", v.Name, err) + } else if err.Error() != v.Error { + t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) + } + continue + } + if 0 < len(v.Error) { + t.Errorf("%s: no error, want error %q", v.Name, v.Error) + continue + } + if !reflect.DeepEqual(v.View, v.Result) { + t.Errorf("%s: result = %q, want %q", v.Name, v.View, v.Result) + } + } +} + +var rowNumberTests = []analyticFunctionTest{ + { + Name: "RowNumber", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + }, + }, + PartitionList: []partitionValue{ + { + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + orderValues: []parser.Primary{parser.NewInteger(2)}, + }, + { + orderValues: []parser.Primary{parser.NewInteger(3)}, + }, + { + orderValues: []parser.Primary{parser.NewInteger(4)}, + }, + { + orderValues: []parser.Primary{parser.NewInteger(5)}, + }, + }, + Result: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + parser.NewInteger(4), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + parser.NewInteger(5), + }), + }, + }, + }, + { + Name: "RowNumber with Partition", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + }, + }, + PartitionList: []partitionValue{ + { + values: []parser.Primary{parser.NewString("a")}, + }, + { + values: []parser.Primary{parser.NewString("a")}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + }, + }, + Result: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + parser.NewInteger(3), + }), + }, + }, + }, + { + Name: "RowNumber Arguments Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + }, + }, + Args: []parser.Expression{ + parser.NewInteger(1), + }, + Error: "function ROW_NUMBER takes no argument", + }, +} + +func TestRowNumber(t *testing.T) { + testAnalyticFunction(t, RowNumber, rowNumberTests) +} + +var rankTests = []analyticFunctionTest{ + { + Name: "Rank", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + }, + }, + PartitionList: []partitionValue{ + { + values: []parser.Primary{parser.NewString("a")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(2)}, + }, + { + values: []parser.Primary{parser.NewString("a")}, + orderValues: []parser.Primary{parser.NewInteger(2)}, + }, + }, + Result: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + }, + }, + }, + { + Name: "Rank Arguments Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + }, + }, + Args: []parser.Expression{ + parser.NewInteger(1), + }, + Error: "function RANK takes no argument", + }, +} + +func TestRank(t *testing.T) { + testAnalyticFunction(t, Rank, rankTests) +} + +var denseRankTests = []analyticFunctionTest{ + { + Name: "DenseRank", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + }, + }, + PartitionList: []partitionValue{ + { + values: []parser.Primary{parser.NewString("a")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(1)}, + }, + { + values: []parser.Primary{parser.NewString("b")}, + orderValues: []parser.Primary{parser.NewInteger(2)}, + }, + { + values: []parser.Primary{parser.NewString("a")}, + orderValues: []parser.Primary{parser.NewInteger(2)}, + }, + }, + Result: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + }, + }, + }, + { + Name: "DenseRank Arguments Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + }, + }, + Args: []parser.Expression{ + parser.NewInteger(1), + }, + Error: "function DENSE_RANK takes no argument", + }, +} + +func TestDenseRank(t *testing.T) { + testAnalyticFunction(t, DenseRank, denseRankTests) +} diff --git a/lib/query/cursor_test.go b/lib/query/cursor_test.go index 8f4b3c29..02f0f1f3 100644 --- a/lib/query/cursor_test.go +++ b/lib/query/cursor_test.go @@ -179,7 +179,7 @@ var cursorMapOpenTests = []struct { { Name: "CursorMap Open Query Error", Key: "cur2", - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } diff --git a/lib/query/error.go b/lib/query/error.go index 0afa81ec..74ad9b9a 100644 --- a/lib/query/error.go +++ b/lib/query/error.go @@ -12,7 +12,7 @@ type IdentificationError struct { } func (e IdentificationError) Error() string { - return fmt.Sprintf("identifier = %s: %s", e.Field.String(), e.Err) + return fmt.Sprintf(e.Err.Error(), e.Field.String()) } type NotGroupedError struct { @@ -25,7 +25,7 @@ func (e NotGroupedError) Error() string { } var ( - ErrFieldAmbiguous = errors.New("field is ambiguous") - ErrFieldNotExist = errors.New("field does not exist") + ErrFieldAmbiguous = errors.New("field %s is ambiguous") + ErrFieldNotExist = errors.New("field %s does not exist") ErrNotGrouped = errors.New("records are not grouped") ) diff --git a/lib/query/filter.go b/lib/query/filter.go index 794e2bcf..7c39b8c4 100644 --- a/lib/query/filter.go +++ b/lib/query/filter.go @@ -95,7 +95,7 @@ func (f Filter) evalFieldReference(expr parser.FieldReference) (parser.Primary, } } if v.View.isGrouped && !v.View.Header[idx].IsGroupKey { - return nil, errors.New(fmt.Sprintf("identifier = %s: field is not a group key", expr)) + return nil, errors.New(fmt.Sprintf("field %s is not a group key", expr)) } p = v.View.Records[v.RecordIndex][idx].Primary() } @@ -370,7 +370,7 @@ func (f Filter) evalFunction(expr parser.Function) (parser.Primary, error) { fn, ok := Functions[name] if !ok { - return nil, errors.New(fmt.Sprintf("function %s is not exist", expr.Name)) + return nil, errors.New(fmt.Sprintf("function %s does not exist", expr.Name)) } if expr.Option.IsDistinct() { @@ -433,15 +433,6 @@ func (f Filter) evalAggregateFunction(expr parser.Function) (parser.Primary, err } func (f Filter) evalGroupConcat(expr parser.GroupConcat) (parser.Primary, error) { - var in = func(list []string, item string) bool { - for _, v := range list { - if v == item { - return true - } - } - return false - } - if !f[0].View.isGrouped { return nil, &NotGroupedError{ Function: expr.GroupConcat, @@ -481,7 +472,7 @@ func (f Filter) evalGroupConcat(expr parser.GroupConcat) (parser.Primary, error) if parser.IsNull(s) { continue } - if expr.Option.IsDistinct() && in(list, s.(parser.String).Value()) { + if expr.Option.IsDistinct() && InStrSlice(s.(parser.String).Value(), list) { continue } list = append(list, s.(parser.String).Value()) @@ -578,16 +569,20 @@ func (f Filter) evalRowValue(expr parser.RowValue) (values []parser.Primary, err return } -func (f Filter) evalValueList(expr parser.ValueList) ([]parser.Primary, error) { - list := make([]parser.Primary, len(expr.Values)) - for i, v := range expr.Values { - s, err := f.Evaluate(v) +func (f Filter) evalValues(exprs []parser.Expression) ([]parser.Primary, error) { + values := make([]parser.Primary, len(exprs)) + for i, v := range exprs { + value, err := f.Evaluate(v) if err != nil { return nil, err } - list[i] = s + values[i] = value } - return list, nil + return values, nil +} + +func (f Filter) evalValueList(expr parser.ValueList) ([]parser.Primary, error) { + return f.evalValues(expr.Values) } func (f Filter) evalRowValueList(expr parser.RowValueList) ([][]parser.Primary, error) { diff --git a/lib/query/filter_test.go b/lib/query/filter_test.go index c4a0506c..cb3c641e 100644 --- a/lib/query/filter_test.go +++ b/lib/query/filter_test.go @@ -77,7 +77,7 @@ var filterEvaluateTests = []struct { }, }, Expr: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, - Error: "identifier = column3: field does not exist", + Error: "field column3 does not exist", }, { Name: "FieldReference FieldAmbigous Error", @@ -100,7 +100,7 @@ var filterEvaluateTests = []struct { }, }, Expr: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, - Error: "identifier = column1: field is ambiguous", + Error: "field column1 is ambiguous", }, { Name: "FieldReference Not Group Key Error", @@ -137,7 +137,7 @@ var filterEvaluateTests = []struct { }, }, Expr: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, - Error: "identifier = column1: field is not a group key", + Error: "field column1 is not a group key", }, { Name: "FieldReference Fields Ambiguous Error with Multiple Tables", @@ -176,7 +176,7 @@ var filterEvaluateTests = []struct { }, }, Expr: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, - Error: "identifier = column1: field is ambiguous", + Error: "field column1 is ambiguous", }, { Name: "Arithmetic", @@ -194,7 +194,7 @@ var filterEvaluateTests = []struct { RHS: parser.NewInteger(2), Operator: '+', }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Arithmetic RHS Error", @@ -203,7 +203,7 @@ var filterEvaluateTests = []struct { RHS: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Operator: '+', }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Concat", @@ -225,7 +225,7 @@ var filterEvaluateTests = []struct { parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Concat Including Null", @@ -254,7 +254,7 @@ var filterEvaluateTests = []struct { RHS: parser.NewInteger(2), Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Comparison RHS Error", @@ -263,7 +263,7 @@ var filterEvaluateTests = []struct { RHS: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Comparison with Row Values", @@ -351,7 +351,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Comparison with Row Value and Subquery Returns No Record", @@ -424,7 +424,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Comparison with Row Values RHS Error", @@ -498,7 +498,7 @@ var filterEvaluateTests = []struct { RHS: parser.NewNull(), Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Is RHS Error", @@ -507,7 +507,7 @@ var filterEvaluateTests = []struct { RHS: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between", @@ -527,7 +527,7 @@ var filterEvaluateTests = []struct { High: parser.NewInteger(3), Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between Low Error", @@ -537,7 +537,7 @@ var filterEvaluateTests = []struct { High: parser.NewInteger(3), Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between High Error", @@ -547,7 +547,7 @@ var filterEvaluateTests = []struct { High: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between with Row Values", @@ -607,7 +607,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between with Row Values Low Error", @@ -637,7 +637,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between with Row Values High Error", @@ -667,7 +667,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Between with Row Values Low Comparison Error", @@ -759,7 +759,7 @@ var filterEvaluateTests = []struct { }, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "In List Error", @@ -776,7 +776,7 @@ var filterEvaluateTests = []struct { }, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "In Subquery", @@ -858,7 +858,7 @@ var filterEvaluateTests = []struct { }, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "In Subquery Returns No Record", @@ -987,7 +987,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "In with Row Values Values Error", @@ -1021,7 +1021,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "In with Row Values Length Not Match Error ", @@ -1108,7 +1108,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "<>"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Any Query Execution Error", @@ -1142,7 +1142,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "<>"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Any Row Value Length Not Match Error", @@ -1224,7 +1224,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "All Query Execution Error", @@ -1258,7 +1258,7 @@ var filterEvaluateTests = []struct { }, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "All Row Value Length Not Match Error", @@ -1304,7 +1304,7 @@ var filterEvaluateTests = []struct { Pattern: parser.NewString("_bc%"), Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Like Pattern Error", @@ -1313,7 +1313,7 @@ var filterEvaluateTests = []struct { Pattern: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Negation: parser.Token{Token: parser.NOT, Literal: "not"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Exists", @@ -1413,7 +1413,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Subquery", @@ -1454,7 +1454,7 @@ var filterEvaluateTests = []struct { }, }, LimitClause: parser.LimitClause{ - Number: 1, + Value: parser.NewInteger(1), }, }, }, @@ -1481,7 +1481,7 @@ var filterEvaluateTests = []struct { }, }, LimitClause: parser.LimitClause{ - Number: 1, + Value: parser.NewInteger(1), }, }, }, @@ -1506,7 +1506,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Subquery Too Many Records Error", @@ -1548,7 +1548,7 @@ var filterEvaluateTests = []struct { }, }, LimitClause: parser.LimitClause{ - Number: 1, + Value: parser.NewInteger(1), }, }, }, @@ -1568,7 +1568,7 @@ var filterEvaluateTests = []struct { Result: parser.NewString("str"), }, { - Name: "Function Is Not Exist", + Name: "Function Not Exist Error", Expr: parser.Function{ Name: "notexist", Option: parser.Option{ @@ -1578,7 +1578,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "function notexist is not exist", + Error: "function notexist does not exist", }, { Name: "Function Option Error", @@ -1896,7 +1896,7 @@ var filterEvaluateTests = []struct { }, OrderBy: parser.OrderByClause{ Items: []parser.Expression{ - parser.OrderItem{Item: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.OrderItem{Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, }, }, Separator: ",", @@ -2075,12 +2075,12 @@ var filterEvaluateTests = []struct { }, OrderBy: parser.OrderByClause{ Items: []parser.Expression{ - parser.OrderItem{Item: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}}, + parser.OrderItem{Value: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}}, }, }, Separator: ",", }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "GroupConcat Function Duplicate Error", @@ -2217,7 +2217,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Case When Condition Error", @@ -2234,7 +2234,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Case When Result Error", @@ -2251,7 +2251,7 @@ var filterEvaluateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Case Else Result Error", @@ -2271,7 +2271,7 @@ var filterEvaluateTests = []struct { Result: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Logic AND", @@ -2306,7 +2306,7 @@ var filterEvaluateTests = []struct { RHS: parser.NewTernary(ternary.FALSE), Operator: parser.Token{Token: parser.AND, Literal: "and"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Logic RHS Error", @@ -2315,7 +2315,7 @@ var filterEvaluateTests = []struct { RHS: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, Operator: parser.Token{Token: parser.AND, Literal: "and"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Variable", diff --git a/lib/query/header.go b/lib/query/header.go index d0345522..ef178996 100644 --- a/lib/query/header.go +++ b/lib/query/header.go @@ -1,6 +1,10 @@ package query -import "github.com/mithrandie/csvq/lib/parser" +import ( + "strings" + + "github.com/mithrandie/csvq/lib/parser" +) const INTERNAL_ID_COLUMN = "@__internal_id" @@ -61,9 +65,10 @@ func MergeHeader(h1 Header, h2 Header) Header { return append(h1, h2...) } -func AddHeaderField(h Header, alias string) (header Header, index int) { +func AddHeaderField(h Header, column string, alias string) (header Header, index int) { header = append(h, HeaderField{ - Alias: alias, + Column: column, + Alias: alias, }) index = header.Len() - 1 return @@ -103,9 +108,9 @@ func (h Header) TableColumnNames() []string { return names } -func (h Header) ContainsAlias(alias string) (int, error) { +func (h Header) ContainsObject(obj parser.Expression) (int, error) { fieldRef := parser.FieldReference{ - Column: parser.Identifier{Literal: alias}, + Column: parser.Identifier{Literal: obj.String()}, } return h.Contains(fieldRef) } @@ -121,11 +126,11 @@ func (h Header) Contains(fieldRef parser.FieldReference) (int, error) { for i, f := range h { if 0 < len(ref) { - if f.Reference != ref || f.Column != column { + if !strings.EqualFold(f.Reference, ref) || !strings.EqualFold(f.Column, column) { continue } } else { - if f.Column != column && f.Alias != column { + if !strings.EqualFold(f.Column, column) && !strings.EqualFold(f.Alias, column) { continue } } diff --git a/lib/query/header_test.go b/lib/query/header_test.go index 7caa4e18..ebb67316 100644 --- a/lib/query/header_test.go +++ b/lib/query/header_test.go @@ -86,13 +86,13 @@ var headerContainsTests = []struct { Ref: parser.FieldReference{ Column: parser.Identifier{Literal: "c1"}, }, - Error: "identifier = c1: field is ambiguous", + Error: "field c1 is ambiguous", }, { Ref: parser.FieldReference{ Column: parser.Identifier{Literal: "d1"}, }, - Error: "identifier = d1: field does not exist", + Error: "field d1 does not exist", }, } diff --git a/lib/query/join_test.go b/lib/query/join_test.go index e6d29f15..6161fa23 100644 --- a/lib/query/join_test.go +++ b/lib/query/join_test.go @@ -295,7 +295,7 @@ var innerJoinTests = []struct { RHS: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.Identifier{Literal: "notexist"}}, Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, - Error: "identifier = table2.notexist: field does not exist", + Error: "field table2.notexist does not exist", }, } @@ -617,7 +617,7 @@ var outerJoinTests = []struct { Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, Direction: parser.LEFT, - Error: "identifier = table1.notexist: field does not exist", + Error: "field table1.notexist does not exist", }, { Name: "Outer Join Direction Undefined", diff --git a/lib/query/main_test.go b/lib/query/main_test.go index 509b7f47..dfd11b94 100644 --- a/lib/query/main_test.go +++ b/lib/query/main_test.go @@ -24,10 +24,14 @@ func GetTestLocation() *time.Location { } func TestMain(m *testing.M) { + os.Exit(run(m)) +} + +func run(m *testing.M) int { + defer teardown() + setup() - r := m.Run() - teardown() - os.Exit(r) + return m.Run() } func setup() { diff --git a/lib/query/query.go b/lib/query/query.go index f8ce5ac7..4b46bb12 100644 --- a/lib/query/query.go +++ b/lib/query/query.go @@ -479,11 +479,15 @@ func Select(query parser.SelectQuery, parentFilter Filter) (*View, error) { } if query.OffsetClause != nil { - view.Offset(query.OffsetClause.(parser.OffsetClause)) + if err := view.Offset(query.OffsetClause.(parser.OffsetClause)); err != nil { + return nil, err + } } if query.LimitClause != nil { - view.Limit(query.LimitClause.(parser.LimitClause)) + if err := view.Limit(query.LimitClause.(parser.LimitClause)); err != nil { + return nil, err + } } view.Fix() diff --git a/lib/query/query_test.go b/lib/query/query_test.go index 6ef5f8a9..1165cd4a 100644 --- a/lib/query/query_test.go +++ b/lib/query/query_test.go @@ -210,6 +210,7 @@ var executeStatementTests = []struct { View: &View{ Header: []HeaderField{ { + Column: "@var1", Alias: "var1", FromTable: true, }, @@ -588,7 +589,7 @@ var ifStmtTests = []struct { parser.TransactionControl{Token: parser.COMMIT}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -796,7 +797,7 @@ var whileTests = []struct { parser.TransactionControl{Token: parser.COMMIT}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "While Statement Execution Error", @@ -819,7 +820,7 @@ var whileTests = []struct { parser.TransactionControl{Token: parser.COMMIT}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -997,7 +998,7 @@ var whileInCursorTests = []struct { parser.TransactionControl{Token: parser.COMMIT}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -1217,14 +1218,14 @@ var selectTests = []struct { }, OrderByClause: parser.OrderByClause{ Items: []parser.Expression{ - parser.OrderItem{Item: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.OrderItem{Value: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, }, }, LimitClause: parser.LimitClause{ - Number: 5, + Value: parser.NewInteger(5), }, OffsetClause: parser.OffsetClause{ - Number: 0, + Value: parser.NewInteger(0), }, }, Result: &View{ @@ -1242,6 +1243,7 @@ var selectTests = []struct { FromTable: true, }, { + Column: "count(*)", Alias: "count(*)", FromTable: true, }, @@ -1573,7 +1575,7 @@ var selectTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Union RHS Error", @@ -1608,7 +1610,7 @@ var selectTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -1820,7 +1822,7 @@ var insertTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Insert Select Query", @@ -2106,7 +2108,7 @@ var updateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Update Query File Is Not Loaded Error", @@ -2168,7 +2170,7 @@ var updateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Update Query Update Value Error", @@ -2192,7 +2194,7 @@ var updateTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Update Query Record Is Ambiguous Error", @@ -2419,7 +2421,7 @@ var deleteTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Delete Query File Is Not Loaded Error", @@ -2777,7 +2779,7 @@ var addColumnsTests = []struct { Column: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Add Columns Field Duplicate Error", @@ -2809,7 +2811,7 @@ var addColumnsTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -2893,7 +2895,7 @@ var dropColumnsTests = []struct { parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -2986,7 +2988,7 @@ var renameColumnTests = []struct { Old: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, New: parser.Identifier{Literal: "newcolumn"}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } diff --git a/lib/query/record.go b/lib/query/record.go index 1b955c49..74946f81 100644 --- a/lib/query/record.go +++ b/lib/query/record.go @@ -63,6 +63,16 @@ func (r Record) IsEqualTo(record Record) bool { return true } +func (r Record) Match(record Record, indices []int) bool { + for _, i := range indices { + if EquivalentTo(r[i].Primary(), record[i].Primary()) != ternary.TRUE { + return false + } + } + + return true +} + func (r Record) GroupLen() int { return r[0].Len() } diff --git a/lib/query/variables_test.go b/lib/query/variables_test.go index c205dd0f..53b58470 100644 --- a/lib/query/variables_test.go +++ b/lib/query/variables_test.go @@ -66,7 +66,7 @@ var variablesDeclareTests = []variableTests{ }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -118,7 +118,7 @@ var variablesSubstituteTests = []variableTests{ Variable: parser.Variable{Name: "var1"}, Value: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } diff --git a/lib/query/view.go b/lib/query/view.go index 0f716293..42b59b53 100644 --- a/lib/query/view.go +++ b/lib/query/view.go @@ -3,6 +3,7 @@ package query import ( "errors" "fmt" + "math" "os" "path" "path/filepath" @@ -184,8 +185,11 @@ type View struct { filteredIndices []int - sortIndices []int - sortDirections []int + sortIndices []int + sortDirections []int + sortNullPositions []int + + offset int OperatedRecords int OperatedFields int @@ -585,33 +589,25 @@ func (view *View) Select(clause parser.SelectClause) error { return append(append(fields[:insertIdx], insert...), fields[insertIdx+1:]...) } - var evalFields = func(view *View, fields []parser.Expression) ([]Record, error) { - records := make([]Record, view.RecordLen()) - for i := range view.Records { - var record Record - var filter Filter = append([]FilterRecord{{View: view, RecordIndex: i}}, view.parentFilter...) - - for _, f := range fields { - field := f.(parser.Field) - primary, err := filter.Evaluate(field.Object) - if err != nil { - return nil, err - } - if _, ok := field.Object.(parser.FieldReference); !ok { - record = append(record, NewCell(primary)) - } + var evalFields = func(view *View, fields []parser.Expression) error { + view.selectFields = make([]int, len(fields)) + for i, f := range fields { + field := f.(parser.Field) + idx, err := view.evalColumn(field.Object, field.Object.String(), field.Name()) + if err != nil { + return err } - records[i] = record + view.selectFields[i] = idx } - return records, nil + return nil } fields := parseAllColumns(view, clause.Fields) - records, err := evalFields(view, fields) + err := evalFields(view, fields) if err != nil { if _, ok := err.(*NotGroupedError); ok { view.group(nil) - records, err = evalFields(view, fields) + err = evalFields(view, fields) if err != nil { return err } @@ -620,26 +616,6 @@ func (view *View) Select(clause parser.SelectClause) error { } } - view.selectFields = make([]int, len(fields)) - for i, f := range fields { - field := f.(parser.Field) - if fieldRef, ok := field.Object.(parser.FieldReference); ok { - idx, err := view.Header.Contains(fieldRef) - if err != nil { - return err - } - view.selectFields[i] = idx - } else { - view.Header, view.selectFields[i] = AddHeaderField(view.Header, field.Name()) - } - } - - for i := range view.Records { - if 0 < len(records[i]) { - view.Records[i] = append(view.Records[i], records[i]...) - } - } - if clause.IsDistinct() { records := make(Records, view.RecordLen()) for i, v := range view.Records { @@ -687,67 +663,192 @@ func (view *View) SelectAllColumns() error { } func (view *View) OrderBy(clause parser.OrderByClause) error { - view.sortIndices = []int{} + view.sortIndices = make([]int, len(clause.Items)) + view.sortDirections = make([]int, len(clause.Items)) + view.sortNullPositions = make([]int, len(clause.Items)) - for _, v := range clause.Items { + for i, v := range clause.Items { oi := v.(parser.OrderItem) - switch oi.Item.(type) { - case parser.FieldReference: - idx, err := view.FieldIndex(oi.Item.(parser.FieldReference)) - if err != nil { - return err + idx, err := view.evalColumn(oi.Value, oi.Value.String(), "") + if err != nil { + return err + } + view.sortIndices[i] = idx + + if oi.Direction.IsEmpty() { + view.sortDirections[i] = parser.ASC + } else { + view.sortDirections[i] = oi.Direction.Token + } + + if oi.Position.IsEmpty() { + switch view.sortDirections[i] { + case parser.ASC: + view.sortNullPositions[i] = parser.FIRST + default: //parser.DESC + view.sortNullPositions[i] = parser.LAST } - view.sortIndices = append(view.sortIndices, idx) - default: - idx, err := view.Header.ContainsAlias(oi.Item.String()) - if err != nil { + } else { + view.sortNullPositions[i] = oi.Position.Token + } + } + + sort.Sort(view) + return nil +} + +func (view *View) evalColumn(obj parser.Expression, column string, alias string) (idx int, err error) { + switch obj.(type) { + case parser.FieldReference: + idx, err = view.FieldIndex(obj.(parser.FieldReference)) + default: + idx, err = view.Header.ContainsObject(obj) + if err != nil { + err = nil + + if analyticFunction, ok := obj.(parser.AnalyticFunction); ok { + err = view.evalAnalyticFunction(analyticFunction) + if err != nil { + return + } + } else { + var filter Filter = append([]FilterRecord{{View: view, RecordIndex: 0}}, view.parentFilter...) for i := range view.Records { - var filter Filter = append([]FilterRecord{{View: view, RecordIndex: i}}, view.parentFilter...) + var primary parser.Primary + filter[0].RecordIndex = i - primary, err := filter.Evaluate(oi.Item) + primary, err = filter.Evaluate(obj) if err != nil { - return err + return } view.Records[i] = append(view.Records[i], NewCell(primary)) } - view.Header, idx = AddHeaderField(view.Header, oi.Item.String()) } - view.sortIndices = append(view.sortIndices, idx) + view.Header, idx = AddHeaderField(view.Header, column, alias) } - view.sortDirections = append(view.sortDirections, oi.Direction.Token) } + return +} - direction := parser.ASC - for i := len(view.sortDirections) - 1; i >= 0; i-- { - if view.sortDirections[i] == parser.ASC || view.sortDirections[i] == parser.DESC { - direction = view.sortDirections[i] - } else { - view.sortDirections[i] = direction +func (view *View) evalAnalyticFunction(expr parser.AnalyticFunction) error { + name := strings.ToUpper(expr.Name) + fn, ok := AnalyticFunctions[name] + if !ok { + return errors.New(fmt.Sprintf("function %s does not exist", expr.Name)) + } + + if expr.Option.IsDistinct() { + return errors.New(fmt.Sprintf("syntax error: unexpected %s", expr.Option.Distinct.Literal)) + } + + if expr.AnalyticClause.OrderByClause != nil { + err := view.OrderBy(expr.AnalyticClause.OrderByClause.(parser.OrderByClause)) + if err != nil { + return err } } - sort.Sort(view) - return nil + partitionList := make([]partitionValue, view.RecordLen()) + + var filter Filter = append([]FilterRecord{{View: view, RecordIndex: 0}}, view.parentFilter...) + for i := range view.Records { + filter[0].RecordIndex = i + values, err := filter.evalValues(expr.AnalyticClause.PartitionValues()) + if err != nil { + return err + } + + orderValues, err := filter.evalValues(expr.AnalyticClause.OrderValues()) + if err != nil { + return err + } + + partitionList[i] = partitionValue{ + values: values, + orderValues: orderValues, + } + } + + return fn(view, expr.Option.Args, partitionList) } -func (view *View) Offset(clause parser.OffsetClause) { - if int64(len(view.Records)) <= clause.Number { +func (view *View) Offset(clause parser.OffsetClause) error { + var filter Filter + value, err := filter.Evaluate(clause.Value) + if err != nil { + return err + } + number := parser.PrimaryToInteger(value) + if parser.IsNull(number) { + return errors.New("offset number is not an integer") + } + view.offset = int(number.(parser.Integer).Value()) + if view.offset < 0 { + view.offset = 0 + } + + if view.RecordLen() <= view.offset { view.Records = Records{} } else { - view.Records = view.Records[clause.Number:] + view.Records = view.Records[view.offset:] records := make(Records, len(view.Records)) copy(records, view.Records) view.Records = records } + return nil } -func (view *View) Limit(clause parser.LimitClause) { - if clause.Number < int64(len(view.Records)) { - view.Records = view.Records[:clause.Number] - records := make(Records, len(view.Records)) - copy(records, view.Records) - view.Records = records +func (view *View) Limit(clause parser.LimitClause) error { + var filter Filter + value, err := filter.Evaluate(clause.Value) + if err != nil { + return err + } + + var limit int + if clause.IsPercentage() { + number := parser.PrimaryToFloat(value) + if parser.IsNull(number) { + return errors.New("limit percentage is not a float value") + } + percentage := number.(parser.Float).Value() + if 100 < percentage { + limit = 100 + } else if percentage < 0 { + limit = 0 + } else { + limit = int(math.Ceil(float64(view.RecordLen()+view.offset) * percentage / 100)) + } + } else { + number := parser.PrimaryToInteger(value) + if parser.IsNull(number) { + return errors.New("limit number of records is not an integer value") + } + limit = int(number.(parser.Integer).Value()) + if limit < 0 { + limit = 0 + } } + + if view.RecordLen() <= limit { + return nil + } + + if clause.IsWithTies() && 0 < len(view.sortIndices) { + bottomRecord := view.Records[limit-1] + for limit < view.RecordLen() { + if !bottomRecord.Match(view.Records[limit], view.sortIndices) { + break + } + limit++ + } + } + + view.Records = view.Records[:limit] + records := make(Records, view.RecordLen()) + copy(records, view.Records) + view.Records = records + return nil } func (view *View) InsertValues(fields []parser.Expression, list []parser.Expression) error { @@ -855,6 +956,8 @@ func (view *View) Fix() { view.parentFilter = Filter(nil) view.sortIndices = []int(nil) view.sortDirections = []int(nil) + view.sortNullPositions = []int(nil) + view.offset = 0 } func (view *View) Union(calcView *View, all bool) { @@ -967,9 +1070,17 @@ func (view *View) Less(i, j int) bool { continue case ternary.UNKNOWN: if parser.IsNull(pi) { - t = ternary.TRUE + if view.sortNullPositions[k] == parser.FIRST { + return true + } else { + return false + } } else if parser.IsNull(pj) { - t = ternary.FALSE + if view.sortNullPositions[k] == parser.FIRST { + return false + } else { + return true + } } else { continue } diff --git a/lib/query/view_test.go b/lib/query/view_test.go index 90230d09..e1a7112c 100644 --- a/lib/query/view_test.go +++ b/lib/query/view_test.go @@ -734,7 +734,7 @@ var viewWhereTests = []struct { Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: "="}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -979,7 +979,7 @@ var viewHavingTests = []struct { Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "Having Not Grouped", @@ -1116,7 +1116,7 @@ var viewSelectTests = []struct { {Reference: "table2", Column: INTERNAL_ID_COLUMN}, {Reference: "table2", Column: "column3", FromTable: true}, {Reference: "table2", Column: "column4", FromTable: true}, - {Alias: "a"}, + {Column: "1", Alias: "a"}, }, Records: []Record{ NewRecordWithoutId([]parser.Primary{ @@ -1215,7 +1215,7 @@ var viewSelectTests = []struct { Result: &View{ Header: []HeaderField{ {Reference: "table1", Column: "column1", FromTable: true}, - {Alias: "a"}, + {Column: "1", Alias: "a"}, }, Records: []Record{ NewRecordWithoutId([]parser.Primary{ @@ -1266,7 +1266,7 @@ var viewSelectTests = []struct { {Reference: "table1", Column: INTERNAL_ID_COLUMN}, {Reference: "table1", Column: "column1", FromTable: true}, {Reference: "table1", Column: "column2", FromTable: true}, - {Alias: "sum(column1)"}, + {Column: "sum(column1)", Alias: "sum(column1)"}, }, Records: []Record{ { @@ -1279,6 +1279,333 @@ var viewSelectTests = []struct { selectFields: []int{3}, }, }, + { + Name: "Select Analytic Function", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + }, + }, + Select: parser.SelectClause{ + Fields: []parser.Expression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.Field{ + Object: parser.AnalyticFunction{ + Name: "row_number", + Over: "over", + AnalyticClause: parser.AnalyticClause{ + Partition: parser.Partition{ + PartitionBy: "partition by", + Values: []parser.Expression{ + parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, + }, + }, + OrderByClause: parser.OrderByClause{ + OrderBy: "order by", + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, + }, + }, + }, + }, + }, + Alias: parser.Identifier{Literal: "rownum"}, + }, + }, + }, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + {Column: "row_number() over (partition by column1 order by column2)", Alias: "rownum"}, + }, + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + parser.NewInteger(3), + }), + }, + selectFields: []int{0, 1, 2}, + }, + }, + { + Name: "Select Analytic Function Not Exist Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + }, + }, + Select: parser.SelectClause{ + Fields: []parser.Expression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.Field{ + Object: parser.AnalyticFunction{ + Name: "notexist", + Over: "over", + AnalyticClause: parser.AnalyticClause{ + Partition: parser.Partition{ + PartitionBy: "partition by", + Values: []parser.Expression{ + parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, + }, + }, + OrderByClause: parser.OrderByClause{ + OrderBy: "order by", + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, + }, + }, + }, + }, + }, + Alias: parser.Identifier{Literal: "rownum"}, + }, + }, + }, + Error: "function notexist does not exist", + }, + { + Name: "Select Analytic Function Option Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + }, + }, + Select: parser.SelectClause{ + Fields: []parser.Expression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.Field{ + Object: parser.AnalyticFunction{ + Name: "row_number", + Option: parser.Option{ + Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"}, + }, + Over: "over", + AnalyticClause: parser.AnalyticClause{ + Partition: parser.Partition{ + PartitionBy: "partition by", + Values: []parser.Expression{ + parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, + }, + }, + OrderByClause: parser.OrderByClause{ + OrderBy: "order by", + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, + }, + }, + }, + }, + }, + Alias: parser.Identifier{Literal: "rownum"}, + }, + }, + }, + Error: "syntax error: unexpected distinct", + }, + { + Name: "Select Analytic Function Order Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + }, + }, + Select: parser.SelectClause{ + Fields: []parser.Expression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.Field{ + Object: parser.AnalyticFunction{ + Name: "row_number", + Over: "over", + AnalyticClause: parser.AnalyticClause{ + Partition: parser.Partition{ + PartitionBy: "partition by", + Values: []parser.Expression{ + parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, + }, + }, + OrderByClause: parser.OrderByClause{ + OrderBy: "order by", + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, + }, + }, + }, + }, + }, + Alias: parser.Identifier{Literal: "rownum"}, + }, + }, + }, + Error: "field notexist does not exist", + }, + { + Name: "Select Analytic Function Partition Value Error", + View: &View{ + Header: NewHeaderWithoutId("table1", []string{"column1", "column2"}), + Records: []Record{ + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(2), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(3), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(5), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("a"), + parser.NewInteger(1), + }), + NewRecordWithoutId([]parser.Primary{ + parser.NewString("b"), + parser.NewInteger(4), + }), + }, + }, + Select: parser.SelectClause{ + Fields: []parser.Expression{ + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, + parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, + parser.Field{ + Object: parser.AnalyticFunction{ + Name: "row_number", + Over: "over", + AnalyticClause: parser.AnalyticClause{ + Partition: parser.Partition{ + PartitionBy: "partition by", + Values: []parser.Expression{ + parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, + }, + }, + OrderByClause: parser.OrderByClause{ + OrderBy: "order by", + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, + }, + }, + }, + }, + }, + Alias: parser.Identifier{Literal: "rownum"}, + }, + }, + }, + Error: "field notexist does not exist", + }, } func TestView_Select(t *testing.T) { @@ -1355,17 +1682,17 @@ var viewOrderByTests = []struct { OrderBy: parser.OrderByClause{ Items: []parser.Expression{ parser.OrderItem{ - Item: parser.Identifier{Literal: "column1"}, + Value: parser.Identifier{Literal: "column1"}, }, parser.OrderItem{ - Item: parser.Identifier{Literal: "column2"}, + Value: parser.Identifier{Literal: "column2"}, Direction: parser.Token{Token: parser.DESC, Literal: "desc"}, }, parser.OrderItem{ - Item: parser.Identifier{Literal: "column3"}, + Value: parser.Identifier{Literal: "column3"}, }, parser.OrderItem{ - Item: parser.NewInteger(1), + Value: parser.NewInteger(1), }, }, }, @@ -1375,9 +1702,15 @@ var viewOrderByTests = []struct { {Reference: "table1", Column: "column1", FromTable: true}, {Reference: "table1", Column: "column2", FromTable: true}, {Reference: "table1", Column: "column3", FromTable: true}, - {Alias: "1"}, + {Column: "1"}, }, Records: []Record{ + NewRecord(5, []parser.Primary{ + parser.NewNull(), + parser.NewString("2"), + parser.NewString("4"), + parser.NewInteger(1), + }), NewRecord(2, []parser.Primary{ parser.NewString("1"), parser.NewString("4"), @@ -1402,24 +1735,91 @@ var viewOrderByTests = []struct { parser.NewString("2"), parser.NewInteger(1), }), - NewRecord(5, []parser.Primary{ + }, + }, + }, + { + Name: "Order By With Null Positions", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), + }), + NewRecord(3, []parser.Primary{ parser.NewNull(), parser.NewString("2"), - parser.NewString("4"), - parser.NewInteger(1), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("1"), + parser.NewNull(), + }), + NewRecord(5, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), }), }, }, - }, -} - -func TestView_OrderBy(t *testing.T) { - for _, v := range viewOrderByTests { - err := v.View.OrderBy(v.OrderBy) - if err != nil { - if len(v.Error) < 1 { - t.Errorf("%s: unexpected error %q", v.Name, err) - } else if err.Error() != v.Error { + OrderBy: parser.OrderByClause{ + Items: []parser.Expression{ + parser.OrderItem{ + Value: parser.Identifier{Literal: "column1"}, + Position: parser.Token{Token: parser.LAST, Literal: "last"}, + }, + parser.OrderItem{ + Value: parser.Identifier{Literal: "column2"}, + Position: parser.Token{Token: parser.FIRST, Literal: "first"}, + }, + }, + }, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(4, []parser.Primary{ + parser.NewString("1"), + parser.NewNull(), + }), + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), + }), + NewRecord(5, []parser.Primary{ + parser.NewString("1"), + parser.NewString("2"), + }), + NewRecord(3, []parser.Primary{ + parser.NewNull(), + parser.NewString("2"), + }), + }, + }, + }, +} + +func TestView_OrderBy(t *testing.T) { + for _, v := range viewOrderByTests { + err := v.View.OrderBy(v.OrderBy) + if err != nil { + if len(v.Error) < 1 { + t.Errorf("%s: unexpected error %q", v.Name, err) + } else if err.Error() != v.Error { t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) } continue @@ -1437,143 +1837,637 @@ func TestView_OrderBy(t *testing.T) { } } -func TestView_Limit(t *testing.T) { - view := &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, +var viewLimitTests = []struct { + Name string + View *View + Limit parser.LimitClause + Result *View + Error string +}{ + { + Name: "Limit", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, }, - Records: []Record{ - NewRecord(1, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(2, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(3, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(4, []parser.Primary{ - parser.NewString("2"), - parser.NewString("str2"), - }), + Limit: parser.LimitClause{Value: parser.NewInteger(2)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, }, - } - limit := parser.LimitClause{Number: 2} - expect := &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, + }, + { + Name: "Limit With Ties", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, + sortIndices: []int{1, 2}, }, - Records: []Record{ - NewRecord(1, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(2, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), + Limit: parser.LimitClause{Value: parser.NewInteger(2), With: parser.LimitWith{Type: parser.Token{Token: parser.TIES}}}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + sortIndices: []int{1, 2}, }, - } - - view.Limit(limit) - if !reflect.DeepEqual(view, expect) { - t.Errorf("limit: view = %s, want %s", view, expect) - } -} - -func TestView_Offset(t *testing.T) { - view := &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, + }, + { + Name: "Limit By Percentage", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, + offset: 1, }, - Records: []Record{ - NewRecord(1, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(2, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(3, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(4, []parser.Primary{ - parser.NewString("2"), - parser.NewString("str2"), - }), + Limit: parser.LimitClause{Value: parser.NewFloat(50.5), Percent: "percent"}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, + offset: 1, }, - } - - offset := parser.OffsetClause{Number: 3} - expect := &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, + }, + { + Name: "Limit By Over 100 Percentage", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, }, - Records: []Record{ - NewRecord(4, []parser.Primary{ - parser.NewString("2"), - parser.NewString("str2"), - }), + Limit: parser.LimitClause{Value: parser.NewFloat(150), Percent: "percent"}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, }, - } + }, + { + Name: "Limit By Negative Percentage", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("3"), + parser.NewString("str3"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.NewFloat(-10), Percent: "percent"}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{}, + }, + }, + { + Name: "Limit Greater Than Records", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.NewInteger(5)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + }, + { + Name: "Limit Evaluate Error", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.Variable{Name: "notexist"}}, + Error: "variable notexist is undefined", + }, + { + Name: "Limit Value Error", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.NewString("str")}, + Error: "limit number of records is not an integer value", + }, + { + Name: "Limit Negative Value", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.NewInteger(-1)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{}, + }, + }, + { + Name: "Limit By Percentage Value Error", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Limit: parser.LimitClause{Value: parser.NewString("str"), Percent: "percent"}, + Error: "limit percentage is not a float value", + }, +} - view.Offset(offset) - if !reflect.DeepEqual(view, expect) { - t.Errorf("offset: view = %s, want %s", view, expect) +func TestView_Limit(t *testing.T) { + for _, v := range viewLimitTests { + err := v.View.Limit(v.Limit) + if err != nil { + if len(v.Error) < 1 { + t.Errorf("%s: unexpected error %q", v.Name, err) + } else if err.Error() != v.Error { + t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) + } + continue + } + if 0 < len(v.Error) { + t.Errorf("%s: no error, want error %q", v.Name, v.Error) + continue + } + if !reflect.DeepEqual(v.View, v.Result) { + t.Errorf("%s: view = %s, want %s", v.Name, v.View, v.Result) + } } +} - view = &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, +var viewOffsetTests = []struct { + Name string + View *View + Offset parser.OffsetClause + Result *View + Error string +}{ + { + Name: "Offset", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, }, - Records: []Record{ - NewRecord(1, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(2, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(3, []parser.Primary{ - parser.NewString("1"), - parser.NewString("str1"), - }), - NewRecord(4, []parser.Primary{ - parser.NewString("2"), - parser.NewString("str2"), - }), + Offset: parser.OffsetClause{Value: parser.NewInteger(3)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, + offset: 3, }, - } - - offset = parser.OffsetClause{Number: 4} - expect = &View{ - Header: []HeaderField{ - {Reference: "table1", Column: INTERNAL_ID_COLUMN}, - {Reference: "table1", Column: "column1", FromTable: true}, - {Reference: "table1", Column: "column2", FromTable: true}, + }, + { + Name: "Offset Equal To Record Length", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, }, - Records: []Record{}, - } + Offset: parser.OffsetClause{Value: parser.NewInteger(4)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{}, + offset: 4, + }, + }, + { + Name: "Offset Evaluate Error", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, + }, + Offset: parser.OffsetClause{Value: parser.Variable{Name: "notexist"}}, + Error: "variable notexist is undefined", + }, + { + Name: "Offset Value Error", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(3, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(4, []parser.Primary{ + parser.NewString("2"), + parser.NewString("str2"), + }), + }, + }, + Offset: parser.OffsetClause{Value: parser.NewString("str")}, + Error: "offset number is not an integer", + }, + { + Name: "Offset Negative Number", + View: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + }, + Offset: parser.OffsetClause{Value: parser.NewInteger(-3)}, + Result: &View{ + Header: []HeaderField{ + {Reference: "table1", Column: INTERNAL_ID_COLUMN}, + {Reference: "table1", Column: "column1", FromTable: true}, + {Reference: "table1", Column: "column2", FromTable: true}, + }, + Records: []Record{ + NewRecord(1, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + NewRecord(2, []parser.Primary{ + parser.NewString("1"), + parser.NewString("str1"), + }), + }, + offset: 0, + }, + }, +} - view.Offset(offset) - if !reflect.DeepEqual(view, expect) { - t.Errorf("offset: view = %s, want %s", view, expect) +func TestView_Offset(t *testing.T) { + for _, v := range viewOffsetTests { + err := v.View.Offset(v.Offset) + if err != nil { + if len(v.Error) < 1 { + t.Errorf("%s: unexpected error %q", v.Name, err) + } else if err.Error() != v.Error { + t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) + } + continue + } + if 0 < len(v.Error) { + t.Errorf("%s: no error, want error %q", v.Name, v.Error) + continue + } + if !reflect.DeepEqual(v.View, v.Result) { + t.Errorf("%s: view = %s, want %s", v.Name, v.View, v.Result) + } } } @@ -1663,7 +2557,7 @@ var viewInsertValuesTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, { Name: "InsertValues Field Does Not Exist Error", @@ -1679,7 +2573,7 @@ var viewInsertValuesTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } @@ -1792,7 +2686,7 @@ var viewInsertFromQueryTests = []struct { }, }, }, - Error: "identifier = notexist: field does not exist", + Error: "field notexist does not exist", }, } diff --git a/main.go b/main.go index 6df30149..1ff4ecfb 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,7 @@ import ( "github.com/urfave/cli" ) -var version = "v0.2.2" +var version = "v0.2.3" func main() { cli.AppHelpTemplate = appHHelpTemplate