activequery 0.2.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72acf6bff5b58b74b7738ac87e50ca9aa520e4186a3d46b85294fc7671e5bce0
4
- data.tar.gz: c6dd9784750fa6d6f8cefbe24bc5333c79b8e3d5a063a27f5f5acdbff89b832d
3
+ metadata.gz: dfecf5a3421fd5763c30d60a3c2bb2c9722306d641a6ae5e32729909e239fceb
4
+ data.tar.gz: 86be01caf81eb11756ceacd8270f786dd3676ab60214e026b27c0453d59301cb
5
5
  SHA512:
6
- metadata.gz: 86eaede33b0564252eef9216bdee12f9e62a5ee23417281ffa7aff6326fcd521545dcd2b3670ee9c5f38a0df9a4c891aaa8f80aa934eb4f96d46c3821f23f52b
7
- data.tar.gz: 3e7423324da0a9733c87ee8b545b4852f1b20988b170fc1fb3a8aecc519b97d951aefccab7c4ed82fc805866cc25b70a92f52882af480f8819bd7de7970813f6
6
+ metadata.gz: 1a2f84ce98adb36d251946d9136a83aadb33f74fa3ecc403fcd1ddb1ddf34f300d6cf20f98eb336f5e4986fd3b77379b4607d8a485bb40d42964b16a30502100
7
+ data.tar.gz: 3c0942ab98cfeffda8fdf9f0201d0a278e9d5ca7a0a1d74e4f33e2d17f5a92e17457c3c0b4141c9605d6dfdfa790e6f0f62678e64523554c6e172d948e8670df
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- activequery (0.2.0)
4
+ activequery (0.2.1)
5
5
  strscan (~> 1.0)
6
6
 
7
7
  GEM
@@ -18,6 +18,7 @@ GEM
18
18
  coderay (~> 1.1.0)
19
19
  method_source (~> 0.9.0)
20
20
  rake (10.5.0)
21
+ rantly (2.0.0)
21
22
  strscan (1.0.0)
22
23
 
23
24
  PLATFORMS
@@ -31,6 +32,7 @@ DEPENDENCIES
31
32
  pg (~> 1.0)
32
33
  pry
33
34
  rake (~> 10.0)
35
+ rantly (~> 2.0.0)
34
36
 
35
37
  BUNDLED WITH
36
38
  1.17.2
data/README.md CHANGED
@@ -81,7 +81,8 @@ end
81
81
  - [x] PostgreSQL Adapter
82
82
  - [x] Ruby erb inside sql template files
83
83
  - [x] Async/Stream results (ideal for realtime reporting/analytics)
84
- - [ ] Named parameters, and ?-style positional parameters
84
+ - [x] Named parameters
85
+ - [ ] ?-style positional parameters
85
86
  - [ ] class: MyClass param to create or extend ruby class with
86
87
  - [ ] Import/Export to Materialized Views
87
88
  - [ ] Retrieving SQL templates from custom stores (Redis, Riak)
@@ -49,5 +49,6 @@ Gem::Specification.new do |spec|
49
49
  spec.add_development_dependency "pry"
50
50
  spec.add_development_dependency 'pg', '~> 1.0'
51
51
  spec.add_development_dependency 'benchmark-memory', '~> 0.1.2'
52
+ spec.add_development_dependency 'rantly', '~> 2.0.0'
52
53
 
53
54
  end
@@ -3,6 +3,10 @@ require "active_query/configuration"
3
3
  require "active_query/sql_template"
4
4
  require "active_query/data_adapters/postgresql_adapter"
5
5
  require 'pg'
6
+
7
+ class ApplicationError < StandardError
8
+ end
9
+
6
10
  module ActiveQuery
7
11
  include ActiveQuery::DataAdapters
8
12
  # Configuration
@@ -22,7 +26,7 @@ module ActiveQuery
22
26
  yield(config)
23
27
  end
24
28
 
25
- # runners...
29
+ # WIP runners...
26
30
  # Full-Scan
27
31
  def self.run(query)
28
32
  if query.is_a? Symbol
@@ -67,18 +71,20 @@ module ActiveQuery
67
71
  # Build heleper methods for query names
68
72
  #fail TemplatePathError, "templates path missing" if self.config.template_path.empty?
69
73
  puts "Loading SQL templates from #{self.config.template_path}"
70
- t = ActiveQuery::SQLTemplate.new(self.config)
71
- t.load!
72
74
 
73
- t.templates.each do |query|
74
- define_singleton_method(:"#{query.name}") do |params=nil|
75
- query.query
75
+ begin
76
+ t = ActiveQuery::SQLTemplate.new(self.config)
77
+ t.load!
78
+ t.templates.each do |query|
79
+ if query
80
+ define_singleton_method(:"#{query.name}") do |params=nil|
81
+ query.query
82
+ end
76
83
  end
77
84
  end
78
-
79
85
  puts "SQL templates loaded."
80
86
  rescue ApplicationError => err
81
- $stderr.puts "%p ::SQLTemplate.load! %s" % [ err.class, err.message ]
82
-
83
-
84
- end
87
+ $stderr.puts "%p ::ActiveQuery.load! %s" % [ err.class, err.message ]
88
+ end
89
+
90
+ end
@@ -1,11 +1,26 @@
1
1
  module ActiveQuery
2
2
  module DataAdapters
3
3
  class AdapterBase
4
-
4
+ # WIP
5
5
  def initialize(connection, logger = nil, config = {})
6
6
  super()
7
7
  @connection = connection
8
8
  end
