querybuilder 0.7.0 → 0.8.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.
@@ -87,6 +87,7 @@ module QueryBuilder
87
87
 
88
88
  action goto_expr_p {
89
89
  # remember current machine state 'cs'
90
+ par_count += 1
90
91
  last << [:par, cs]
91
92
  stack.push last.last
92
93
  last = last.last
@@ -96,6 +97,7 @@ module QueryBuilder
96
97
  action expr_close {
97
98
  pop_stack(stack, :par_close)
98
99
  # reset machine state 'cs'
100
+ par_count -= 1
99
101
  cs = stack.last.delete_at(1)
100
102
  # one more time to remove [:par...] line
101
103
  stack.pop
@@ -195,6 +197,7 @@ module QueryBuilder
195
197
  else
196
198
  data = "#{arg}\n"
197
199
  end
200
+ par_count = 0
198
201
  stack = [[:query]]
199
202
  last = stack.last
200
203
  str_buf = ""
@@ -206,7 +209,11 @@ module QueryBuilder
206
209
  if p < pe
207
210
  p = p - 3
208
211
  p = 0 if p < 0
209
- raise QueryBuilder::SyntaxError.new("Syntax error near #{data[p..-1].chomp.inspect}.")
212
+ raise QueryBuilder::SyntaxError.new("Syntax error near #{data[p..-2].inspect}.")
213
+ end
214
+
215
+ if par_count > 0
216
+ raise QueryBuilder::SyntaxError.new("Missing closing parenthesis in #{data[0..-2].inspect}.")
210
217
  end
211
218
  stack.first
212
219
  end
@@ -8,7 +8,7 @@
8
8
  # The where CLAUSE can contain the following operators
9
9
 
10
10
  ws = ' ' | '\t' | '\n';
11
- var = ws* ([a-zA-Z_]+) $str_a;
11
+ var = ws* ([a-zA-Z_:]+) $str_a;
12
12
  dquote = ([^"\\] | '\n') $str_a | ('\\' (any | '\n') $str_a);
13
13
  squote = ([^'\\] | '\n') $str_a | ('\\' (any | '\n') $str_a);
14
14
  string = ws* ("'" squote* "'" >string | '"' dquote* '"' >dstring);
File without changes
data/querybuilder.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{querybuilder}
8
- s.version = "0.7.0"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Gaspard Bucher"]
12
- s.date = %q{2010-05-27}
12
+ s.date = %q{2010-07-22}
13
13
  s.description = %q{QueryBuilder is an interpreter for the "pseudo sql" language. This language
14
14
  can be used for two purposes:
15
15
 
@@ -38,12 +38,13 @@ Gem::Specification.new do |s|
38
38
  "lib/querybuilder_rb.rb",
39
39
  "lib/querybuilder_rb.rl",
40
40
  "lib/querybuilder_syntax.rl",
41
+ "lib/tasks/build.rake",
41
42
  "old_QueryBuilder.rb",
42
43
  "querybuilder.gemspec",
43
44
  "script/console",
44
45
  "script/destroy",
45
46
  "script/generate",
46
- "tasks/build.rake",
47
+ "test/database.rb",
47
48
  "test/dummy_test.rb",
48
49
  "test/mock/custom_queries/test.yml",
49
50
  "test/mock/dummy.rb",
@@ -69,7 +70,8 @@ Gem::Specification.new do |s|
69
70
  s.rubygems_version = %q{1.3.6}
70
71
  s.summary = %q{QueryBuilder is an interpreter for the "pseudo sql" language.}
71
72
  s.test_files = [
72
- "test/dummy_test.rb",
73
+ "test/database.rb",
74
+ "test/dummy_test.rb",
73
75
  "test/mock/dummy.rb",
74
76
  "test/mock/dummy_processor.rb",
75
77
  "test/mock/user_processor.rb",
data/test/database.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'active_record'
2
+
3
+ begin
4
+ class QueryBuilderTestMigration < ActiveRecord::Migration
5
+ def self.down
6
+ end
7
+
8
+ def self.up
9
+ end
10
+ end
11
+
12
+ ActiveRecord::Base.establish_connection(:adapter=>'sqlite3', :database=>':memory:')
13
+ log_path = Pathname(__FILE__).dirname + '../log/test.log'
14
+ Dir.mkdir(log_path.dirname) unless File.exist?(log_path.dirname)
15
+ ActiveRecord::Base.logger = Logger.new(File.open(log_path, 'wb'))
16
+ ActiveRecord::Migration.verbose = false
17
+ #PropertyMigration.migrate(:down)
18
+ QueryBuilderTestMigration.migrate(:up)
19
+ ActiveRecord::Migration.verbose = true
20
+ end
@@ -32,11 +32,28 @@ class DummyProcessor < QueryBuilder::Processor
32
32
  "#{table}.#{fld_name}"
33
33
  elsif fld_name == 'REF_DATE'
34
34
  context[:ref_date] ? insert_bind(context[:ref_date]) : 'now()'
35
+ elsif fld_name == 'index'
36
+ add_table('index')
37
+ add_filter "#{table('index')}.node_id = #{field_or_attr('id', table(self.class.main_table))}"
38
+ "#{table('index')}.value"
35
39
  else
36
40
  super # raises an error
37
41
  end
38
42
  end
39
43
 
44
+ def resolve_missing_table(query, table_alias, table_name)
45
+ case table_name
46
+ when 'index'
47
+ query.where.insert 0, "#{table_alias}.id = 0"
48
+ when 'links'
49
+ query.where.insert 0, "#{table_alias}.id = 0"
50
+ else
51
+ # Raise an error
52
+ super
53
+ end
54
+ # do nothing
55
+ end
56
+
40
57
  # We do special things with 'class ='
41
58
  def process_equal(left, right)
42
59
  if left == [:field, 'class'] && right[0] == :string
@@ -70,11 +70,12 @@ paginate:
70
70
  recipients_or_objects:
71
71
  src: recipients or objects
72
72
  sxp: '[:query, [:clause_or, [:relation, "recipients"], [:relation, "objects"]]]'
73
- res: "[%Q{SELECT objects.* FROM links,objects WHERE ((objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?) OR objects.parent_id = ?) GROUP BY objects.id}, id, id]"
73
+ res: "[%Q{SELECT objects.* FROM links,objects WHERE ((objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?) OR (objects.parent_id = ? AND links.id = 0)) GROUP BY objects.id}, id, id]"
74
74
 
75
75
  recipients_or_objects_or_letters:
76
76
  src: recipients or objects or letters
77
- res: "[%Q{SELECT objects.* FROM links,objects WHERE ((objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?) OR objects.parent_id = ? OR (objects.kpath LIKE 'NNL%' AND objects.parent_id = ?)) GROUP BY objects.id}, id, id, id]"
77
+ res: "[%Q{SELECT objects.* FROM links,objects WHERE ((objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?) OR (links.id = 0 AND objects.parent_id = ?) OR (links.id = 0 AND objects.kpath LIKE 'NNL%' AND objects.parent_id = ?)) GROUP BY objects.id}, id, id, id]"
78
+ res: "[%Q{SELECT objects.* FROM links,objects WHERE ((objects.id = links.target_id AND links.relation_id = 4 AND links.source_id = ?) OR (objects.parent_id = ? AND links.id = 0) OR (objects.kpath LIKE 'NNL%' AND objects.parent_id = ? AND links.id = 0)) GROUP BY objects.id}, id, id, id]"
78
79
 
79
80
  or_clause_with_filter:
80
81
  src: "(recipients where name = 'foo') or objects"
@@ -88,4 +89,4 @@ after_process_callback:
88
89
  context:
89
90
  after_filter: '(1 = 1)'
90
91
  src: "objects where name like 'a%' or name like 'b%' in site"
91
- res: "%Q{SELECT objects.* FROM objects WHERE (1 = 1) AND (objects.name LIKE 'a%' OR objects.name LIKE 'b%')}"
92
+ res: "%Q{SELECT objects.* FROM objects WHERE (1 = 1) AND (objects.name LIKE 'a%' OR objects.name LIKE 'b%') GROUP BY id}"
@@ -30,3 +30,12 @@ or_clause_with_filter:
30
30
  src: "recipients where name = 'foo' or objects"
31
31
  sxp: '[:query, [:filter, [:relation, "recipients"], [:or, [:"=", [:field, "name"], [:string, "foo"]], [:field, "objects"]]]]'
32
32
  res: "Unknown field 'objects'."
33
+
34
+
35
+ unmatched_open_par:
36
+ src: "objects where event_at is null or (name is not null"
37
+ res: "Missing closing parenthesis in \"objects where event_at is null or (name is not null\"."
38
+
39
+ unmatched_close_par:
40
+ src: "objects where event_at is null )"
41
+ res: "Syntax error near \"ll )\"."
@@ -83,7 +83,15 @@ equation_with_date_interval:
83
83
  equation_and_or_par:
84
84
  src: "objects where event_at > '2006-04-01' or name like 'foo%'"
85
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]"
86
+ res: "[%Q{SELECT objects.* FROM objects WHERE (objects.event_at > '2006-04-01' OR objects.name LIKE 'foo%') AND objects.parent_id = ? GROUP BY id}, id]"
87
+
88
+ or_with_same_tables:
89
+ src: "objects where index = 5 or index = 7"
90
+ res: "[%Q{SELECT objects.* FROM index,objects WHERE ((index.value = 5 AND index.node_id = objects.id) OR (index.value = 7 AND index.node_id = objects.id)) AND objects.parent_id = ? GROUP BY objects.id}, id]"
91
+
92
+ or_with_missing_table:
93
+ src: "objects where index = 5 or 7"
94
+ res: "[%Q{SELECT objects.* FROM index,objects WHERE ((index.value = 5 AND index.node_id = objects.id) OR (7 AND index.id = 0)) AND objects.parent_id = ? GROUP BY objects.id}, id]"
87
95
 
88
96
  equation_par:
89
97
  src: "objects where (1 > 2 or 2 > 3) and 4 = 5 "
@@ -112,4 +120,4 @@ functions:
112
120
  filter_empty_literal:
113
121
  src: "objects where \"\" = ''"
114
122
  sxp: '[:query, [:filter, [:relation, "objects"], [:"=", [:dstring, ""], [:string, ""]]]]'
115
- sql: "SELECT objects.* FROM objects WHERE '' = '' AND objects.parent_id = 123"
123
+ sql: "SELECT objects.* FROM objects WHERE '' = '' AND objects.parent_id = 123"
@@ -26,6 +26,11 @@ tags:
26
26
  complex_from_with_scopes:
27
27
  src: "letters where name = 'foo' in project from letters in section"
28
28
  sxp: '[:query, [:from, [:scope, [:filter, [:relation, "letters"], [:"=", [:field, "name"], [:string, "foo"]]], "project"], [:scope, [:relation, "letters"], "section"]]]'
29
+
30
+ complex_from_with_scopes_and_typed_scope:
31
+ # instead of 'project', we give it a class with 'jobs:project'
32
+ src: "letters where name = 'foo' in jobs:project from letters in section"
33
+ sxp: '[:query, [:from, [:scope, [:filter, [:relation, "letters"], [:"=", [:field, "name"], [:string, "foo"]]], "jobs:project"], [:scope, [:relation, "letters"], "section"]]]'
29
34
 
30
35
  letters_in_project_from_letters:
31
36
  sxp: '[:query, [:from, [:scope, [:relation, "letters"], "project"], [:relation, "letters"]]]'
data/test/test_helper.rb CHANGED
@@ -3,6 +3,7 @@ $LOAD_PATH.unshift((Pathname(__FILE__).dirname + '..' + 'lib').expand_path)
3
3
  require 'stringio'
4
4
  require 'test/unit'
5
5
  require 'rubygems'
6
+ require 'database'
6
7
  require 'querybuilder'
7
8
  require 'shoulda'
8
9
  require 'yamltest'
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 7
7
+ - 8
8
8
  - 0
9
- version: 0.7.0
9
+ version: 0.8.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Gaspard Bucher
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-27 00:00:00 +02:00
17
+ date: 2010-07-22 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -89,12 +89,13 @@ files:
89
89
  - lib/querybuilder_rb.rb
90
90
  - lib/querybuilder_rb.rl
91
91
  - lib/querybuilder_syntax.rl
92
+ - lib/tasks/build.rake
92
93
  - old_QueryBuilder.rb
93
94
  - querybuilder.gemspec
94
95
  - script/console
95
96
  - script/destroy
96
97
  - script/generate
97
- - tasks/build.rake
98
+ - test/database.rb
98
99
  - test/dummy_test.rb
99
100
  - test/mock/custom_queries/test.yml
100
101
  - test/mock/dummy.rb
@@ -144,6 +145,7 @@ signing_key:
144
145
  specification_version: 3
145
146
  summary: QueryBuilder is an interpreter for the "pseudo sql" language.
146
147
  test_files:
148
+ - test/database.rb
147
149
  - test/dummy_test.rb
148
150
  - test/mock/dummy.rb
149
151
  - test/mock/dummy_processor.rb