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 +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +2 -1
- data/activequery.gemspec +1 -0
- data/lib/active_query.rb +17 -11
- data/lib/active_query/data_adapters/adapter_base.rb +16 -1
- data/lib/active_query/sql_parser.rb +41 -17
- data/lib/active_query/sql_template.rb +11 -5
- data/lib/active_query/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfecf5a3421fd5763c30d60a3c2bb2c9722306d641a6ae5e32729909e239fceb
|
4
|
+
data.tar.gz: 86be01caf81eb11756ceacd8270f786dd3676ab60214e026b27c0453d59301cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a2f84ce98adb36d251946d9136a83aadb33f74fa3ecc403fcd1ddb1ddf34f300d6cf20f98eb336f5e4986fd3b77379b4607d8a485bb40d42964b16a30502100
|
7
|
+
data.tar.gz: 3c0942ab98cfeffda8fdf9f0201d0a278e9d5ca7a0a1d74e4f33e2d17f5a92e17457c3c0b4141c9605d6dfdfa790e6f0f62678e64523554c6e172d948e8670df
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activequery (0.2.
|
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
|
-
- [
|
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)
|
data/activequery.gemspec
CHANGED
data/lib/active_query.rb
CHANGED
@@ -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
|
-
|
74
|
-
|
75
|
-
|
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 ::
|
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
|
-
|
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
|
-
|
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?
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
43
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
46
|
-
|
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
|
data/lib/active_query/version.rb
CHANGED
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.
|
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-
|
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:
|