9
+
10
+ def transaction(*args, &blk)
11
+ @connection.execute(false) do |conn|
12
+ super
13
+ end
14
+ end
15
+
16
+ def real_connection
17
+ @connection.connection
18
+ end
19
+
20
+ def open_transactions
21
+ real_connection.open_transactions
22
+ end
23
+
9
24
 
10
25
  def exec(conn)
11
26
  raise "Not implemented"
@@ -2,23 +2,32 @@ module ActiveQuery
2
2
  module SQLParser
3
3
 
4
4
  require 'strscan'
5
- class SyntaxError < StandardError; end
5
+
6
+ class InvalidQueryError < ArgumentError; end
7
+ class SyntaxError < StandardError
8
+ attr_reader :line, :pos
9
+ def initialize(msg = "", line:, pos:)
10
+ msg = "Missing #{msg} on line #{line} (pos. #{pos})"
11
+ super(msg)
12
+ end
13
+ end
6
14
 
7
15
  Query = Struct.new(:name, :params, :comment, :query)
8
16
 
9
17
  WHITESPACE = /\s+/
10
18
  NAME = /^\s*--\s*name\s*:\s*(.+)/
11
- END_QUERY = /;/
19
+ QNAME = /^\s*--\s*name\s*:/
20
+ SEMICOLON = /;/
12
21
  PARAMS = /\(\:\s*([^)]+?)\s*\)/
13
22
  ALL_COMMENTS = /(?-m:--.*)|(?m:--\*.--?\*\/)/
14
23
  PARAM = /:\w+/
15
24
 
16
25
  def self.parse_query(query)
17
- @scanner = StringScanner.new(query)
26
+ @scanner = StringScanner.new(query.strip)
18
27
  @line = 0
19
28
  @query = Query.new
20
29
 
21
- until @scanner.eos? || @scanner.check_until(END_QUERY).nil?
30
+ until @scanner.eos?
22
31
  @line += 1
23
32
  parse_line
24
33
  end
@@ -29,27 +38,38 @@ module ActiveQuery
29
38
  private
30
39
  def self.parse_line
31
40
  @query.params = []
32
-
33
- # Query name match: --name
34
- @scanner.skip(NAME)
35
- qname = @scanner.captures
36
- if qname
37
- @query.name = qname.first
38
- else
39
- fail SyntaxError, "error on line #{@line} (pos. #{@scanner.pos})"
41
+ # Query name match: --name:
42
+ header = @scanner.check_until(NAME)
43
+ unless header
44
+ fail SyntaxError.new("'-- name:'", line: @line, pos: @scanner.pos)
45
+ end
46
+
47
+ ## ===============================
48
+ # Query name match after: --name:
49
+ # Todo: test missing name
50
+ query_name = @scanner.scan_until(NAME)
51
+ unless query_name
52
+ fail SyntaxError.new("query name", line: @line, pos: @scanner.pos)
40
53
  end
54
+ @query.name = @scanner.captures&.first.strip
41
55
 
42
- @query.query = @scanner.rest
43
- fail SyntaxError unless @query.query
56
+ # SQL expression
57
+ @scanner.skip_until(ALL_COMMENTS)
58
+ @scanner.skip_until(/^\s+/)
59
+ query = @scanner.check_until(SEMICOLON)
60
+ if query && query != ';'
61
+ @query.query = query.strip
62
+ else
63
+ fail SyntaxError.new("SQL expression", line: @line, pos: @scanner.pos)
64
+ end
44
65
 
45
66
  # All params
46
67
  until @scanner.check_until(PARAM).nil?
47
68
  @scanner.scan_until(PARAM)
48
69
  @query.params.push @scanner.matched
49
70
  end
50
-
51
- # End of query match: ;
52
- @scanner.scan_until(END_QUERY)
71
+ # done
72
+ @scanner.scan_until(SEMICOLON) # important! don't touch
53
73
  end
54
74
 
55
75
  # and this only work for postgres - split transform from struct
@@ -65,6 +85,10 @@ module ActiveQuery
65
85
  end
66
86
  end
67
87
 
88
+ def self.valid_query?(query)
89
+ query.name && query.name != "" &&
90
+ query.query && query.query != ""
91
+ end
68
92
 
69
93
  end
70
94
  end
@@ -25,7 +25,8 @@ module ActiveQuery
25
25
  else
26
26
  Find.find(template_path) do |path|
27
27
  if File.basename(path) =~ /sql$/
28
- @templates << parse_sql(path)
28
+ sql = parse_sql(path)
29
+ @templates << sql if sql
29
30
  end
30
31
  end
31
32
  end
@@ -36,14 +37,19 @@ module ActiveQuery
36
37
  end
37
38
 
38
39
  private
40
+
39
41
  def read_sql_file(path:)
40
42
  open(path, "r") { |t| ERB.new(t.read).result(binding) }
41
43
  end
42
44
 
43
45
  def parse_sql(path)
44
- sql_template = read_sql_file(path: path)
45
- ActiveQuery::SQLParser.parse_query(sql_template)
46
- end
46
+ sql_template = read_sql_file(path: path)
47
+ begin
48
+ ActiveQuery::SQLParser.parse_query(sql_template)
49
+ rescue ActiveQuery::SQLParser::SyntaxError => err
50
+ $stderr.puts "%p %s:" % [ err.class, err.message ]
51
+ end
47
52
 
53
+ end
48
54
  end
49
- end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveQuery
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activequery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-07 00:00:00.000000000 Z
11
+ date: 2019-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: strscan
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.1.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: rantly
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.0.0
111
125
  description: Raw sql with ruby - ideal for reports, large queries, separating SQL
112
126
  from code logic and CQRS
113
127
  email: