querybuilder 0.5.9 → 0.7.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.
- data/History.txt +29 -25
- data/Manifest.txt +20 -9
- data/README.rdoc +73 -10
- data/Rakefile +62 -30
- data/lib/extconf.rb +3 -0
- data/lib/query_builder.rb +39 -898
- data/lib/query_builder/error.rb +7 -0
- data/lib/query_builder/info.rb +3 -0
- data/lib/query_builder/parser.rb +80 -0
- data/lib/query_builder/processor.rb +714 -0
- data/lib/query_builder/query.rb +273 -0
- data/lib/querybuilder_ext.c +1870 -0
- data/lib/querybuilder_ext.rl +418 -0
- data/lib/querybuilder_rb.rb +1686 -0
- data/lib/querybuilder_rb.rl +214 -0
- data/lib/querybuilder_syntax.rl +47 -0
- data/old_QueryBuilder.rb +946 -0
- data/querybuilder.gemspec +42 -15
- data/tasks/build.rake +20 -0
- data/test/dummy_test.rb +21 -0
- data/test/mock/custom_queries/test.yml +5 -4
- data/test/mock/dummy.rb +9 -0
- data/test/mock/dummy_processor.rb +160 -0
- data/test/mock/queries/bar.yml +1 -1
- data/test/mock/queries/foo.yml +2 -2
- data/test/mock/user_processor.rb +34 -0
- data/test/query_test.rb +38 -0
- data/test/querybuilder/basic.yml +91 -0
- data/test/{query_builder → querybuilder}/custom.yml +11 -11
- data/test/querybuilder/errors.yml +32 -0
- data/test/querybuilder/filters.yml +115 -0
- data/test/querybuilder/group.yml +7 -0
- data/test/querybuilder/joins.yml +37 -0
- data/test/querybuilder/mixed.yml +18 -0
- data/test/querybuilder/rubyless.yml +15 -0
- data/test/querybuilder_test.rb +111 -0
- data/test/test_helper.rb +8 -3
- metadata +66 -19
- data/test/mock/dummy_query.rb +0 -114
- data/test/mock/user_query.rb +0 -55
- data/test/query_builder/basic.yml +0 -60
- data/test/query_builder/errors.yml +0 -50
- data/test/query_builder/filters.yml +0 -43
- data/test/query_builder/joins.yml +0 -25
- data/test/query_builder/mixed.yml +0 -12
- data/test/query_builder_test.rb +0 -36
@@ -4,50 +4,50 @@ it_should_be_available:
|
|
4
4
|
context:
|
5
5
|
custom_query_group: test
|
6
6
|
src: "abc"
|
7
|
-
res: "
|
7
|
+
res: "%Q{SELECT a,34 AS number,c FROM test WHERE 3 AND 2 AND 1 ORDER BY a ASC}"
|
8
8
|
|
9
9
|
it_should_be_customizable:
|
10
10
|
context:
|
11
11
|
custom_query_group: test
|
12
12
|
src: "foo where name < 50"
|
13
|
-
res: "
|
13
|
+
res: "%Q{SELECT foo FROM objects WHERE objects.name < 50 ORDER BY f DESC}"
|
14
14
|
|
15
15
|
it_should_be_customizable_with_select_attributes:
|
16
16
|
context:
|
17
17
|
custom_query_group: test
|
18
18
|
src: "abc where number < 50"
|
19
|
-
res: "
|
19
|
+
res: "%Q{SELECT a,34 AS number,c FROM test WHERE (34) < 50 AND 3 AND 2 AND 1 ORDER BY a ASC}"
|
20
20
|
|
21
21
|
it_should_not_find_queries_not_in_group:
|
22
22
|
context:
|
23
23
|
custom_query_group: test
|
24
24
|
src: "bar"
|
25
|
-
res: "
|
25
|
+
res: "Unknown relation 'bar'."
|
26
26
|
|
27
27
|
# test2 context (queries = [foo,bar])
|
28
28
|
it_should_not_find_queries_not_in_file_named_group:
|
29
29
|
context:
|
30
30
|
custom_query_group: test2
|
31
31
|
src: "abc"
|
32
|
-
res: "
|
32
|
+
res: "Unknown relation 'abc'."
|
33
33
|
|
34
34
|
it_should_find_queries_in_group_list:
|
35
35
|
context:
|
36
36
|
custom_query_group: test2
|
37
37
|
src: "bar"
|
38
|
-
res: "
|
38
|
+
res: "%Q{SELECT bar FROM bart}"
|
39
39
|
|
40
|
-
|
40
|
+
it_should_not_use_the_first_table_as_main:
|
41
41
|
context:
|
42
42
|
custom_query_group: test
|
43
|
-
src: "two_table where x = '4' and name like '
|
44
|
-
res: "
|
43
|
+
src: "two_table where x = '4' and name like 'b%'"
|
44
|
+
res: "%Q{SELECT x AS x,IF(table_one.y,table_one.y,table_two.z) AS y,table_two.name FROM table_one,table_two WHERE (x) = '4' AND table_one.name LIKE 'b%'}"
|
45
45
|
|
46
46
|
it_should_use_main_table_as_main:
|
47
47
|
context:
|
48
48
|
custom_query_group: test
|
49
49
|
src: "two_table_main where name = '4'"
|
50
|
-
res: "
|
50
|
+
res: "%Q{SELECT x FROM foo,table_one,table_two WHERE foo.name = '4'}"
|
51
51
|
|
52
52
|
it_should_limit_the_entries:
|
53
53
|
context:
|
@@ -59,4 +59,4 @@ it_should_paginate_the_entries:
|
|
59
59
|
context:
|
60
60
|
custom_query_group: test
|
61
61
|
src: "abc limit 4 paginate foo"
|
62
|
-
res: "[
|
62
|
+
res: "[%Q{SELECT a,34 AS number,c FROM test WHERE 3 AND 2 AND 1 ORDER BY a ASC LIMIT 4 OFFSET ?}, ((foo.to_i > 0 ? foo.to_i : 1)-1)*4]"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
bad_relation:
|
2
|
+
src: "bolobolo"
|
3
|
+
res: "Unknown relation 'bolobolo'."
|
4
|
+
|
5
|
+
bad_relation_in_alternate_query:
|
6
|
+
src: "(bolobolo) or (letters in project)"
|
7
|
+
res: "Unknown relation 'bolobolo'."
|
8
|
+
|
9
|
+
order:
|
10
|
+
src: "objects in project order by bad asc"
|
11
|
+
res: "Unknown field 'bad'."
|
12
|
+
|
13
|
+
offset_without_limit:
|
14
|
+
src: "objects in project offset 3"
|
15
|
+
res: "Invalid offset (used without limit)."
|
16
|
+
|
17
|
+
legacy_many_clauses:
|
18
|
+
src: letters or foo
|
19
|
+
res: "Unknown relation 'foo'."
|
20
|
+
|
21
|
+
bad_equation:
|
22
|
+
src: "objects where event_at > 2006.04.01"
|
23
|
+
res: 'Syntax error near ".04.01".'
|
24
|
+
|
25
|
+
bad_plus_plus:
|
26
|
+
src: "objects where 1 + 3 + + 5 > event_at"
|
27
|
+
res: 'Syntax error near " + + 5 > event_at".'
|
28
|
+
|
29
|
+
or_clause_with_filter:
|
30
|
+
src: "recipients where name = 'foo' or objects"
|
31
|
+
sxp: '[:query, [:filter, [:relation, "recipients"], [:or, [:"=", [:field, "name"], [:string, "foo"]], [:field, "objects"]]]]'
|
32
|
+
res: "Unknown field 'objects'."
|
@@ -0,0 +1,115 @@
|
|
1
|
+
simple:
|
2
|
+
src: "objects where name = 'foo' in site"
|
3
|
+
sxp: '[:query, [:scope, [:filter, [:relation, "objects"], [:"=", [:field, "name"], [:string, "foo"]]], "site"]]'
|
4
|
+
res: "%Q{SELECT objects.* FROM objects WHERE objects.name = 'foo'}"
|
5
|
+
|
6
|
+
recipients_where_kpath:
|
7
|
+
src: "recipients where kpath like 'NRCC%'"
|
8
|
+
res: "[%Q{SELECT objects.* FROM links,objects WHERE objects.kpath LIKE 'NRCC%' AND objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?}, id]"
|
9
|
+
|
10
|
+
hand_made_class_filter:
|
11
|
+
src: "recipients where kpath like 'NRCC%'"
|
12
|
+
res: "[%Q{SELECT objects.* FROM links,objects WHERE objects.kpath LIKE 'NRCC%' AND objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?}, id]"
|
13
|
+
|
14
|
+
better_class_filter:
|
15
|
+
src: "recipients where class = 'Client'"
|
16
|
+
res: "[%Q{SELECT objects.* FROM links,objects WHERE objects.kpath LIKE ? AND objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?}, \"NRCC%\", id]"
|
17
|
+
|
18
|
+
like_filter_with_scope:
|
19
|
+
src: "letters where name like 'a%' in site"
|
20
|
+
sxp: '[:query, [:scope, [:filter, [:relation, "letters"], [:like, [:field, "name"], [:string, "a%"]]], "site"]]'
|
21
|
+
res: "%Q{SELECT objects.* FROM objects WHERE objects.name LIKE 'a%' AND objects.kpath LIKE 'NNL%'}"
|
22
|
+
|
23
|
+
not_like_with_scope:
|
24
|
+
src: "letters where name not like 'a%' in site"
|
25
|
+
sxp: '[:query, [:scope, [:filter, [:relation, "letters"], [:not, [:like, [:field, "name"], [:string, "a%"]]]], "site"]]'
|
26
|
+
res: "%Q{SELECT objects.* FROM objects WHERE objects.name NOT LIKE 'a%' AND objects.kpath LIKE 'NNL%'}"
|
27
|
+
|
28
|
+
letters_group_by_name:
|
29
|
+
sxp: '[:query, [:group, [:relation, "letters"], [:field, "name"]]]'
|
30
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.kpath LIKE 'NNL%' AND objects.parent_id = ? GROUP BY objects.name}, id]"
|
31
|
+
|
32
|
+
recipients_group_by_name:
|
33
|
+
sxp: '[:query, [:group, [:relation, "recipients"], [:field, "name"]]]'
|
34
|
+
res: "[%Q{SELECT objects.* FROM links,objects WHERE objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ? GROUP BY objects.name}, id]"
|
35
|
+
|
36
|
+
custom_query_having:
|
37
|
+
context:
|
38
|
+
custom_query_group: test
|
39
|
+
src: "abc where number > 12"
|
40
|
+
res: "%Q{SELECT a,34 AS number,c FROM test WHERE (34) > 12 AND 3 AND 2 AND 1 ORDER BY a ASC}"
|
41
|
+
|
42
|
+
equation_in_filter:
|
43
|
+
src: "objects where event_at > REF_DATE + custom_a months"
|
44
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:>, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
45
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at > now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
46
|
+
|
47
|
+
equation_in_filter_using_gt:
|
48
|
+
src: "objects where event_at gt REF_DATE + custom_a months"
|
49
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:gt, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
50
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at > now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
51
|
+
|
52
|
+
equation_in_filter_using_ge:
|
53
|
+
src: "objects where event_at ge REF_DATE + custom_a months"
|
54
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:ge, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
55
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at >= now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
56
|
+
|
57
|
+
equation_in_filter_using_eq:
|
58
|
+
src: "objects where event_at eq REF_DATE + custom_a months"
|
59
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:eq, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
60
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at = now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
61
|
+
|
62
|
+
equation_in_filter_using_le:
|
63
|
+
src: "objects where event_at le REF_DATE + custom_a months"
|
64
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:le, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
65
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at <= now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
66
|
+
|
67
|
+
equation_in_filter_using_lt:
|
68
|
+
src: "objects where event_at lt REF_DATE + custom_a months"
|
69
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:lt, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
70
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at < now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
71
|
+
|
72
|
+
equation_in_filter_using_ne:
|
73
|
+
src: "objects where event_at ne REF_DATE + custom_a months"
|
74
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:ne, [:field, "event_at"], [:+, [:field, "REF_DATE"], [:interval, [:field, "custom_a"], "month"]]]]]'
|
75
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at <> now() + INTERVAL objects.custom_a MONTH AND objects.parent_id = ?}, id]"
|
76
|
+
|
77
|
+
|
78
|
+
equation_with_date_interval:
|
79
|
+
src: "objects where event_at > '2006-04-01' + 6 week"
|
80
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:>, [:field, "event_at"], [:+, [:string, "2006-04-01"], [:interval, [:integer, "6"], "week"]]]]]'
|
81
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.event_at > '2006-04-01' + INTERVAL 6 WEEK AND objects.parent_id = ?}, id]"
|
82
|
+
|
83
|
+
equation_and_or_par:
|
84
|
+
src: "objects where event_at > '2006-04-01' or name like 'foo%'"
|
85
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:or, [:>, [:field, "event_at"], [:string, "2006-04-01"]], [:like, [:field, "name"], [:string, "foo%"]]]]]'
|
86
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE (objects.event_at > '2006-04-01' OR objects.name LIKE 'foo%') AND objects.parent_id = ?}, id]"
|
87
|
+
|
88
|
+
equation_par:
|
89
|
+
src: "objects where (1 > 2 or 2 > 3) and 4 = 5 "
|
90
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:and, [:par, [:or, [:>, [:integer, "1"], [:integer, "2"]], [:>, [:integer, "2"], [:integer, "3"]]]], [:"=", [:integer, "4"], [:integer, "5"]]]]]'
|
91
|
+
# res: "[%Q{SELECT objects.* FROM objects WHERE objects.parent_id = ? AND (1 > 2 OR 2 > 3) AND 4 = 5}, id]"
|
92
|
+
|
93
|
+
is_not_null:
|
94
|
+
src: "objects where name is not null"
|
95
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:is, [:field, "name"], [:raw, "not null"]]]]'
|
96
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.name IS NOT NULL AND objects.parent_id = ?}, id]"
|
97
|
+
|
98
|
+
is_null:
|
99
|
+
src: "objects where name is null"
|
100
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:is, [:field, "name"], [:raw, "null"]]]]'
|
101
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE objects.name IS NULL AND objects.parent_id = ?}, id]"
|
102
|
+
|
103
|
+
match:
|
104
|
+
src: "objects where fulltext match 'one'"
|
105
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:match, [:field, "fulltext"], [:string, "one"]]]]'
|
106
|
+
|
107
|
+
functions:
|
108
|
+
src: "objects where event_at.year = REF_DATE.year"
|
109
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:"=", [:function, [:field, "event_at"], [:method, "year"]], [:function, [:field, "REF_DATE"], [:method, "year"]]]]]'
|
110
|
+
res: "[%Q{SELECT objects.* FROM objects WHERE strftime('%Y',objects.event_at) = strftime('%Y',now()) AND objects.parent_id = ?}, id]"
|
111
|
+
|
112
|
+
filter_empty_literal:
|
113
|
+
src: "objects where \"\" = ''"
|
114
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:"=", [:dstring, ""], [:string, ""]]]]'
|
115
|
+
sql: "SELECT objects.* FROM objects WHERE '' = '' AND objects.parent_id = 123"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
group_by_function:
|
2
|
+
src: "objects in site group by event_at.year"
|
3
|
+
res: "%Q{SELECT objects.* FROM objects GROUP BY strftime('%Y',objects.event_at)}"
|
4
|
+
|
5
|
+
group_and_order:
|
6
|
+
src: "objects in site group by event_at.year order by event_at asc"
|
7
|
+
res: "%Q{SELECT objects.* FROM objects GROUP BY strftime('%Y',objects.event_at) ORDER BY objects.event_at ASC}"
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
icons_from_recipients:
|
3
|
+
sxp: '[:query, [:from, [:relation, "icons"], [:relation, "recipients"]]]'
|
4
|
+
res: "[%Q{SELECT objects.* FROM links,links AS li1,objects,objects AS ob1 WHERE objects.id = li1.source_id AND li1.relation_id = 5 AND li1.target_id = ob1.id AND ob1.id = links.target_id AND links.relation_id = 4 AND links.source_id = ? GROUP BY objects.id}, id]"
|
5
|
+
|
6
|
+
icons_from_recipients_from_letters:
|
7
|
+
sxp: '[:query, [:from, [:from, [:relation, "icons"], [:relation, "recipients"]], [:relation, "letters"]]]'
|
8
|
+
|
9
|
+
letters_from_recipients:
|
10
|
+
res: "[%Q{SELECT objects.* FROM links,objects,objects AS ob1 WHERE objects.kpath LIKE 'NNL%' AND objects.parent_id = ob1.id AND ob1.id = links.target_id AND links.relation_id = 4 AND links.source_id = ? GROUP BY objects.id}, id]"
|
11
|
+
|
12
|
+
objects_from_recipients:
|
13
|
+
res: "[%Q{SELECT objects.* FROM links,objects,objects AS ob1 WHERE objects.parent_id = ob1.id AND ob1.id = links.target_id AND links.relation_id = 4 AND links.source_id = ? GROUP BY objects.id}, id]"
|
14
|
+
|
15
|
+
parent_from_parent:
|
16
|
+
sxp: '[:query, [:from, [:relation, "parent"], [:relation, "parent"]]]'
|
17
|
+
res: "[%Q{SELECT objects.* FROM objects,objects AS ob1 WHERE objects.id = ob1.parent_id AND ob1.id = ? GROUP BY objects.id}, parent_id]"
|
18
|
+
|
19
|
+
children_from_objects_in_project:
|
20
|
+
res: "[%Q{SELECT objects.* FROM objects,objects AS ob1 WHERE objects.parent_id = ob1.id AND ob1.project_id = ? GROUP BY objects.id}, project_id]"
|
21
|
+
|
22
|
+
tags:
|
23
|
+
sxp: '[:query, [:relation, "tags"]]'
|
24
|
+
res: "%Q{SELECT objects.* FROM objects INNER JOIN tags ON objects.id = tags.node_id}"
|
25
|
+
|
26
|
+
complex_from_with_scopes:
|
27
|
+
src: "letters where name = 'foo' in project from letters in section"
|
28
|
+
sxp: '[:query, [:from, [:scope, [:filter, [:relation, "letters"], [:"=", [:field, "name"], [:string, "foo"]]], "project"], [:scope, [:relation, "letters"], "section"]]]'
|
29
|
+
|
30
|
+
letters_in_project_from_letters:
|
31
|
+
sxp: '[:query, [:from, [:scope, [:relation, "letters"], "project"], [:relation, "letters"]]]'
|
32
|
+
res: "[%Q{SELECT objects.* FROM objects,objects AS ob1 WHERE objects.kpath LIKE 'NNL%' AND objects.project_id = ob1.id AND ob1.kpath LIKE 'NNL%' AND ob1.parent_id = ? GROUP BY objects.id}, id]"
|
33
|
+
|
34
|
+
letters_in_project_from_letters_group_by:
|
35
|
+
src: "letters in project from letters group by name,id"
|
36
|
+
sxp: '[:query, [:group, [:from, [:scope, [:relation, "letters"], "project"], [:relation, "letters"]], [:field, "name"], [:field, "id"]]]'
|
37
|
+
res: "[%Q{SELECT objects.* FROM objects,objects AS ob1 WHERE objects.kpath LIKE 'NNL%' AND objects.project_id = ob1.id AND ob1.kpath LIKE 'NNL%' AND ob1.parent_id = ? GROUP BY objects.name, objects.id}, id]"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
users_from_objects:
|
2
|
+
sxp: '[:query, [:from, [:relation, "users"], [:relation, "objects"]]]'
|
3
|
+
res: "TestUser: [%Q{SELECT users.* FROM objects AS ob1,users WHERE users.node_id = ob1.id AND ob1.parent_id = ? GROUP BY users.id ORDER BY users.name ASC, users.first_name ASC}, id]"
|
4
|
+
|
5
|
+
users_where_name_from_objects:
|
6
|
+
src: "users where name eq 'bob' from objects"
|
7
|
+
res: "TestUser: [%Q{SELECT users.* FROM objects AS ob1,users WHERE users.name = 'bob' AND users.node_id = ob1.id AND ob1.parent_id = ? GROUP BY users.id ORDER BY users.name ASC, users.first_name ASC}, id]"
|
8
|
+
|
9
|
+
objects_from_users_from_objects:
|
10
|
+
src: "objects from users where name = 'foo' from objects where event_at > REF_DATE order by event_at asc"
|
11
|
+
res: "[%Q{SELECT objects.* FROM objects,objects AS ob1,users AS us1 WHERE objects.id = us1.node_id AND us1.name = 'foo' AND us1.node_id = ob1.id AND ob1.event_at > now() AND ob1.parent_id = ? GROUP BY objects.id ORDER BY objects.event_at ASC}, id]"
|
12
|
+
|
13
|
+
users:
|
14
|
+
res: "TestUser: [%Q{SELECT users.* FROM users WHERE users.node_id = ? ORDER BY users.name ASC, users.first_name ASC}, id]"
|
15
|
+
|
16
|
+
users_with_filter:
|
17
|
+
src: "users where name = 'foo'"
|
18
|
+
res: "TestUser: [%Q{SELECT users.* FROM users WHERE users.name = 'foo' AND users.node_id = ? ORDER BY users.name ASC, users.first_name ASC}, id]"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
parsing:
|
2
|
+
src: 'objects where name like "#{name}%" or event_at > #{params[:blow]} or name = #{this.is.ruby("with more #{stuff}")}'
|
3
|
+
sxp: '[:query, [:filter, [:relation, "objects"], [:or, [:or, [:like, [:field, "name"], [:dstring, "\#{name}%"]], [:>, [:field, "event_at"], [:rubyless, "params[:blow]"]]], [:"=", [:field, "name"], [:rubyless, "this.is.ruby(\"with more \#{stuff}\")"]]]]]'
|
4
|
+
|
5
|
+
dstring_eval:
|
6
|
+
src: 'objects where name like "#{params[:name]}%"'
|
7
|
+
res: '[%Q{SELECT objects.* FROM objects WHERE objects.name LIKE ? AND objects.parent_id = ?}, "#{get_params[:name]}%", id]'
|
8
|
+
|
9
|
+
eval:
|
10
|
+
src: 'objects where name = #{params[:name]}'
|
11
|
+
res: '[%Q{SELECT objects.* FROM objects WHERE objects.name = ? AND objects.parent_id = ?}, get_params[:name], id]'
|
12
|
+
|
13
|
+
date_function:
|
14
|
+
src: 'objects where name = #{params[:name]}.year'
|
15
|
+
res: "/objects.name = strftime\('%Y',\?\)/"
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
class StringHash
|
5
|
+
end
|
6
|
+
|
7
|
+
class DummyQueryBuilder < Test::Unit::TestCase
|
8
|
+
yamltest
|
9
|
+
include RubyLess::SafeClass
|
10
|
+
safe_method :params => {:class => StringHash, :method => 'get_params'}
|
11
|
+
safe_method :id => Number, :parent_id => Number, :project_id => Number
|
12
|
+
|
13
|
+
safe_method_for StringHash, [:[], Symbol] => String
|
14
|
+
safe_method_for StringHash, [:[], String] => String
|
15
|
+
|
16
|
+
def id; 123; end
|
17
|
+
def parent_id; 333; end
|
18
|
+
def project_id; 9999; end
|
19
|
+
def connection; self; end
|
20
|
+
|
21
|
+
context 'A query processor' do
|
22
|
+
subject do
|
23
|
+
DummyProcessor
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'raise a QueryBuilder::SyntaxError on syntax errors' do
|
27
|
+
assert_raise(QueryBuilder::SyntaxError) do
|
28
|
+
subject.new('this is a bad source')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'return a query object on query' do
|
33
|
+
assert_kind_of QueryBuilder::Query, subject.new('objects').query
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'Including QueryBuilder' do
|
38
|
+
context 'in a class' do
|
39
|
+
subject do
|
40
|
+
Class.new do
|
41
|
+
include QueryBuilder
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'receive class method query_compiler' do
|
46
|
+
assert_nothing_raised do
|
47
|
+
subject.query_compiler = 'Foo'
|
48
|
+
assert_equal 'Foo', subject.query_compiler
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
should 'receive class method query_compiler on sub_class' do
|
53
|
+
sub_class = Class.new(subject)
|
54
|
+
subject.query_compiler = 'Foo'
|
55
|
+
assert_equal 'Foo', subject.query_compiler
|
56
|
+
|
57
|
+
sub_class.query_compiler = 'Bar'
|
58
|
+
assert_equal 'Bar', sub_class.query_compiler
|
59
|
+
assert_equal 'Foo', subject.query_compiler
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end # Including QueryBuilder
|
63
|
+
|
64
|
+
|
65
|
+
def yt_parse(key, source, opts)
|
66
|
+
opts = {:rubyless_helper => self}.merge(Hash[*(opts.map{|k,v| [k.to_sym, v]}.flatten)])
|
67
|
+
|
68
|
+
case key
|
69
|
+
when 'res'
|
70
|
+
|
71
|
+
begin
|
72
|
+
query = DummyProcessor.new(source, opts).query
|
73
|
+
(query.main_class != DummyClass ? "#{query.main_class}: " : '') + query.to_s
|
74
|
+
rescue QueryBuilder::Error => err
|
75
|
+
err.message
|
76
|
+
end
|
77
|
+
when 'sxp'
|
78
|
+
# s-expression
|
79
|
+
QueryBuilder::Parser.parse(source).inspect
|
80
|
+
when 'sql'
|
81
|
+
DummyProcessor.new(source, opts).query.sql(binding)
|
82
|
+
when 'count'
|
83
|
+
DummyProcessor.new(source, opts).query.to_s(:count)
|
84
|
+
when 'count_sql'
|
85
|
+
DummyProcessor.new(source, opts).query.sql(binding, :count)
|
86
|
+
else
|
87
|
+
"parse not implemented for '#{key}' in querybuilder_test.rb"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
=begin
|
91
|
+
def test_benchmark
|
92
|
+
Benchmark.bmbm do |x|
|
93
|
+
['basic', 'errors', 'filters'].each do |file_name|
|
94
|
+
x.report("#{file_name}:") do
|
95
|
+
@@test_strings[file_name].each do |name, keys|
|
96
|
+
src = keys['src'] || name.gsub('_', ' ')
|
97
|
+
100.times do
|
98
|
+
begin
|
99
|
+
QueryBuilder::Parser.parse(src)
|
100
|
+
rescue QueryBuilder::Error => err
|
101
|
+
#
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
=end
|
110
|
+
yt_make
|
111
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
$LOAD_PATH.unshift((Pathname(__FILE__).dirname + '..' + 'lib').expand_path)
|
1
3
|
require 'stringio'
|
2
4
|
require 'test/unit'
|
3
|
-
require File.dirname(__FILE__) + '/../lib/QueryBuilder'
|
4
|
-
require File.dirname(__FILE__) + '/mock/dummy_query'
|
5
|
-
require File.dirname(__FILE__) + '/mock/user_query'
|
6
5
|
require 'rubygems'
|
6
|
+
require 'querybuilder'
|
7
|
+
require 'shoulda'
|
7
8
|
require 'yamltest'
|
9
|
+
|
10
|
+
require 'mock/dummy_processor'
|
11
|
+
require 'mock/user_processor'
|
12
|
+
require 'mock/dummy'
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 7
|
8
|
+
- 0
|
9
|
+
version: 0.7.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Gaspard Bucher
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-27 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: rubyless
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
@@ -29,8 +29,34 @@ dependencies:
|
|
29
29
|
- 5
|
30
30
|
- 0
|
31
31
|
version: 0.5.0
|
32
|
-
type: :
|
32
|
+
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: shoulda
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: yamltest
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
- 5
|
56
|
+
- 0
|
57
|
+
version: 0.5.0
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id003
|
34
60
|
description: |-
|
35
61
|
QueryBuilder is an interpreter for the "pseudo sql" language. This language
|
36
62
|
can be used for two purposes:
|
@@ -50,24 +76,42 @@ files:
|
|
50
76
|
- Manifest.txt
|
51
77
|
- README.rdoc
|
52
78
|
- Rakefile
|
79
|
+
- lib/extconf.rb
|
53
80
|
- lib/query_builder.rb
|
81
|
+
- lib/query_builder/error.rb
|
82
|
+
- lib/query_builder/info.rb
|
83
|
+
- lib/query_builder/parser.rb
|
84
|
+
- lib/query_builder/processor.rb
|
85
|
+
- lib/query_builder/query.rb
|
54
86
|
- lib/querybuilder.rb
|
87
|
+
- lib/querybuilder_ext.c
|
88
|
+
- lib/querybuilder_ext.rl
|
89
|
+
- lib/querybuilder_rb.rb
|
90
|
+
- lib/querybuilder_rb.rl
|
91
|
+
- lib/querybuilder_syntax.rl
|
92
|
+
- old_QueryBuilder.rb
|
55
93
|
- querybuilder.gemspec
|
56
94
|
- script/console
|
57
95
|
- script/destroy
|
58
96
|
- script/generate
|
97
|
+
- tasks/build.rake
|
98
|
+
- test/dummy_test.rb
|
59
99
|
- test/mock/custom_queries/test.yml
|
60
|
-
- test/mock/
|
100
|
+
- test/mock/dummy.rb
|
101
|
+
- test/mock/dummy_processor.rb
|
61
102
|
- test/mock/queries/bar.yml
|
62
103
|
- test/mock/queries/foo.yml
|
63
|
-
- test/mock/
|
64
|
-
- test/
|
65
|
-
- test/
|
66
|
-
- test/
|
67
|
-
- test/
|
68
|
-
- test/
|
69
|
-
- test/
|
70
|
-
- test/
|
104
|
+
- test/mock/user_processor.rb
|
105
|
+
- test/query_test.rb
|
106
|
+
- test/querybuilder/basic.yml
|
107
|
+
- test/querybuilder/custom.yml
|
108
|
+
- test/querybuilder/errors.yml
|
109
|
+
- test/querybuilder/filters.yml
|
110
|
+
- test/querybuilder/group.yml
|
111
|
+
- test/querybuilder/joins.yml
|
112
|
+
- test/querybuilder/mixed.yml
|
113
|
+
- test/querybuilder/rubyless.yml
|
114
|
+
- test/querybuilder_test.rb
|
71
115
|
- test/test_helper.rb
|
72
116
|
has_rdoc: true
|
73
117
|
homepage: http://zenadmin.org/524
|
@@ -98,9 +142,12 @@ rubyforge_project:
|
|
98
142
|
rubygems_version: 1.3.6
|
99
143
|
signing_key:
|
100
144
|
specification_version: 3
|
101
|
-
summary: QueryBuilder is an interpreter for the "pseudo sql" language
|
145
|
+
summary: QueryBuilder is an interpreter for the "pseudo sql" language.
|
102
146
|
test_files:
|
103
|
-
- test/
|
104
|
-
- test/mock/
|
105
|
-
- test/
|
147
|
+
- test/dummy_test.rb
|
148
|
+
- test/mock/dummy.rb
|
149
|
+
- test/mock/dummy_processor.rb
|
150
|
+
- test/mock/user_processor.rb
|
151
|
+
- test/query_test.rb
|
152
|
+
- test/querybuilder_test.rb
|
106
153
|
- test/test_helper.rb
|