activequery 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: