sequel_oracle_extensions 0.5.2 → 0.5.3

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/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