plume 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +506 -11
  3. data/lib/plume/analysis/resolver.rb +797 -0
  4. data/lib/plume/analysis.rb +211 -0
  5. data/lib/plume/ast/alter_table_statement.rb +40 -0
  6. data/lib/plume/ast/analyze_statement.rb +15 -0
  7. data/lib/plume/ast/assignment.rb +18 -0
  8. data/lib/plume/ast/attach_statement.rb +17 -0
  9. data/lib/plume/ast/begin_statement.rb +17 -0
  10. data/lib/plume/ast/binary_expression.rb +71 -0
  11. data/lib/plume/ast/case_condition.rb +29 -0
  12. data/lib/plume/ast/case_expression.rb +22 -0
  13. data/lib/plume/ast/cast_expression.rb +16 -0
  14. data/lib/plume/ast/check_column_constraint.rb +20 -0
  15. data/lib/plume/ast/check_table_constraint.rb +20 -0
  16. data/lib/plume/ast/collate_column_constraint.rb +19 -0
  17. data/lib/plume/ast/collation_expression.rb +26 -0
  18. data/lib/plume/ast/column_constraint.rb +7 -0
  19. data/lib/plume/ast/column_definition.rb +16 -0
  20. data/lib/plume/ast/column_name.rb +22 -0
  21. data/lib/plume/ast/column_type.rb +26 -0
  22. data/lib/plume/ast/commit_statement.rb +13 -0
  23. data/lib/plume/ast/common_table_expression.rb +31 -0
  24. data/lib/plume/ast/compound_select.rb +30 -0
  25. data/lib/plume/ast/conflict_clause.rb +22 -0
  26. data/lib/plume/ast/conflict_resolution.rb +20 -0
  27. data/lib/plume/ast/create_index_statement.rb +29 -0
  28. data/lib/plume/ast/create_table_statement.rb +47 -0
  29. data/lib/plume/ast/create_trigger_statement.rb +43 -0
  30. data/lib/plume/ast/create_view_statement.rb +30 -0
  31. data/lib/plume/ast/create_virtual_table_statement.rb +28 -0
  32. data/lib/plume/ast/default_column_constraint.rb +29 -0
  33. data/lib/plume/ast/deferrable_column_constraint.rb +20 -0
  34. data/lib/plume/ast/delete_statement.rb +28 -0
  35. data/lib/plume/ast/detach_statement.rb +13 -0
  36. data/lib/plume/ast/drop_statement.rb +21 -0
  37. data/lib/plume/ast/empty_function_argument.rb +6 -0
  38. data/lib/plume/ast/exists_expression.rb +15 -0
  39. data/lib/plume/ast/explain_statement.rb +15 -0
  40. data/lib/plume/ast/expression.rb +30 -0
  41. data/lib/plume/ast/foreign_key_action.rb +26 -0
  42. data/lib/plume/ast/foreign_key_clause.rb +50 -0
  43. data/lib/plume/ast/foreign_key_column_constraint.rb +16 -0
  44. data/lib/plume/ast/foreign_key_table_constraint.rb +20 -0
  45. data/lib/plume/ast/frame_boundary.rb +35 -0
  46. data/lib/plume/ast/frame_spec.rb +34 -0
  47. data/lib/plume/ast/function_arguments.rb +18 -0
  48. data/lib/plume/ast/function_reference.rb +29 -0
  49. data/lib/plume/ast/generated_as_column_constraint.rb +24 -0
  50. data/lib/plume/ast/indexed_column.rb +24 -0
  51. data/lib/plume/ast/insert_statement.rb +35 -0
  52. data/lib/plume/ast/join.rb +12 -0
  53. data/lib/plume/ast/join_clause.rb +15 -0
  54. data/lib/plume/ast/join_on_constraint.rb +12 -0
  55. data/lib/plume/ast/join_operator.rb +31 -0
  56. data/lib/plume/ast/join_using_constraint.rb +16 -0
  57. data/lib/plume/ast/like_expression.rb +19 -0
  58. data/lib/plume/ast/literal_expression.rb +29 -0
  59. data/lib/plume/ast/literal_false.rb +7 -0
  60. data/lib/plume/ast/literal_nil.rb +7 -0
  61. data/lib/plume/ast/literal_value.rb +18 -0
  62. data/lib/plume/ast/match_clause.rb +15 -0
  63. data/lib/plume/ast/node.rb +330 -0
  64. data/lib/plume/ast/noop_column_constraint.rb +15 -0
  65. data/lib/plume/ast/noop_table_constraint.rb +15 -0
  66. data/lib/plume/ast/not_like_expression.rb +7 -0
  67. data/lib/plume/ast/not_null_column_constraint.rb +17 -0
  68. data/lib/plume/ast/null_column_constraint.rb +17 -0
  69. data/lib/plume/ast/ordering_term.rb +32 -0
  70. data/lib/plume/ast/over_clause.rb +25 -0
  71. data/lib/plume/ast/parenthetical_expression.rb +37 -0
  72. data/lib/plume/ast/parenthetical_source.rb +19 -0
  73. data/lib/plume/ast/pragma_statement.rb +26 -0
  74. data/lib/plume/ast/primary_key_column_constraint.rb +23 -0
  75. data/lib/plume/ast/primary_key_table_constraint.rb +23 -0
  76. data/lib/plume/ast/raise_expression.rb +23 -0
  77. data/lib/plume/ast/reindex_statement.rb +15 -0
  78. data/lib/plume/ast/release_statement.rb +16 -0
  79. data/lib/plume/ast/result_column.rb +18 -0
  80. data/lib/plume/ast/returning_clause.rb +12 -0
  81. data/lib/plume/ast/rollback_statement.rb +19 -0
  82. data/lib/plume/ast/savepoint_statement.rb +16 -0
  83. data/lib/plume/ast/select_core.rb +27 -0
  84. data/lib/plume/ast/select_statement.rb +34 -0
  85. data/lib/plume/ast/star_function_argument.rb +6 -0
  86. data/lib/plume/ast/star_result_column.rb +16 -0
  87. data/lib/plume/ast/strict_table_option.rb +6 -0
  88. data/lib/plume/ast/subquery_expression.rb +14 -0
  89. data/lib/plume/ast/subquery_source.rb +19 -0
  90. data/lib/plume/ast/table_constraint.rb +7 -0
  91. data/lib/plume/ast/table_function.rb +28 -0
  92. data/lib/plume/ast/table_name.rb +28 -0
  93. data/lib/plume/ast/table_option.rb +7 -0
  94. data/lib/plume/ast/ternary_expression.rb +26 -0
  95. data/lib/plume/ast/token.rb +183 -0
  96. data/lib/plume/ast/unary_expression.rb +36 -0
  97. data/lib/plume/ast/unique_column_constraint.rb +17 -0
  98. data/lib/plume/ast/unique_table_constraint.rb +20 -0
  99. data/lib/plume/ast/update_statement.rb +35 -0
  100. data/lib/plume/ast/upsert_clause.rb +26 -0
  101. data/lib/plume/ast/vacuum_statement.rb +18 -0
  102. data/lib/plume/ast/values_clause.rb +12 -0
  103. data/lib/plume/ast/values_row.rb +13 -0
  104. data/lib/plume/ast/variable.rb +15 -0
  105. data/lib/plume/ast/window_definition.rb +26 -0
  106. data/lib/plume/ast/with_clause.rb +15 -0
  107. data/lib/plume/ast/without_rowid_table_option.rb +6 -0
  108. data/lib/plume/catalog.rb +276 -0
  109. data/lib/plume/comment.rb +73 -0
  110. data/lib/plume/dump.rb +143 -0
  111. data/lib/plume/fingerprint.rb +86 -0
  112. data/lib/plume/lexer.rb +640 -0
  113. data/lib/plume/literal_patches.rb +76 -0
  114. data/lib/plume/normalize.rb +65 -0
  115. data/lib/plume/parameters.rb +52 -0
  116. data/lib/plume/parser.rb +4064 -0
  117. data/lib/plume/pretty_printer.rb +202 -0
  118. data/lib/plume/printer.rb +525 -0
  119. data/lib/plume/sqlite_grammar.rb +86 -0
  120. data/lib/plume/truncate.rb +67 -0
  121. data/lib/plume/union.rb +28 -0
  122. data/lib/plume/version.rb +1 -1
  123. data/lib/plume.rb +274 -3
  124. metadata +176 -12
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class OrderingTerm < Node
5
+ Direction = _Union(
6
+ :ASC, "ASC", :asc, "asc", :ASCENDING, "ASCENDING", :ascending, "ascending",
7
+ :DESC, "DESC", :desc, "desc", :DESCENDING, "DESCENDING", :descending, "descending",
8
+ )
9
+ Nulls = _Union(
10
+ :FIRST, "FIRST", :first, "first",
11
+ :LAST, "LAST", :last, "last",
12
+ )
13
+
14
+ token :collate_kw
15
+ token :collation_tk
16
+ token :direction_tk
17
+ token :nulls_kw
18
+ token :nulls_tk
19
+
20
+ node :expression, Expression
21
+ attribute :collation, Stringy
22
+ attribute :direction, Direction
23
+ attribute :nulls, Nulls
24
+
25
+ def self.new(*, **) = super
26
+ def self.concrete(*, **) = super
27
+
28
+ def collation = (@collation == LiteralNil) ? Node.collation_name(collation_tk_val) : @collation
29
+ def direction = (@direction == LiteralNil) ? direction_tk_val&.to_sym&.upcase : @direction
30
+ def nulls = (@nulls == LiteralNil) ? nulls_tk_val&.to_sym&.upcase : @nulls
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class OverClause < Node
5
+ token :over_kw
6
+ token :window_lp
7
+ token :base_window_name_tk
8
+ token :partition_by_kw
9
+ token :order_by_kw
10
+ token :window_rp
11
+ token :window_name_tk
12
+
13
+ nodes :partitions, Expression
14
+ nodes :orderings, OrderingTerm
15
+ node :frame, FrameSpec
16
+ attribute :window_name, Stringy
17
+ attribute :base_window_name, Stringy
18
+
19
+ def self.new(*, **) = super
20
+ def self.concrete(*, over_kw:, **) = super
21
+
22
+ def window_name = (@window_name == LiteralNil) ? window_name_tk_val : @window_name
23
+ def base_window_name = (@base_window_name == LiteralNil) ? base_window_name_tk_val : @base_window_name
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class ParentheticalExpression < Node
5
+ token :value_lp
6
+ token :value_tk
7
+ token :value_rp
8
+
9
+ # Hand-built trees may wrap plain Ruby values; a lambda keeps them out of the union's
10
+ # plain-value set, see Node.attribute
11
+ attribute :value, _Union(Expression, _Array(Expression), -> (v) { LiteralValue === v })
12
+
13
+ def self.new(*, value:, **) = super
14
+ def self.concrete(*, **) = super
15
+
16
+ # Parser may pass either tokens or attributes, so
17
+ # require none in `concrete` signature but ensure presence here.
18
+ def after_initialize
19
+ if @value == LiteralNil && @value_tk == LiteralNil
20
+ raise ArgumentError.new("missing either: :value, :value_tk")
21
+ end
22
+ end
23
+
24
+ # The child as stored - nil only for the empty list of `x IN ()`. Unlike `value`, a NULL
25
+ # literal stays a node, so it cannot be mistaken for that empty list
26
+ def contents = LiteralNil.equal?(@value) ? value_tk_val : @value
27
+
28
+ def value
29
+ case (v = contents)
30
+ when LiteralNil then nil
31
+ when LiteralFalse then false
32
+ when LiteralExpression then v.value
33
+ else v
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # A parenthesized join or source list used as a FROM source, like `(a JOIN b) AS ab`
5
+ class ParentheticalSource < Node
6
+ token :source_lp
7
+ token :source_rp
8
+ token :as_kw
9
+ token :alias_tk
10
+
11
+ node :source, _Any
12
+ attribute :alias, Stringy
13
+
14
+ def self.new(*, source:, **) = super
15
+ def self.concrete(*, source:, **) = super
16
+
17
+ def alias = (@alias == LiteralNil) ? alias_tk_val : @alias
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/pragma.html)**
5
+ class PragmaStatement < Node
6
+ token :pragma_kw
7
+ token :schema_tk
8
+ token :dot_tk
9
+ token :name_tk
10
+ token :eq_tk # `=`, or the opening parenthesis of `PRAGMA name(value)`
11
+ token :value_tk
12
+ token :value_rp
13
+
14
+ attribute :schema, Stringy
15
+ attribute :name, Stringy
16
+
17
+ def self.new(*, name:, **) = super
18
+ def self.concrete(*, pragma_kw:, name_tk:, **) = super
19
+
20
+ def schema = (@schema == LiteralNil) ? schema_tk_val : @schema
21
+ def name = (@name == LiteralNil) ? name_tk_val : @name
22
+
23
+ # As written: numbers come out as numbers, keywords and names as strings
24
+ inspectable def value = value_tk_val
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class PrimaryKeyColumnConstraint < ColumnConstraint
5
+ token :constraint_kw
6
+ token :name_tk
7
+ token :primary_key_kw
8
+ token :direction_tk
9
+ token :autoincrement_kw
10
+
11
+ attribute :name, Stringy
12
+ attribute :direction, Stringy
13
+ attribute :autoincrement, _Boolean
14
+ node :conflict_clause, ConflictClause
15
+
16
+ def self.new(*, **) = super
17
+ def self.concrete(*, primary_key_kw:, **) = super
18
+
19
+ def name = (@name == LiteralNil) ? name_tk_val : @name
20
+ def direction = (@direction == LiteralNil) ? direction_tk_val&.to_sym&.upcase : @direction
21
+ def autoincrement = (@autoincrement == LiteralNil) ? autoincrement_kw? : @autoincrement
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class PrimaryKeyTableConstraint < TableConstraint
5
+ token :constraint_kw
6
+ token :name_tk
7
+ token :primary_key_kw
8
+ token :primary_key_lp
9
+ token :autoincrement_kw
10
+ token :primary_key_rp
11
+
12
+ attribute :name, Stringy
13
+ attribute :autoincrement, _Boolean
14
+ nodes :columns, IndexedColumn
15
+ node :conflict_clause, ConflictClause
16
+
17
+ def self.new(*, columns:, **) = super
18
+ def self.concrete(*, primary_key_kw:, columns:, **) = super
19
+
20
+ def name = (@name == LiteralNil) ? name_tk_val : @name
21
+ def autoincrement = (@autoincrement == LiteralNil) ? autoincrement_kw? : @autoincrement
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class RaiseExpression < Node
5
+ Type = _Union(:IGNORE, :ROLLBACK, :ABORT, :FAIL)
6
+
7
+ token :raise_kw # required
8
+ token :raise_lp # required
9
+ token :type_kw # required
10
+ token :comma # maybe
11
+ token :error_message_tk # maybe
12
+ token :raise_rp # required
13
+
14
+ attribute :type, Type # required
15
+ attribute :error_message, Expression # maybe
16
+
17
+ def self.new(*, type:, **) = super
18
+ def self.concrete(*, raise_kw:, raise_lp:, type_kw:, raise_rp:, **) = super
19
+
20
+ def type = (@type == LiteralNil) ? type_kw_src.to_sym.upcase : @type
21
+ def error_message = (@error_message == LiteralNil) ? error_message_tk_val : @error_message
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/lang_reindex.html)**
5
+ #
6
+ # `target` names a schema, table or index - SQLite works out which at run time
7
+ class ReindexStatement < Node
8
+ token :reindex_kw
9
+
10
+ node :target, TableName
11
+
12
+ def self.new(*, **) = super
13
+ def self.concrete(*, reindex_kw:, **) = super
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/lang_savepoint.html)**
5
+ class ReleaseStatement < Node
6
+ token :release_kw # RELEASE or RELEASE SAVEPOINT
7
+ token :name_tk
8
+
9
+ attribute :name, Stringy
10
+
11
+ def self.new(*, name:, **) = super
12
+ def self.concrete(*, release_kw:, name_tk:, **) = super
13
+
14
+ def name = (@name == LiteralNil) ? name_tk_val : @name
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class ResultColumn < Node
5
+ token :as_kw
6
+ token :alias_tk
7
+ token :result_tk
8
+
9
+ node :result, Expression
10
+ attribute :alias, Stringy
11
+
12
+ def self.new(*, result:, **) = super
13
+ def self.concrete(*, **) = super
14
+
15
+ def result = (@result == LiteralNil) ? result_tk_val : @result
16
+ def alias = (@alias == LiteralNil) ? alias_tk_val : @alias
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class ReturningClause < Node
5
+ token :returning_kw
6
+
7
+ nodes :columns, _Union(ResultColumn, StarResultColumn)
8
+
9
+ def self.new(*, columns:, **) = super
10
+ def self.concrete(*, returning_kw:, columns:, **) = super
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/lang_transaction.html)**
5
+ class RollbackStatement < Node
6
+ token :rollback_kw
7
+ token :transaction_kw
8
+ token :name_tk
9
+ token :to_kw # TO or TO SAVEPOINT
10
+ token :savepoint_tk
11
+
12
+ attribute :savepoint, Stringy
13
+
14
+ def self.new(*, **) = super
15
+ def self.concrete(*, rollback_kw:, **) = super
16
+
17
+ def savepoint = (@savepoint == LiteralNil) ? savepoint_tk_val : @savepoint
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/lang_savepoint.html)**
5
+ class SavepointStatement < Node
6
+ token :savepoint_kw
7
+ token :name_tk
8
+
9
+ attribute :name, Stringy
10
+
11
+ def self.new(*, name:, **) = super
12
+ def self.concrete(*, savepoint_kw:, name_tk:, **) = super
13
+
14
+ def name = (@name == LiteralNil) ? name_tk_val : @name
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # A single `SELECT … FROM … WHERE … GROUP BY … HAVING … WINDOW …`, without the
5
+ # statement-level `WITH`, `ORDER BY` and `LIMIT`
6
+ class SelectCore < Node
7
+ token :select_kw
8
+ token :type_tk
9
+ token :from_kw
10
+ token :where_kw
11
+ token :group_by_kw
12
+ token :having_kw
13
+ token :window_kw
14
+
15
+ nodes :columns, _Union(ResultColumn, StarResultColumn)
16
+ node :source, _Any
17
+ node :condition, Expression
18
+ nodes :groupings, Expression
19
+ node :having, Expression
20
+ nodes :windows, WindowDefinition
21
+
22
+ def self.new(*, columns:, **) = super
23
+ def self.concrete(*, select_kw:, columns:, **) = super
24
+
25
+ inspectable def distinct = type_tk_tok == :DISTINCT
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # **[SQLite Docs](https://www.sqlite.org/lang_select.html)**
5
+ #
6
+ # ```sql
7
+ # with t as (select 1) select * from t union select 2 order by 1 limit 1
8
+ # ```
9
+ #
10
+ # `body` is a `SelectCore`, a `ValuesClause`, or a `CompoundSelect` of those.
11
+ # `ORDER BY` and `LIMIT` belong to the statement as a whole, not to its last core.
12
+ class SelectStatement < Node
13
+ token :order_by_kw
14
+ token :limit_kw
15
+ token :offset_tk # OFFSET keyword, or the comma in `LIMIT offset, limit`
16
+
17
+ node :with_clause, _Any
18
+ node :body, _Any
19
+ nodes :orderings, OrderingTerm
20
+ node :limit, Expression
21
+ node :offset, Expression
22
+
23
+ def self.new(*, body:, **) = super
24
+ def self.concrete(*, body:, **) = super
25
+
26
+ # Every `SelectCore` and `ValuesClause` making up the body, left to right
27
+ def cores
28
+ case body
29
+ when CompoundSelect then body.cores
30
+ else [body]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class StarFunctionArgument < Node
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class StarResultColumn < Node
5
+ token :table_tk
6
+ token :dot_tk
7
+ token :star_tk
8
+
9
+ attribute :table, Stringy
10
+
11
+ def self.new(*, **) = super
12
+ def self.concrete(*, star_tk:, **) = super
13
+
14
+ def table = (@table == LiteralNil) ? table_tk_val : @table
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class StrictTableOption < TableOption
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # A scalar subquery `(SELECT …)`, also the right side of `x IN (SELECT …)`
5
+ class SubqueryExpression < Node
6
+ token :select_lp
7
+ token :select_rp
8
+
9
+ node :select, SelectStatement
10
+
11
+ def self.new(*, select:, **) = super
12
+ def self.concrete(*, select:, **) = super
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # A parenthesized select used as a FROM source, like `(SELECT …) AS s`
5
+ class SubquerySource < Node
6
+ token :select_lp
7
+ token :select_rp
8
+ token :as_kw
9
+ token :alias_tk
10
+
11
+ node :select, SelectStatement
12
+ attribute :alias, Stringy
13
+
14
+ def self.new(*, select:, **) = super
15
+ def self.concrete(*, select:, **) = super
16
+
17
+ def alias = (@alias == LiteralNil) ? alias_tk_val : @alias
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class TableConstraint < Node
5
+ # abstract
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # A table-valued function used as a FROM source, like `json_each(doc) AS j`
5
+ class TableFunction < Node
6
+ token :schema_tk
7
+ token :dot_tk
8
+ token :function_tk
9
+ token :arguments_lp
10
+ token :arguments_rp
11
+ token :as_kw
12
+ token :alias_tk
13
+
14
+ attribute :schema, Stringy
15
+ attribute :function, Stringy
16
+ nodes :arguments, Expression
17
+ attribute :alias, Stringy
18
+
19
+ def self.new(*, function:, **) = super
20
+ def self.concrete(*, function_tk:, **) = super
21
+
22
+ def schema = (@schema == LiteralNil) ? schema_tk_val : @schema
23
+ def function = (@function == LiteralNil) ? function_tk_val : @function
24
+ def alias = (@alias == LiteralNil) ? alias_tk_val : @alias
25
+
26
+ alias_method :name, :function
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class TableName < Node
5
+ token :schema_tk
6
+ token :dot_tk
7
+ token :table_tk
8
+ token :as_kw
9
+ token :alias_tk
10
+ token :indexed_kw # INDEXED BY, or NOT INDEXED
11
+ token :index_tk
12
+
13
+ attribute :schema, Stringy
14
+ attribute :table, Stringy
15
+ attribute :alias, Stringy
16
+
17
+ def self.new(*, table:, **) = super
18
+ def self.concrete(*, table_tk:, **) = super
19
+
20
+ def schema = (@schema == LiteralNil) ? schema_tk_val : @schema
21
+ def table = (@table == LiteralNil) ? table_tk_val : @table
22
+ def alias = (@alias == LiteralNil) ? alias_tk_val : @alias
23
+ def indexed_by = index_tk_val
24
+ def not_indexed = indexed_kw_tok == [:NOT, :INDEXED]
25
+
26
+ alias_method :name, :table
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ class TableOption < Node
5
+ # abstract
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plume
4
+ # `left [NOT] BETWEEN middle AND right`
5
+ class TernaryExpression < Node
6
+ TOKEN_TO_OPERATOR = {
7
+ :BETWEEN => :BETWEEN,
8
+ [:BETWEEN].freeze => :BETWEEN,
9
+ [:NOT, :BETWEEN].freeze => :NOT_BETWEEN,
10
+ }.freeze
11
+ Operator = _Union(*TOKEN_TO_OPERATOR.values)
12
+
13
+ token :operator_tk
14
+ token :and_kw
15
+
16
+ attribute :operator, Operator
17
+ node :left, Expression
18
+ node :middle, Expression
19
+ node :right, Expression
20
+
21
+ def self.new(*, operator:, left:, middle:, right:, **) = super
22
+ def self.concrete(*, operator_tk:, left:, middle:, right:, **) = super
23
+
24
+ def operator = (@operator == LiteralNil) ? TOKEN_TO_OPERATOR[operator_tk_tok] : @operator
25
+ end
26
+ end