Skip to content

Commit 4758c57

Browse files
authored
Merge pull request #6 from sql-rb/node-tokens
Node tokens
2 parents a0a3fb0 + 3ba2b9d commit 4758c57

File tree

11 files changed

+230
-60
lines changed

11 files changed

+230
-60
lines changed

lib/sql/composer/compiler.rb

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
# frozen_string_literal: true
22

3+
require "sql/composer/statement"
4+
require "sql/composer/tokens"
5+
36
module SQL
47
module Composer
58
class Compiler
9+
include ::Dry::Effects::Handler.State(:tokens)
10+
611
attr_reader :backend
712

813
attr_reader :nodes
914

10-
def initialize(backend)
15+
attr_reader :options
16+
17+
attr_reader :tokens
18+
19+
def initialize(backend, options)
1120
@backend = backend
12-
@nodes = []
21+
@options = options
22+
@nodes = options[:nodes] || []
23+
@tokens = options[:tokens]
1324
end
1425

1526
def call(ast)
16-
ast.map { |node| visit(node) }
17-
freeze
27+
with_tokens(tokens) { ast.map { |node| visit(node) } }
28+
Statement.new(compiler: freeze)
29+
end
30+
31+
def with(new_options)
32+
self.class.new(backend, options.merge(new_options).merge(nodes: nodes))
1833
end
1934

2035
def to_s
21-
nodes.map(&:to_s).join("\n")
36+
with_tokens(tokens) { nodes.map(&:to_s).join("\n") }.last
2237
end
2338

2439
def visit(node)

lib/sql/composer/dsl.rb

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
# frozen_string_literal: true
22

3+
require "dry/effects"
4+
35
require "sql/composer/compiler"
6+
require "sql/composer/tokens"
47

58
module SQL
69
module Composer
710
class DSL < BasicObject
11+
include ::Dry::Effects::Handler.State(:tokens)
12+
813
attr_reader :options
914

1015
attr_reader :ast
1116

17+
attr_reader :tokens
18+
1219
def initialize(options, &block)
13-
@ast = []
1420
@options = options
15-
instance_exec(*options[:args], &block)
21+
@ast = []
22+
@tokens = options[:tokens] || Tokens.new
23+
24+
with_tokens(tokens) do
25+
instance_exec(*options[:args], &block)
26+
end
1627
end
1728

1829
def call
19-
compiler = Compiler.new(options.fetch(:backend))
30+
compiler = Compiler.new(options.fetch(:backend), tokens: tokens)
2031
compiler.(ast)
2132
end
2233

lib/sql/composer/nodes/core.rb

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
# frozen_string_literal: true
22

3+
require "dry/effects"
4+
35
module SQL
46
module Composer
57
module Nodes
68
class Core
9+
include Dry::Effects.State(:tokens)
10+
11+
attr_reader :id
12+
713
attr_reader :options
814

915
def initialize(options)
1016
@options = options
17+
@id = tokens.next_id
1118
end
1219

13-
def fetch(name)
14-
@options.fetch(name)
20+
def fetch(name, default = nil)
21+
@options.fetch(name, default)
1522
end
1623

1724
def backend

lib/sql/composer/nodes/identifier.rb

+9-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,15 @@ def qualify?
3232

3333
# this is probably a stupid idea lol
3434
def ==(other)
35-
Operations::Eql.new(self, Nodes::Value.new(input: other, backend: backend))
35+
value = Nodes::Value.new(input: other, backend: backend)
36+
37+
operation = Operations::Eql.new(left: self, right: value)
38+
39+
if other.start_with?("%") && other.end_with?("%")
40+
tokens.add(other, value)
41+
end
42+
43+
operation
3644
end
3745
end
3846
end

lib/sql/composer/nodes/operations/eql.rb

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
# frozen_string_literal: true
22

3+
require "sql/composer/nodes/core"
4+
35
module SQL
46
module Composer
57
module Nodes
68
module Operations
7-
class Eql
8-
attr_reader :left, :right
9+
class Eql < Core
10+
def left
11+
fetch(:left)
12+
end
913

10-
def initialize(left, right)
11-
@left, @right = left, right
14+
def right
15+
fetch(:right)
1216
end
1317

1418
def or(other)
15-
Operations::Or.new(self, other)
19+
Operations::Or.new(left: self, right: other)
1620
end
1721
alias_method :OR, :or
1822

lib/sql/composer/nodes/operations/or.rb

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
# frozen_string_literal: true
22

3+
require "sql/composer/nodes/core"
4+
35
module SQL
46
module Composer
57
module Nodes
68
module Operations
7-
class Or
8-
attr_reader :left, :right
9+
class Or < Core
10+
def left
11+
fetch(:left)
12+
end
913

10-
def initialize(left, right)
11-
@left, @right = left, right
14+
def right
15+
fetch(:right)
1216
end
1317

1418
def to_s

lib/sql/composer/nodes/value.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module Composer
77
module Nodes
88
class Value < Core
99
def input
10-
fetch(:input)
10+
tokens.value(id, fetch(:input))
1111
end
1212

1313
def to_s

lib/sql/composer/statement.rb

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
module SQL
4+
module Composer
5+
class Statement
6+
include Enumerable
7+
8+
attr_reader :options
9+
10+
def initialize(options)
11+
@options = options
12+
end
13+
14+
def each(&block)
15+
nodes.each(&block)
16+
end
17+
18+
def set(values)
19+
tokens = compiler.tokens.new
20+
21+
values.each do |key, value|
22+
tokens.set(key, value)
23+
end
24+
25+
compiler.with(tokens: tokens)
26+
end
27+
28+
def to_s
29+
compiler.to_s
30+
end
31+
32+
def compiler
33+
options.fetch(:compiler)
34+
end
35+
36+
def nodes
37+
compiler.nodes
38+
end
39+
end
40+
end
41+
end

lib/sql/composer/tokens.rb

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
3+
module SQL
4+
module Composer
5+
class Tokens
6+
include Dry::Core::Constants
7+
8+
attr_reader :data
9+
10+
def initialize(data: {}, counter: 0)
11+
@data = data
12+
@counter = counter
13+
end
14+
15+
def add(key, node)
16+
data[key[1..-2].to_sym] = [node.id, Undefined]
17+
self
18+
end
19+
20+
def set(key, value)
21+
tuple = [data[key][0], value]
22+
data[key] = tuple
23+
self
24+
end
25+
26+
def new
27+
self.class.new(data: data.dup, counter: @counter)
28+
end
29+
30+
def value(id, default)
31+
entry = data.detect { |_, (node_id, value)| node_id.equal?(id) }
32+
entry ? entry[1][1] : default
33+
end
34+
35+
def next_id
36+
@counter += 1
37+
end
38+
end
39+
end
40+
end

0 commit comments

Comments
 (0)