sequel_oracle_extensions 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.2
1
+ 0.5.3
@@ -1,72 +1,72 @@
1
- require 'sequel'
2
- Sequel.require 'adapters/shared/oracle'
3
-
4
- # The hint extension adds support for Oracle hints
5
- module Sequel
6
-
7
- [Dataset, Oracle::DatasetMethods].each do |t|
8
- t.instance_eval do
9
- constants.grep(/_CLAUSE_METHODS$/).each do |k|
10
- type = k[0,k.length - 15].downcase
11
- meth = :"#{type}_hint_sql"
12
- const_set k, [meth].concat(remove_const(k)) unless const_get(k).include? meth
13
- end
1
+ require 'sequel'
2
+ Sequel.require 'adapters/shared/oracle'
3
+
4
+ # The hint extension adds support for Oracle hints
5
+ module Sequel
6
+
7
+ [Dataset, Oracle::DatasetMethods].each do |t|
8
+ t.instance_eval do
9
+ constants.grep(/_CLAUSE_METHODS$/).each do |k|
10
+ type = k[0,k.length - 15].downcase
11
+ meth = :"#{type}_hint_sql"
12
+ const_set k, [meth].concat(remove_const(k)) unless const_get(k).include? meth
13
+ end
14
14
  end
15
- end
16
-
17
- module Oracle
18
- module DatasetMethods
19
-
20
- def hint(*args) clone(:hints => _hints(*args){|v| v.dup}) end
21
- def hint!(*args) @opts[:hints] = _hints(*args){|v| v.dup}; self end
22
- def hints(*args) clone(:hints => _hints(*args){|v| []}) end
23
- def hints!(*args) @opts[:hints] = _hints(*args){|v| []}; self end
24
-
25
- def hint_sql(type, sql)
26
- if @opts.include? :hints and @opts[:hints].include? type and not @opts[:hints][type].empty?
27
- sql << " /*+ #{@opts[:hints][type].join ' '} */"
28
- end
29
- end
30
-
31
- %w(select insert update delete merge).map{|k| k.to_sym}.each do |k|
32
- define_method(:"#{k}_hint") {|*args| hint k, *args}
33
- define_method(:"#{k}_hint!") {|*args| hint! k, *args}
34
- define_method(:"#{k}_hints") {|*args| hints k, *args}
35
- define_method(:"#{k}_hints!") {|*args| hints! k, *args}
36
- define_method(:"#{k}_hint_sql") {|sql| hint_sql k, sql}
37
- end
38
-
39
- protected
40
-
41
- def _hints(*args, &block)
42
- type = args.shift if Symbol === args.first
43
- hints = hints_copy type, &block
44
- if type.nil?
45
- args.each do |arg|
46
- arg = { :select => arg } unless Hash === arg
47
- arg.each{|k,v| hint_list_add hints[k], v}
48
- end
49
- else
50
- hint_list_add hints[type], args
51
- end
52
- hints
53
- end
54
-
55
- private
56
-
57
- def hints_copy(type=nil)
58
- hints = Hash.new{|h,k| h[k] = []}
59
- @opts[:hints].each{|k,v| v = yield v if type.nil? or type==k; hints[k] = v} if @opts.include? :hints
60
- hints
61
- end
62
-
63
- def hint_list_add(list, hint)
64
- case hint
65
- when String; list.push hint
66
- when Array; list.concat hint
67
- else raise Error, "Invalid SQL hint value '#{hints.class.name}': must be an Array or String"
68
- end
69
- end
70
- end
71
- end
72
- end
15
+ end
16
+
17
+ module Oracle
18
+ module DatasetMethods
19
+
20
+ def hint(*args) clone(:hints => _hints(*args){|v| v.dup}) end
21
+ def hint!(*args) @opts[:hints] = _hints(*args){|v| v.dup}; self end
22
+ def hints(*args) clone(:hints => _hints(*args){|v| []}) end
23
+ def hints!(*args) @opts[:hints] = _hints(*args){|v| []}; self end
24
+
25
+ def hint_sql(type, sql)
26
+ if @opts.include? :hints and @opts[:hints].include? type and not @opts[:hints][type].empty?
27
+ sql << " /*+ #{@opts[:hints][type].join ' '} */"
28
+ end
29
+ end
30
+
31
+ %w(select insert update delete merge).map{|k| k.to_sym}.each do |k|
32
+ define_method(:"#{k}_hint") {|*args| hint k, *args}
33
+ define_method(:"#{k}_hint!") {|*args| hint! k, *args}
34
+ define_method(:"#{k}_hints") {|*args| hints k, *args}
35
+ define_method(:"#{k}_hints!") {|*args| hints! k, *args}
36
+ define_method(:"#{k}_hint_sql") {|sql| hint_sql k, sql}
37
+ end
38
+
39
+ protected
40
+
41
+ def _hints(*args, &block)
42
+ type = args.shift if Symbol === args.first
43
+ hints = hints_copy type, &block
44
+ if type.nil?
45
+ args.each do |arg|
46
+ arg = { :select => arg } unless Hash === arg
47
+ arg.each{|k,v| hint_list_add hints[k], v}
48
+ end
49
+ else
50
+ hint_list_add hints[type], args
51
+ end
52
+ hints
53
+ end
54
+
55
+ private
56
+
57
+ def hints_copy(type=nil)
58
+ hints = Hash.new{|h,k| h[k] = []}
59
+ @opts[:hints].each{|k,v| v = yield v if type.nil? or type==k; hints[k] = v} if @opts.include? :hints
60
+ hints
61
+ end
62
+
63
+ def hint_list_add(list, hint)
64
+ case hint
65
+ when String; list.push hint
66
+ when Array; list.concat hint
67
+ else raise Error, "Invalid SQL hint value '#{hints.class.name}': must be an Array or String"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,204 +1,204 @@
1
- require 'sequel'
2
-
3
- # The merge extension adds support for Oracle's MERGE statement.
4
- module Sequel
5
- class Dataset
6
- MERGE_CLAUSE_METHODS = clause_methods(:merge, %w'target source join update delete insert')
7
-
8
- def merge(&block)
9
- execute_dui merge_sql(&block)
10
- end
11
-
12
- def merge_using(*values, &block)
13
- execute_dui merge_using_sql(*values, &block)
14
- end
15
-
16
- def merge_into(*values, &block)
17
- execute_dui merge_into_sql(*values, &block)
18
- end
19
-
20
- def merge_sql(*values, &block)
21
- ms = clone
22
- ms.opts = { :into=>values.shift, :using=>values.shift, :on=>[values.shift].compact }
23
- [:update, :insert, :delete].each{|k| ms.opts[k] = values.shift }
24
- ms.opts.update :defaults=>@opts[:defaults], :overrides=>@opts[:overrides]
25
-
26
- if block_given?
27
- ms.extend(MergeBlockCopy)
28
- ms.instance_eval(&block)
29
- ms = ms.clone(ms.opts)
30
- end
31
-
32
- ms.opts[:into] ||= @opts[:from].first
33
- ms.opts[:on] << @opts[:where] if @opts[:where]
34
-
35
- ms.send :_merge_sql
36
- end
37
-
38
- def merge_using_sql(using, *values, &block)
39
- merge_sql @opts[:from].first, using, *values, &block
40
- end
41
-
42
- def merge_into_sql(into, on, *values, &block)
43
- merge_sql into, self, on, *values, &block
44
- end
45
-
46
- protected
47
-
48
- # SQL fragment specifying the target to merge INTO
49
- def merge_target_sql(sql)
50
- sql << " INTO #{table_ref(@opts[:into])}"
51
- end
52
-
53
- # SQL fragment specifying the source to merge USING
54
- def merge_source_sql(sql)
55
- sql << "\nUSING #{table_ref(@opts[:using])}"
56
- end
57
-
58
- # SQL fragment specifying what to perform the merge ON
59
- def merge_join_sql(sql)
60
- sql << "\nON #{literal(@opts[:on])}"
61
- end
62
-
63
- # SQL fragment specifying which target rows to DELETE
64
- def merge_delete_sql(sql)
65
- sql << "\nDELETE WHERE #{literal(@opts[:delete])}\n" if @opts[:delete]
66
- end
67
-
68
- # The SQL fragment specifying the columns and values to UPDATE
69
- def merge_update_sql(sql)
70
- return if not (values = @opts[:update]) or values.empty?
71
- values = Hash[values] if Array===values and values.all?{|v| Array===v && v.size==2}
72
- if Hash === values
73
- values = @opts[:defaults].merge(values) if @opts[:defaults]
74
- values = values.merge(@opts[:overrides]) if @opts[:overrides]
75
- # get values from hash
76
- values = values.map do |k, v|
77
- "#{k.is_a?(String) && !k.is_a?(LiteralString) ? quote_identifier(k) : literal(k)} = #{literal(v)}"
78
- end.join(COMMA_SEPARATOR)
79
- end
80
- sql << "\nWHEN MATCHED THEN\nUPDATE SET #{values}"
81
- end
82
-
83
- # The SQL fragment specifying the columns and values to INSERT
84
- def merge_insert_sql(sql)
85
- return if not @opts[:insert] or @opts[:insert].empty?
86
- columns, values = [], []
87
- @opts[:insert].each do |k,v|
88
- columns.push(k.is_a?(String) && !k.is_a?(LiteralString) ? quote_identifier(k) : literal(k))
89
- values.push(v.is_a?(String) && !v.is_a?(LiteralString) ? quote_identifier(v) : literal(v))
90
- end
91
- sql << "\nWHEN NOT MATCHED THEN\nINSERT (#{columns.join(COMMA_SEPARATOR)})"
92
- sql << "\nVALUES (#{values.join(COMMA_SEPARATOR)})"
93
- end
94
-
95
- # The order of methods to call on the MERGE SQL statement
96
- def merge_clause_methods
97
- MERGE_CLAUSE_METHODS
98
- end
99
-
100
- def _merge_sql
101
- _merge_alias_tables
102
- @opts[:on] = @opts[:on].inject(nil) do |a,b|
103
- b = _merge_expressions b
104
- b = filter_expr((Array===b && b.size==1) ? b.first : b)
105
- a ? SQL::BooleanExpression.new(:AND, a, b) : b
106
- end
107
- @opts[:insert] = @opts[:defaults].merge(@opts[:insert]) if @opts[:defaults]
108
- @opts[:insert] = @opts[:insert].merge(@opts[:overrides]) if @opts[:overrides]
109
- [:insert, :update, :delete].each do |k|
110
- @opts[k] = _merge_expressions @opts[k], k!=:delete || nil
111
- end
112
-
113
- clause_sql(:merge)
114
- end
115
-
116
- # Utility method to create and/or apply table aliaseses for expressions.
117
- def _merge_expressions(expr,apply_aliases=nil)
118
- if Symbol===expr
119
- expr = {expr => expr}
120
- elsif expr.is_a?(Array) and not expr.empty? and expr.all?{|x| x.is_a?(Symbol)}
121
- expr = expr.inject({}){|h,k| h[k]=k; h}
122
- elsif expr.nil? or LiteralString===expr
123
- return expr
124
- end
125
- apply_aliases = Sequel.condition_specifier?(expr) if apply_aliases.nil?
126
- apply_aliases ? _merge_column_pairs(expr) : expr
127
- end
128
-
129
- # Utility method to create any necessary table aliases.
130
- def _merge_alias_tables
131
- alias_num = @opts[:num_dataset_sources]||0
132
- [:into, :using].each do |k|
133
- if Symbol===@opts[k]
134
- u_table, u_column, u_alias = split_symbol(@opts[k])
135
- @opts[k] = "#{@opts[k]}___#{dataset_alias(alias_num += 1)}".to_sym unless u_alias
136
- else
137
- @opts[k] = @opts[k].as dataset_alias(alias_num += 1) unless @opts[k].respond_to? :aliaz
138
- end
139
- end
140
- end
141
-
142
- private
143
-
144
- # Utility method to qualify column pairs to the target and source table aliases.
145
- def _merge_table_aliases
146
- @opts.values_at(:into, :using).map{|t| Symbol===t ? split_symbol(t).last : t.aliaz.to_s}
147
- end
148
-
149
- # Utility method to qualify column pairs to the target and source table aliases.
150
- def _merge_column_pairs(pairs)
151
- t1, t2 = _merge_table_aliases
152
- merged = pairs.collect do |k, v|
153
- k = qualified_column_name(k, t1) if k.is_a?(Symbol)
154
- v = qualified_column_name(v, t2) if v.is_a?(Symbol)
155
- [k,v]
156
- end
157
- merged = Hash[*merged.flatten] if Hash === pairs
158
- merged
159
- end
160
-
161
- # Module used by Dataset#merge that has the effect of making all
162
- # dataset methods into !-style methods that modify the receiver.
163
- module MergeBlockCopy
164
- def each; raise Error, "each cannot be invoked inside a merge block." end
165
- def into(t) @opts[:into] = t end
166
- def using(t) @opts[:using] = t end
167
-
168
- %w'on update delete'.each do |m|
169
- module_eval <<-eodef
170
- def #{m}(*args, &block)
171
- @opts[:#{m}] = if block; then Sequel.virtual_row(&block)
172
- elsif Hash===args.first; then args.first
173
- else args
174
- end
175
- end
176
- eodef
177
- end
178
-
179
- def insert(*args, &block)
180
- args = [ args ] unless args.empty?
181
- args.push([Sequel.virtual_row(&block)]) if block
182
- @opts[:insert] = args.inject([]) do |r,a|
183
- if Hash === a.first
184
- raise Error, "Invalid insert arguments" unless a.size == 1
185
- r.concat a.first.to_a
186
- elsif a.size == 2
187
- raise Error, "Invalid insert arguments" unless a.all?{|v| Array===v && v.size==2}
188
- a.first.each_with_index{|k,i| r.push([k,a.last[i]]) }
189
- r
190
- else
191
- raise Error, "Invalid insert arguments"
192
- end
193
- end
194
- end
195
-
196
- # Merge the given options into the receiver's options and return the receiver
197
- # instead of cloning the receiver.
198
- def clone(opts = nil)
199
- @opts.merge!(opts)
200
- self
201
- end
202
- end
203
- end
204
- end
1
+ require 'sequel'
2
+
3
+ # The merge extension adds support for Oracle's MERGE statement.
4
+ module Sequel
5
+ class Dataset
6
+ MERGE_CLAUSE_METHODS = clause_methods(:merge, %w'target source join update delete insert')
7
+
8
+ def merge(&block)
9
+ execute_dui merge_sql(&block)
10
+ end
11
+
12
+ def merge_using(*values, &block)
13
+ execute_dui merge_using_sql(*values, &block)
14
+ end
15
+
16
+ def merge_into(*values, &block)
17
+ execute_dui merge_into_sql(*values, &block)
18
+ end
19
+
20
+ def merge_sql(*values, &block)
21
+ ms = clone
22
+ ms.opts = { :into=>values.shift, :using=>values.shift, :on=>[values.shift].compact }
23
+ [:update, :insert, :delete].each{|k| ms.opts[k] = values.shift }
24
+ ms.opts.update :defaults=>@opts[:defaults], :overrides=>@opts[:overrides]
25
+
26
+ if block_given?
27
+ ms.extend(MergeBlockCopy)
28
+ ms.instance_eval(&block)
29
+ ms = ms.clone(ms.opts)
30
+ end
31
+
32
+ ms.opts[:into] ||= @opts[:from].first
33
+ ms.opts[:on] << @opts[:where] if @opts[:where]
34
+
35
+ ms.send :_merge_sql
36
+ end
37
+
38
+ def merge_using_sql(using, *values, &block)
39
+ merge_sql @opts[:from].first, using, *values, &block
40
+ end
41
+
42
+ def merge_into_sql(into, on, *values, &block)
43
+ merge_sql into, self, on, *values, &block
44
+ end
45
+
46
+ protected
47
+
48
+ # SQL fragment specifying the target to merge INTO
49
+ def merge_target_sql(sql)
50
+ sql << " INTO #{table_ref(@opts[:into])}"
51
+ end
52
+
53
+ # SQL fragment specifying the source to merge USING
54
+ def merge_source_sql(sql)
55
+ sql << "\nUSING #{table_ref(@opts[:using])}"
56
+ end
57
+
58
+ # SQL fragment specifying what to perform the merge ON
59
+ def merge_join_sql(sql)
60
+ sql << "\nON #{literal(@opts[:on])}"
61
+ end
62
+
63
+ # SQL fragment specifying which target rows to DELETE
64
+ def merge_delete_sql(sql)
65
+ sql << "\nDELETE WHERE #{literal(@opts[:delete])}\n" if @opts[:delete]
66
+ end
67
+
68
+ # The SQL fragment specifying the columns and values to UPDATE
69
+ def merge_update_sql(sql)
70
+ return if not (values = @opts[:update]) or values.empty?
71
+ values = Hash[values] if Array===values and values.all?{|v| Array===v && v.size==2}
72
+ if Hash === values
73
+ values = @opts[:defaults].merge(values) if @opts[:defaults]
74
+ values = values.merge(@opts[:overrides]) if @opts[:overrides]
75
+ # get values from hash
76
+ values = values.map do |k, v|
77
+ "#{k.is_a?(String) && !k.is_a?(LiteralString) ? quote_identifier(k) : literal(k)} = #{literal(v)}"
78
+ end.join(COMMA_SEPARATOR)
79
+ end
80
+ sql << "\nWHEN MATCHED THEN\nUPDATE SET #{values}"
81
+ end
82
+
83
+ # The SQL fragment specifying the columns and values to INSERT
84
+ def merge_insert_sql(sql)
85
+ return if not @opts[:insert] or @opts[:insert].empty?
86
+ columns, values = [], []
87
+ @opts[:insert].each do |k,v|
88
+ columns.push(k.is_a?(String) && !k.is_a?(LiteralString) ? quote_identifier(k) : literal(k))
89
+ values.push(v.is_a?(String) && !v.is_a?(LiteralString) ? quote_identifier(v) : literal(v))
90
+ end
91
+ sql << "\nWHEN NOT MATCHED THEN\nINSERT (#{columns.join(COMMA_SEPARATOR)})"
92
+ sql << "\nVALUES (#{values.join(COMMA_SEPARATOR)})"
93
+ end
94
+
95
+ # The order of methods to call on the MERGE SQL statement
96
+ def merge_clause_methods
97
+ MERGE_CLAUSE_METHODS
98
+ end
99
+
100
+ def _merge_sql
101
+ _merge_alias_tables
102
+ @opts[:on] = @opts[:on].inject(nil) do |a,b|
103
+ b = _merge_expressions b
104
+ b = filter_expr((Array===b && b.size==1) ? b.first : b)
105
+ a ? SQL::BooleanExpression.new(:AND, a, b) : b
106
+ end
107
+ @opts[:insert] = @opts[:defaults].merge(@opts[:insert]) if @opts[:defaults]
108
+ @opts[:insert] = @opts[:insert].merge(@opts[:overrides]) if @opts[:overrides]
109
+ [:insert, :update, :delete].each do |k|
110
+ @opts[k] = _merge_expressions @opts[k], k!=:delete || nil
111
+ end
112
+
113
+ clause_sql(:merge)
114
+ end
115
+
116
+ # Utility method to create and/or apply table aliaseses for expressions.
117
+ def _merge_expressions(expr,apply_aliases=nil)
118
+ if Symbol===expr
119
+ expr = {expr => expr}
120
+ elsif expr.is_a?(Array) and not expr.empty? and expr.all?{|x| x.is_a?(Symbol)}
121
+ expr = expr.inject({}){|h,k| h[k]=k; h}
122
+ elsif expr.nil? or LiteralString===expr
123
+ return expr
124
+ end
125
+ apply_aliases = Sequel.condition_specifier?(expr) if apply_aliases.nil?
126
+ apply_aliases ? _merge_column_pairs(expr) : expr
127
+ end
128
+
129
+ # Utility method to create any necessary table aliases.
130
+ def _merge_alias_tables
131
+ alias_num = @opts[:num_dataset_sources]||0
132
+ [:into, :using].each do |k|
133
+ if Symbol===@opts[k]
134
+ u_table, u_column, u_alias = split_symbol(@opts[k])
135
+ @opts[k] = "#{@opts[k]}___#{dataset_alias(alias_num += 1)}".to_sym unless u_alias
136
+ else
137
+ @opts[k] = @opts[k].as dataset_alias(alias_num += 1) unless @opts[k].respond_to? :aliaz
138
+ end
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ # Utility method to qualify column pairs to the target and source table aliases.
145
+ def _merge_table_aliases
146
+ @opts.values_at(:into, :using).map{|t| Symbol===t ? split_symbol(t).last : t.aliaz.to_s}
147
+ end
148
+
149
+ # Utility method to qualify column pairs to the target and source table aliases.
150
+ def _merge_column_pairs(pairs)
151
+ t1, t2 = _merge_table_aliases
152
+ merged = pairs.collect do |k, v|
153
+ k = qualified_column_name(k, t1) if k.is_a?(Symbol)
154
+ v = qualified_column_name(v, t2) if v.is_a?(Symbol)
155
+ [k,v]
156
+ end
157
+ merged = Hash[*merged.flatten] if Hash === pairs
158
+ merged
159
+ end
160
+
161
+ # Module used by Dataset#merge that has the effect of making all
162
+ # dataset methods into !-style methods that modify the receiver.
163
+ module MergeBlockCopy
164
+ def each; raise Error, "each cannot be invoked inside a merge block." end
165
+ def into(t) @opts[:into] = t end
166
+ def using(t) @opts[:using] = t end
167
+
168
+ %w'on update delete'.each do |m|
169
+ module_eval <<-eodef
170
+ def #{m}(*args, &block)
171
+ @opts[:#{m}] = if block; then Sequel.virtual_row(&block)
172
+ elsif Hash===args.first; then args.first
173
+ else args
174
+ end
175
+ end
176
+ eodef
177
+ end
178
+
179
+ def insert(*args, &block)
180
+ args = [ args ] unless args.empty?
181
+ args.push([Sequel.virtual_row(&block)]) if block
182
+ @opts[:insert] = args.inject([]) do |r,a|
183
+ if Hash === a.first
184
+ raise Error, "Invalid insert arguments" unless a.size == 1
185
+ r.concat a.first.to_a
186
+ elsif a.size == 2
187
+ raise Error, "Invalid insert arguments" unless a.all?{|v| Array===v && v.size==2}
188
+ a.first.each_with_index{|k,i| r.push([k,a.last[i]]) }
189
+ r
190
+ else
191
+ raise Error, "Invalid insert arguments"
192
+ end
193
+ end
194
+ end
195
+
196
+ # Merge the given options into the receiver's options and return the receiver
197
+ # instead of cloning the receiver.
198
+ def clone(opts = nil)
199
+ @opts.merge!(opts)
200
+ self
201
+ end
202
+ end
203
+ end
204
+ end