querybuilder 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,4 +1,15 @@
1
+ == 0.5.2 2009-04-03
2
+
3
+ * 1 minor enhancement:
4
+ * Added support for main_table option in custom queries
5
+ * More tests for custom queries
6
+
7
+ == 0.5.1 2009-03-03
8
+
9
+ * 1 minor enhancement:
10
+ * Added support for glob directories in load_custom_queries
11
+
1
12
  == 0.5.0 2009-01-23
2
13
 
3
14
  * 1 major enhancement:
4
- * Initial release (extraction from zena: http://zenadmin.org)
15
+ * Initial release (extraction from zena: http://zenadmin.org)
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- = querybuilder
1
+ = QueryBuilder
2
2
 
3
3
  * http://github.com/zena/querybuilder/tree/master
4
4
 
data/lib/QueryBuilder.rb CHANGED
@@ -10,7 +10,7 @@ Syntax of a query is "RELATION [where ...|] [in ...|from SUB_QUERY|]".
10
10
  =end
11
11
  class QueryBuilder
12
12
  attr_reader :tables, :where, :errors, :join_tables, :distinct, :final_parser, :page_size
13
- VERSION = '0.5.0'
13
+ VERSION = '0.5.2'
14
14
 
15
15
  @@main_table = {}
16
16
  @@main_class = {}
@@ -28,24 +28,30 @@ class QueryBuilder
28
28
  @@main_class[self] = main_class.to_s
29
29
  end
30
30
 
31
- # Load prepared SQL definitions from a directory.
31
+ # Load prepared SQL definitions from a set of directories. If the file does not contain "host" or "hosts" keys,
32
+ # the filename is used as host.
32
33
  #
33
34
  # ==== Parameters
34
35
  # query<String>:: Path to list of custom queries yaml files.
35
36
  #
36
37
  # ==== Examples
37
- # DummyQuery.load_custom_queries("/path/to/directory")
38
+ # DummyQuery.load_custom_queries("/path/to/some/*/directory")
38
39
  #
39
40
  # The format of a custom query definition is:
40
41
  #
41
- # DummyQuery: # QueryBuilder class
42
- # abc: # query's relation name
43
- # select: # selected fields
42
+ # hosts:
43
+ # - test.host
44
+ # DummyQuery: # QueryBuilder class
45
+ # abc: # query's relation name
46
+ # select: # selected fields
44
47
  # - 'a'
45
48
  # - '34 AS number'
46
49
  # - 'c'
47
- # tables: # tables used
50
+ # tables: # tables used
48
51
  # - 'test'
52
+ # join_tables: # joins
53
+ # test:
54
+ # - LEFT JOIN other ON other.test_id = test.id
49
55
  # where: # filters
50
56
  # - '1'
51
57
  # - '2'
@@ -54,21 +60,26 @@ class QueryBuilder
54
60
  #
55
61
  # Once loaded, this 'custom query' can be used in a query like:
56
62
  # "images from abc where a > 54"
57
- def load_custom_queries(dir)
63
+ def load_custom_queries(directories)
58
64
  klass = nil
59
- if File.directory?(dir)
60
- Dir.foreach(dir) do |file|
61
- next unless file =~ /(.+).yml$/
62
- custom_query_group = $1
63
- definitions = YAML::load(File.read(File.join(dir,file)))
64
- definitions.each do |klass,v|
65
- klass = Module.const_get(klass)
66
- raise ArgumentError.new("invalid class for CustomQueries (#{klass})") unless klass.ancestors.include?(QueryBuilder)
67
- @@custom_queries[klass] ||= {}
68
- @@custom_queries[klass][custom_query_group] ||= {}
69
- klass_queries = @@custom_queries[klass][custom_query_group]
70
- v.each do |k,v|
71
- klass_queries[k] = v
65
+ Dir.glob(directories).each do |dir|
66
+ if File.directory?(dir)
67
+ Dir.foreach(dir) do |file|
68
+ next unless file =~ /(.+).yml$/
69
+ custom_query_groups = $1
70
+ definitions = YAML::load(File.read(File.join(dir,file)))
71
+ custom_query_groups = [definitions.delete('groups') || definitions.delete('group') || custom_query_groups].flatten
72
+ definitions.each do |klass,v|
73
+ klass = Module.const_get(klass)
74
+ raise ArgumentError.new("invalid class for CustomQueries (#{klass})") unless klass.ancestors.include?(QueryBuilder)
75
+ @@custom_queries[klass] ||= {}
76
+ custom_query_groups.each do |custom_query_group|
77
+ @@custom_queries[klass][custom_query_group] ||= {}
78
+ klass_queries = @@custom_queries[klass][custom_query_group]
79
+ v.each do |k,v|
80
+ klass_queries[k] = v
81
+ end
82
+ end
72
83
  end
73
84
  end
74
85
  end
@@ -132,7 +143,7 @@ class QueryBuilder
132
143
  # => "[\"SELECT COUNT(*) FROM objects WHERE objects.project_id = ?\", project_id]"
133
144
  def to_s(type = :find)
134
145
  return nil if !valid?
135
- return "\"SELECT #{@main_table}.* FROM #{@main_table} WHERE 0\"" if @tables.empty? # all alternate queries invalid and 'ignore_warnings' set.
146
+ return "\"SELECT #{main_table}.* FROM #{main_table} WHERE 0\"" if @tables.empty? # all alternate queries invalid and 'ignore_warnings' set.
136
147
  statement, bind_values = build_statement(type)
137
148
  bind_values.empty? ? "\"#{statement}\"" : "[#{[["\"#{statement}\""] + bind_values].join(', ')}]"
