querybuilder 0.7.0 → 0.8.0

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