querylet 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +105 -10
- data/lib/querylet/parser.rb +3 -3
- data/lib/querylet/tree.rb +2 -0
- data/lib/querylet/version.rb +1 -1
- data/spec/parser_spec.rb +19 -4
- data/spec/querylet_spec.rb +25 -0
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ec97dcd15beb09f85b656e57b8ab282ec722955f411afaaef3db77ac3682230
|
4
|
+
data.tar.gz: 1d532fbbc2a5335703348f00d645f48ffe406943a0084ebf8ebf2ac97ba9c3c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f48440d625e46181aea476dfe79f3e4f354c2848cb7d6b480f4e093ebc739d1b30a019cf55356bb338db2bab29bc1be54817d4691f528817c4b54a8607a00dd0
|
7
|
+
data.tar.gz: 86552d7a090baf83feb29d94aff63474af7a8f43816027c74e07a05d35f67d3b329ffd9784348b98a6ce87d7c892cf80462755b6b5affedb50e2d29a38745a0d
|
data/README.md
CHANGED
@@ -1,21 +1,118 @@
|
|
1
|
-
|
1
|
+
# Querylet
|
2
|
+
|
3
|
+
Querylet is a templating language for SQL
|
4
|
+
and is designed to make writing raw SQL much easier.
|
5
|
+
|
6
|
+
```sql
|
7
|
+
SELECT
|
8
|
+
questions.id,
|
9
|
+
questions.uuid,
|
10
|
+
questions.question_html as question,
|
11
|
+
questions.target_type as kind,
|
12
|
+
{{#object}}
|
13
|
+
SELECT
|
14
|
+
case_study_questions.menu,
|
15
|
+
case_study_questions.questions_pool_size,
|
16
|
+
|
17
|
+
CASE {{str sub_question_type}}
|
18
|
+
WHEN 'MultiChoiceQuestion' THEN
|
19
|
+
{{> object 'questions.multiple_choice' id='{{sub_question_id}}' }} as question
|
20
|
+
WHEN 'MultiSelectQuestion' THEN
|
21
|
+
{{> object 'questions.multiple_select' id='{{sub_question_id}}' }} as question
|
22
|
+
END,
|
23
|
+
|
24
|
+
{{#array}}
|
25
|
+
SELECT
|
26
|
+
que.id,
|
27
|
+
que.uuid,
|
28
|
+
que.target_type as kind,
|
29
|
+
choices.comment,
|
30
|
+
choices.flagged,
|
31
|
+
choices.choice_value as answered,
|
32
|
+
multiple_select_questions.answers_count
|
33
|
+
FROM ts_admin_que.questions que
|
34
|
+
LEFT JOIN public.choices ON choices.question_id = que.id AND choices.attempt_id = {{id}}
|
35
|
+
LEFT JOIN ts_admin_que.multiple_select_questions ON multiple_select_questions.id = que.target_id AND que.target_type = 'MultipleSelectQuestion'
|
36
|
+
WHERE
|
37
|
+
que.id = ANY(case_study_questions.question_ids)
|
38
|
+
{{/array}} as questions
|
39
|
+
{{/object}} as case_study
|
40
|
+
FROM ts_admin_que.questions
|
41
|
+
LEFT JOIN ts_admin_que.case_study_questions ON case_study_questions.question_id = questions.id
|
42
|
+
WHERE
|
43
|
+
questions.id = {{id}}
|
44
|
+
```
|
45
|
+
|
46
|
+
## Variable Filters
|
47
|
+
|
48
|
+
### Int (Integer)
|
49
|
+
|
50
|
+
Cast variable to integer
|
51
|
+
|
52
|
+
```
|
53
|
+
{{int my_number}}
|
54
|
+
```
|
55
|
+
|
56
|
+
### Str (String)
|
57
|
+
|
58
|
+
Cast variable to string
|
2
59
|
|
3
|
-
|
60
|
+
```
|
61
|
+
{{str my_string}}
|
62
|
+
```
|
4
63
|
|
64
|
+
### Float
|
65
|
+
|
66
|
+
Cast variable to float
|
67
|
+
|
68
|
+
```
|
69
|
+
{{float my_number}}
|
70
|
+
```
|
71
|
+
|
72
|
+
### Arr (Array)
|
73
|
+
|
74
|
+
Cast to array (not a postgres array)
|
75
|
+
|
76
|
+
```
|
77
|
+
{{arr my_array}}
|
78
|
+
```
|
79
|
+
|
80
|
+
### Wild (Wildcard)
|
81
|
+
|
82
|
+
Wildcard front and back of string
|
83
|
+
|
84
|
+
```
|
85
|
+
{{wild my_string}}
|
86
|
+
```
|
87
|
+
|
88
|
+
### Variables
|
89
|
+
|
90
|
+
```
|
5
91
|
{{my_variable}}
|
92
|
+
```
|
6
93
|
|
7
|
-
|
94
|
+
### Partials
|
8
95
|
|
9
|
-
|
96
|
+
```
|
97
|
+
{{> include 'link.to.path' name='andrew' }}
|
98
|
+
{{> include 'link.to.path' name={{my_name}} }}
|
99
|
+
{{> include 'link.to.path' name={{str my_name}} }}
|
100
|
+
```
|
101
|
+
|
102
|
+
### Partial blocks
|
10
103
|
|
11
|
-
|
104
|
+
```
|
12
105
|
{{#array}}
|
13
106
|
{{/array}}
|
107
|
+
```
|
14
108
|
|
15
|
-
|
109
|
+
### If Else
|
110
|
+
|
111
|
+
```
|
16
112
|
{{#if variable}}
|
17
113
|
{{else}}
|
18
114
|
{{/end}}
|
115
|
+
```
|
19
116
|
|
20
117
|
## Parslet
|
21
118
|
|
@@ -56,12 +153,10 @@ parser.parse_with_debug(input)
|
|
56
153
|
|
57
154
|
## Parser
|
58
155
|
|
59
|
-
|
60
|
-
|
61
|
-
To see all the define rules check out `parser_helper.rb`
|
156
|
+
To see all the define rules check out `parser_spec.rb`
|
62
157
|
|
63
158
|
```
|
64
|
-
rspec spec/
|
159
|
+
bundle exec rspec spec/parser_spec.rb
|
65
160
|
```
|
66
161
|
|
67
162
|
## Transform
|
data/lib/querylet/parser.rb
CHANGED
@@ -96,7 +96,7 @@ module Querylet
|
|
96
96
|
rule(:variable) { docurly >> space? >> id.as(:variable) >> space? >> dccurly}
|
97
97
|
|
98
98
|
# Can either be a variable or a string:
|
99
|
-
rule(:parameter)
|
99
|
+
rule(:parameter) { id.as(:variable) | string }
|
100
100
|
|
101
101
|
# used in includes eg. hello='world'
|
102
102
|
rule(:parameter_kv) {
|
@@ -104,7 +104,7 @@ module Querylet
|
|
104
104
|
space? >>
|
105
105
|
eq >>
|
106
106
|
space? >>
|
107
|
-
string.as(:value) >>
|
107
|
+
(filter | variable | string).as(:value) >>
|
108
108
|
space?
|
109
109
|
}
|
110
110
|
|
@@ -147,7 +147,7 @@ module Querylet
|
|
147
147
|
rule(:nocurly) { match('[^{}]') }
|
148
148
|
rule(:eof) { any.absent? }
|
149
149
|
|
150
|
-
# String contained in Single
|
150
|
+
# String contained in Single Quotes 'content'
|
151
151
|
rule(:string) { match("'") >> match("[^']").repeat(1).as(:string) >> match("'") }
|
152
152
|
end
|
153
153
|
end
|
data/lib/querylet/tree.rb
CHANGED
data/lib/querylet/version.rb
CHANGED
data/spec/parser_spec.rb
CHANGED
@@ -10,10 +10,9 @@ RSpec.describe Querylet::Parser do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'string' do
|
13
|
-
(SELECT COALESCE(row_to_json(object_row),'{}'::json) FROM (
|
14
|
-
|
15
13
|
expect(parser.parse_with_debug("(SELECT COALESCE(row_to_json(object_row),'{}'::json) FROM (")).to eq({items:[{content: "(SELECT COALESCE(row_to_json(object_row),'{}'::json) FROM ("}]})
|
16
14
|
end
|
15
|
+
|
17
16
|
it 'variable' do
|
18
17
|
expect(parser.parse('{{worf}}')).to eq({items:[{variable: 'worf'}]})
|
19
18
|
expect(parser.parse('{{ worf}}')).to eq({items:[{variable: 'worf'}]})
|
@@ -52,8 +51,24 @@ RSpec.describe Querylet::Parser do
|
|
52
51
|
partial: 'include',
|
53
52
|
path: 'path.to.template',
|
54
53
|
parameters: [
|
55
|
-
{key: 'hello', value: {string: 'world'}},
|
56
|
-
{key: 'star', value: {string: 'trek'}}
|
54
|
+
{key: 'hello', value: { string: 'world'}},
|
55
|
+
{key: 'star' , value: { string: 'trek'}}
|
56
|
+
]
|
57
|
+
}]})
|
58
|
+
|
59
|
+
expect(parser.parse("{{> include 'path.to.template' hello={{world}} }}")).to eq({items:[{
|
60
|
+
partial: 'include',
|
61
|
+
path: 'path.to.template',
|
62
|
+
parameters: [
|
63
|
+
{key: 'hello', value: { variable: 'world'}}
|
64
|
+
]
|
65
|
+
}]})
|
66
|
+
|
67
|
+
expect(parser.parse("{{> include 'path.to.template' hello={{int world}} }}")).to eq({items:[{
|
68
|
+
partial: 'include',
|
69
|
+
path: 'path.to.template',
|
70
|
+
parameters: [
|
71
|
+
{key: 'hello', value: {filter: 'int', parameter: {variable: 'world'} }}
|
57
72
|
]
|
58
73
|
}]})
|
59
74
|
end
|
data/spec/querylet_spec.rb
CHANGED
@@ -58,6 +58,31 @@ SQL
|
|
58
58
|
expect(evaluate(template, {id: 100})).to eq(query)
|
59
59
|
end
|
60
60
|
|
61
|
+
it 'include with parameters variable' do
|
62
|
+
query = <<-SQL.chomp
|
63
|
+
(SELECT
|
64
|
+
users.email
|
65
|
+
FROM users
|
66
|
+
WHERE
|
67
|
+
users.id = 300) as email
|
68
|
+
SQL
|
69
|
+
template = "({{> include 'examples.include_with_params_vars' id={{user_id}} name='andrew' }}) as email"
|
70
|
+
expect(evaluate(template, {user_id: 300})).to eq(query)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'include with parameters filter' do
|
74
|
+
query = <<-SQL.chomp
|
75
|
+
(SELECT
|
76
|
+
users.email,
|
77
|
+
'Andrew' as name
|
78
|
+
FROM users
|
79
|
+
WHERE
|
80
|
+
users.id = 100) as email
|
81
|
+
SQL
|
82
|
+
template = "({{> include 'examples.include_with_params_filter' name={{str my_name}} }}) as email"
|
83
|
+
expect(evaluate(template, {my_name: "Andrew", id: 100})).to eq(query)
|
84
|
+
end
|
85
|
+
|
61
86
|
it 'object' do
|
62
87
|
query = <<-SQL.chomp
|
63
88
|
(SELECT COALESCE(row_to_json(object_row),'{}'::json) FROM (
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: querylet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ExamPro
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -74,7 +74,7 @@ homepage: http://exampro.co
|
|
74
74
|
licenses:
|
75
75
|
- MIT
|
76
76
|
metadata: {}
|
77
|
-
post_install_message:
|
77
|
+
post_install_message:
|
78
78
|
rdoc_options: []
|
79
79
|
require_paths:
|
80
80
|
- lib
|
@@ -89,11 +89,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '0'
|
91
91
|
requirements: []
|
92
|
-
rubygems_version: 3.
|
93
|
-
signing_key:
|
92
|
+
rubygems_version: 3.4.10
|
93
|
+
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: Querylet
|
96
96
|
test_files:
|
97
|
-
- spec/spec_helper.rb
|
98
97
|
- spec/parser_spec.rb
|
99
98
|
- spec/querylet_spec.rb
|
99
|
+
- spec/spec_helper.rb
|