138
149
  end
@@ -155,7 +166,7 @@ class QueryBuilder
155
166
  # => "SELECT COUNT(*) FROM objects WHERE objects.project_id = 12489"
156
167
  def sql(bindings, type = :find)
157
168
  return nil if !valid?
158
- return "SELECT #{@main_table}.* FROM #{@main_table} WHERE 0" if @tables.empty? # all alternate queries invalid and 'ignore_warnings' set.
169
+ return "SELECT #{main_table}.* FROM #{main_table} WHERE 0" if @tables.empty? # all alternate queries invalid and 'ignore_warnings' set.
159
170
  statement, bind_values = build_statement(type)
160
171
  connection = get_connection(bindings)
161
172
  statement.gsub('?') { eval_bound_value(bind_values.shift, connection, bindings) }
@@ -204,7 +215,7 @@ class QueryBuilder
204
215
  end
205
216
 
206
217
  def main_table
207
- @@main_table[self.class]
218
+ @main_table || @@main_table[self.class]
208
219
  end
209
220
 
210
221
  def parse_part(part, is_last)
@@ -584,12 +595,12 @@ class QueryBuilder
584
595
  def field_or_attr(fld, table_name = table, context = nil)
585
596
  if fld =~ /^\d+$/
586
597
  return fld
587
- elsif @select.join =~ / AS #{fld}/
588
- @select.each do |s|
589
- if s =~ /\A(.*) AS #{fld}\Z/
590
- return context == :filter ? "(#{$1})" : fld
591
- end
598
+ elsif !(list = @select.select {|e| e =~ /\A#{fld}\Z|AS #{fld}|\.#{fld}\Z/}).empty?
599
+ res = list.first
600
+ if res =~ /\A(.*) AS #{fld}\Z/
601
+ res = $1
592
602
  end
603
+ return context == :filter ? "(#{res})" : res
593
604
  elsif table_name
594
605
  map_field(fld, table_name, context)
595
606
  else
@@ -848,8 +859,6 @@ class QueryBuilder
848
859
 
849
860
  @errors = []
850
861
 
851
- @main_table ||= 'objects'
852
-
853
862
  @select = []
854
863
 
855
864
  @ignore_warnings = opts[:ignore_warnings]
@@ -55,12 +55,6 @@ recipients_or_objects:
55
55
  - "objects"
56
56
  res: "[\"SELECT objects.* FROM objects,links 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]"
57
57
 
58
- custom_query:
59
- context:
60
- custom_query_group: test
61
- src: "abc"
62
- res: "\"SELECT a,34 AS number,c FROM test WHERE 3 AND 2 AND 1 ORDER BY a\""
63
-
64
58
  count_sql:
65
59
  src: "objects in project"
66
60
  count: "[\"SELECT COUNT(*) FROM objects WHERE objects.project_id = ?\", project_id]"
@@ -24,7 +24,7 @@ custom_query_having:
24
24
  context:
25
25
  custom_query_group: test
26
26
  src: "abc where number > 12"
27
- res: "\"SELECT a,34 AS number,c FROM test WHERE (34) > 12 AND 3 AND 2 AND 1 ORDER BY a\""
27
+ res: "\"SELECT a,34 AS number,c FROM test WHERE (34) > 12 AND 3 AND 2 AND 1 ORDER BY a ASC\""
28
28
 
29
29
  equation_in_filter:
30
30
  src: "objects where event_at > REF_DATE + custom_a months"
@@ -1,14 +1,31 @@
1
1
  DummyQuery:
2
- # form_dates
3
2
  abc:
4
3
  select:
5
- - 'a'
6
- - '34 AS number'
7
- - 'c'
4
+ - a
5
+ - 34 AS number
6
+ - c
8
7
  tables:
9
- - 'test'
8
+ - test
10
9
  where:
11
10
  - '1'
12
11
  - '2'
13
12
  - '3'
14
- order: 'a'
13
+ order: a ASC
14
+
15
+ two_table:
16
+ select:
17
+ - x
18
+ - IF(table_one.y,table_one.y,table_two.z) AS y
19
+ - table_two.name
20
+ tables:
21
+ - table_one
22
+ - table_two
23
+
24
+ two_table_main:
25
+ main_table: foo
26
+ select:
27
+ - x
28
+ tables:
29
+ - table_one
30
+ - foo
31
+ - table_two
@@ -2,7 +2,7 @@ class DummyQuery < QueryBuilder
2
2
  set_main_table 'objects'
3
3
  set_main_class 'DummyQueryClass'
4
4
 
5
- load_custom_queries File.join(File.dirname(__FILE__), 'custom_queries')
5
+ load_custom_queries File.join(File.dirname(__FILE__), '*')
6
6
 
7
7
  # Build joins and filters from a relation.
8
8
  def parse_relation(rel, context)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: querybuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gaspard Bucher
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-26 00:00:00 +01:00
12
+ date: 2009-04-03 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.2.3
33
+ version: 1.3.0
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: hoe