sequel_oracle_extensions 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -5,14 +5,13 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "sequel_oracle_extensions"
8
- gem.summary = %Q{Oracle MERGE, optimizer hints, an schema extensions for Sequel}
8
+ gem.summary = %Q{Oracle MERGE, optimizer hints, and schema extensions for Sequel}
9
9
  gem.description = %Q{Oracle extensions for Sequel, including MERGE statements, optimizer hints, and schema extensions.}
10
10
  gem.email = "joe@ankhcraft.com"
11
11
  gem.homepage = "http://github.com/joekhoobyar/sequel_oracle_extensions"
12
12
  gem.authors = ["Joe Khoobyar"]
13
- gem.add_dependency "sequel", ">= 3.10.0"
13
+ gem.add_dependency "sequel", ">= 3.25.0"
14
14
  gem.add_development_dependency "rspec", ">= 2.0.0"
15
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
15
  end
17
16
  Jeweler::GemcutterTasks.new
18
17
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.5
1
+ 0.6.0
@@ -6,95 +6,343 @@ module Sequel
6
6
  module Oracle
7
7
  module DatabaseMethods
8
8
 
9
- # Returns the indexes for the given +table+ (or +schema.table+), as an array of hashes.
10
- # By default, it does not return primary keys.
11
- #
12
- # * <tt>:valid</tt> - Only look for indexes that are valid (true) or unusable (false). By default (nil),
13
- # looks for any matching index.
14
- # * <tt>:all</tt> - Returns all indexes, even ones used for primary keys.
15
- def indexes(qualified_table, options={})
9
+ # Specifies index attributes which are considered implicit and, thus, do not require DDL clauses.
10
+ IMPLICIT_INDEX_ATTRIBUTES = { :parallel=>false, :compress=>false, :logging=>true, :visible=>true }
11
+
12
+ # Returns a hash containing expanded table metadata that exposes Oracle-specific table attributes.
13
+ #
14
+ # Basic Attributes:
15
+ # :columns :: a columns subhash derived from a call to the #schema(table,options={}) method
16
+ # :schema_name :: the name of the schema that owns this table
17
+ #
18
+ # Extended Attributes: (NOTE: some of the following attributes may be nil with older OCI clients)
19
+ # :index_only :: is this an index-organized table?
20
+ # :clustered :: is this a clustered table?
21
+ # :partitioned :: is this a partitioned table?
22
+ # :temporary :: is this a global temporary table?
23
+ # :typed :: is this a ... typed table? ( not sure what that means :-/ )
24
+ #
25
+ def table_metadata(table,options={})
26
+ columns = schema table, options
27
+ attributes = columns.instance_eval{ remove_instance_variable :@features }
28
+ attributes[:columns] = Hash[ columns ]
29
+ attributes
30
+ end
31
+
32
+ # Return a hash containing index information for the table. Hash keys are index name symbols
33
+ # and values are subhashes. The superclass method specifies only two keys :columns and :unique.
34
+ # This implementation provides additional keys in the subhash that expose Oracle-specific index attributes.
35
+ #
36
+ # By default, this method does not return the primary key index.
37
+ # Options:
38
+ # :valid :: Filter by status: true => only VALID indexes, false => only UNUSABLE indexes
39
+ # :all :: Return all indexes, including the primary key index.
40
+ #
41
+ # Example(s):
42
+ #
43
+ # DB.indexes(:people)
44
+ # # { :person_gender=>{
45
+ # # :unique=>false,
46
+ # # :valid=>true,
47
+ # # :db_type=>'BITMAP',
48
+ # # :tablespace=>:users,
49
+ # # :partitioned=>false,
50
+ # # :visible=>true,
51
+ # # :compress=>false,
52
+ # # :columns=>[:gender]
53
+ # # },
54
+ # # :person_name=>{
55
+ # # :unique=>false,
56
+ # # :valid=>true,
57
+ # # :db_type=>'NORMAL',
58
+ # # :tablespace=>:users,
59
+ # # :partitioned=>false,
60
+ # # :visible=>true,
61
+ # # :compress=>false,
62
+ # # :columns=>[:last_name, :first_name]
63
+ # # } }
64
+ #
65
+ # # NOTE: Passing :all=>true so we can get the primary key index.
66
+ # DB.indexes(:employees, :all=>true)
67
+ # # { :employee_pk=>{
68
+ # # :unique=>true,
69
+ # # :valid=>true,
70
+ # # :db_type=>'NORMAL',
71
+ # # :tablespace=>:users,
72
+ # # :partitioned=>false,
73
+ # # :visible=>true,
74
+ # # :compress=>false,
75
+ # # :columns=>[:id]
76
+ # # },
77
+ # # :employee_dept=>{
78
+ # # :unique=>false,
79
+ # # :valid=>true,
80
+ # # :db_type=>'BITMAP',
81
+ # # :type=>:bitmap,
82
+ # # :join=>[:dept_id],
83
+ # # :tablespace=>:users,
84
+ # # :partitioned=>false,
85
+ # # :visible=>true,
86
+ # # :compress=>false,
87
+ # # :columns=>[:departments__id]
88
+ # # } }
89
+ def indexes(table, opts={})
16
90
  ds, result = metadata_dataset, []
17
91
  outm = lambda{|k| ds.send :output_identifier, k}
18
- schema, table = ds.schema_and_table(qualified_table).map{|k| k.to_s.send(ds.identifier_input_method) if k}
92
+ schema, table = ds.schema_and_table(table).map{|k| k.to_s.send(ds.identifier_input_method) if k}
93
+ who = schema.nil? ? 'user' : 'all'
19
94
 
20
95
  # Build the dataset and apply filters for introspection of indexes.
21
- ds = ds.select(:i__index_name, :i__index_type, :i__join_index, :i__partitioned,
22
- :i__status, :i__uniqueness, :i__visibility, :i__compression, :i__tablespace_name,
23
- :ic__column_name).
24
- from(:"all_indexes___i").
25
- join(:"all_ind_columns___ic", [ [:index_owner,:owner], [:index_name,:index_name] ]).
96
+ ds = ds.select(:i__index_name, :i__index_type, :i__join_index, :i__partitioned, :i__status,
97
+ :i__uniqueness, :i__visibility, :i__compression, :i__tablespace_name,
98
+ :i__logging, :i__degree, :i__instances, :ic__column_name).
99
+ from(:"#{who}_indexes___i").
100
+ join(:"#{who}_ind_columns___ic", [ [:index_name,:index_name] ]).
26
101
  where(:i__table_name=>table, :i__dropped=>'NO').
27
102
  order(:status.desc, :index_name, :ic__column_position)
28
- ds = ds.where :i__owner => schema unless schema.nil?
29
- ds = ds.where :i__status => (options[:valid] ? 'VALID' : 'UNUSABLE') unless options[:valid].nil?
30
- unless options[:all]
31
- pk = from(:all_constraints.as(:c)).where(:c__constraint_type=>'P').
32
- where(:c__index_name=>:i__index_name, :c__owner=>:i__owner)
103
+ ds = ds.where :i__owner => schema, :c__index_owner => schema unless schema.nil?
104
+ ds = ds.where :i__status => (opts[:valid] ? 'VALID' : 'UNUSABLE') unless opts[:valid].nil?
105
+ unless opts[:all]
106
+ pk = from(:"#{who}_constraints".as(:c)).where(:c__constraint_type=>'P').
107
+ where(:c__index_name => :i__index_name)
108
+ pk = pk.where :c__owner => schema unless schema.nil?
33
109
  ds = ds.where ~pk.exists
34
110
  end
35
111
 
36
- # Return the table constraints as an array of hashes, including a column list.
37
- hash = Hash.new do |h,k|
38
- result.push :index_name=>outm[k], :table_name=>outm[table], :columns=>[]
39
- h[k] = result.last
40
- end
41
- ds.each do |row|
42
- ref = hash[row[:index_name]]
43
- ref[:index_type] = row[:index_type]
44
- ref[:join_index] = row[:join_index]=='YES'
45
- ref[:partitioned] = row[:partitioned]=='YES'
46
- ref[:valid] = row[:status]=='VALID'
47
- ref[:uniqueness] = row[:uniqueness]=='UNIQUE'
48
- ref[:visible] = row[:visibility]=='VISIBLE'
49
- ref[:compression] = row[:compression]!='DISABLED'
50
- ref[:tablespace] = row[:tablespace_name]
51
- ref[:columns] << outm[row[:column_name]]
52
- end
53
- result
112
+ # Collect the indexes as a hash of subhashes, including a column list.
113
+ # As a followup, collect any additional metadata about the indexes (such as bitmap join columns).
114
+ hash, join_indexes = {}, []
115
+ p ds.sql
116
+ ds.each do |row|
117
+ key = :"#{outm[row[:index_name]]}"
118
+ unless subhash = hash[key]
119
+ subhash = hash[key] = {
120
+ :columns=>[], :unique=>(row[:uniqueness]=='UNIQUE'), :logging=>(row[:logging]=='YES'),
121
+ :db_type=>row[:index_type], :valid=>(row[:status]=='VALID'),
122
+ :parallel=>(row[:degree]!='1' || row[:instances]!='1'),
123
+ :tablespace=>:"#{outm[row[:tablespace_name]]}", :partitioned=>(row[:partitioned]=='YES'),
124
+ :visible=>(row[:visibility]=='VISIBLE'), :compress=>(row[:compression]!='DISABLED')
125
+ }
126
+ case subhash[:db_type]; when 'BITMAP','NORMAL'
127
+ subhash[:type] = :"#{subhash[:db_type].downcase}"
128
+ end
129
+ if row[:join_index]=='YES'
130
+ join_indexes << row[:index_name]
131
+ subhash[:join] = []
132
+ end
133
+ end
134
+ subhash[:columns] << :"#{outm[row[:column_name]]}"
135
+ end
136
+ ds = metadata_dataset.from(:"#{who}_join_ind_columns").where(:index_name=>join_indexes)
137
+ ds = ds.where :index_owner => schema unless schema.nil?
138
+ ds.each do |row|
139
+ subhash = hash[:"#{outm[row[:index_name]]}"]
140
+ ref_column = :"#{outm[row[:outer_table_column]]}"
141
+ pos = subhash[:columns].index ref_column
142
+ subhash[:columns][pos] = :"#{outm[row[:outer_table_name]]}__#{ref_column}"
143
+ subhash[:join][pos] = :"#{outm[row[:inner_table_column]]}"
144
+ end
145
+ hash
54
146
  end
55
147
 
56
- # Returns the primary key for the given +table+ (or +schema.table+), as a hash.
57
- #
58
- # * <tt>:enabled</tt> - Only look for keys that are enabled (true) or disabled (false). By default (nil),
59
- # looks for any matching key.
60
- # * <tt>:all</tt> - Return an array of matching keys, instead of the first matching key.
61
- #
62
- def primary_key(qualified_table, options={})
63
- result = table_constraints qualified_table, 'P', options
64
- options[:all] ? result : result.first
148
+ # Returns a hash containing primary key information for the table, or nil if the table has no primary key.
149
+ # Options:
150
+ # :enabled :: Filter by status: true => only ENABLED primary key, false => only DISABLED primary key
151
+ # :validated :: Filter by validation: true => only VALIDATED primary key, false => only NOT VALIDATED primary key
152
+ #
153
+ # Example:
154
+ #
155
+ # DB.primary_key(:people)
156
+ # # { :person_id=>{
157
+ # # :rely=>false,
158
+ # # :enabled=>true,
159
+ # # :validated=>true,
160
+ # # :using_index=>:person_pk,
161
+ # # :columns=>[:id]
162
+ # # } }
163
+ def primary_key(table, options={})
164
+ result = table_constraints table, 'P', options
165
+ return unless result and not result.empty?
166
+ result.values.first.tap{|pk| pk[:name] = result.keys.first }
65
167
  end
66
168
 
67
- # Returns unique constraints defined on the given +table+ (or +schema.table+), as an array of hashes.
68
- #
69
- # * <tt>:enabled</tt> - Only look for keys that are enabled (true) or disabled (false). By default (nil),
70
- # looks for all matching keys.
71
- def unique_keys(qualified_table, options={})
72
- table_constraints qualified_table, 'U', options
169
+ # Return a hash containing unique constraint information for the table. Hash keys are constraint name symbols
170
+ # and values are subhashes. Primary key constraints are _not_ returned by this method.
171
+ # Options:
172
+ # :enabled :: Filter by status: true => only ENABLED unique keys, false => only DISABLED unique keys
173
+ # :validated :: Filter by validation: true => only VALIDATED unique keys, false => only NOT VALIDATED unique keys
174
+ #
175
+ # Example:
176
+ #
177
+ # DB.unique_keys(:people)
178
+ # # { :person_ssn=>{
179
+ # # :rely=>false,
180
+ # # :enabled=>true,
181
+ # # :validated=>true,
182
+ # # :using_index=>:person_ssn_index,
183
+ # # :columns=>[:ssn]
184
+ # # },
185
+ # # :person_dlnum=>{
186
+ # # :rely=>true,
187
+ # # :enabled=>false,
188
+ # # :validated=>false,
189
+ # # :using_index=>nil,
190
+ # # :columns=>[:drivers_license_state, :drivers_license_number]
191
+ # # } }
192
+ def unique_keys(table, options={})
193
+ table_constraints table, 'U', options
73
194
  end
74
195
 
75
- # Returns foreign keys defined on the given +table+ (or +schema.table+), as an array of hashes.
76
- #
77
- # * <tt>:enabled</tt> - Only look for keys that are enabled (true) or disabled (false). By default (nil),
78
- # looks for all matching keys.
79
- def foreign_keys(qualified_table, options={})
80
- table_constraints qualified_table, 'R', options
196
+ # Return a hash containing foreign key information for the table. Hash keys are constraint name symbols
197
+ # and values are subhashes.
198
+ # Options:
199
+ # :enabled :: Filter by status: true => only ENABLED foreign keys, false => only DISABLED foreign keys
200
+ # :validated :: Filter by validation: true => only VALIDATED foreign keys, false => only NOT VALIDATED foreign keys
201
+ #
202
+ # Example:
203
+ #
204
+ # DB.foreign_keys(:employees)
205
+ # # { :employee_manager_fk=>{
206
+ # # :rely=>false,
207
+ # # :enabled=>true,
208
+ # # :validated=>true,
209
+ # # :columns=>[:manager_id],
210
+ # # :ref_constraint=>:manager_pk,
211
+ # # :ref_table=>:managers
212
+ # # },
213
+ # # :employee_department_fk=>{
214
+ # # :rely=>false,
215
+ # # :enabled=>true,
216
+ # # :validated=>true,
217
+ # # :columns=>[:department_id],
218
+ # # :ref_constraint=>:department_pk,
219
+ # # :ref_table=>:departments
220
+ # # } }
221
+ def foreign_keys(table, options={})
222
+ table_constraints table, 'R', options
81
223
  end
82
224
 
83
- # Returns foreign keys that refer to the given +table+ (or +schema.table+), as an array of hashes.
84
- #
85
- # * <tt>:enabled</tt> - Only look for keys that are enabled (true) or disabled (false). By default (nil),
86
- # looks for all matching keys.
87
- def references(qualified_table, options={})
88
- table_constraints qualified_table, 'R', options.merge(:table_name_column=>:t__table_name)
225
+ # Return a hash containing foreign key information for keys that _refer_ to this table. Hash keys are constraint name symbols
226
+ # and values are subhashes. Foreign keys for this table are _not_ returned by this method (unless they are self-referential).
227
+ # Options:
228
+ # :enabled :: Filter by status: true => only ENABLED foreign keys, false => only DISABLED foreign keys
229
+ # :validated :: Filter by validation: true => only VALIDATED foreign keys, false => only NOT VALIDATED foreign keys
230
+ #
231
+ # Example:
232
+ #
233
+ # DB.references(:employees)
234
+ # # { :assignment_employee_fk=>{
235
+ # # :rely=>false,
236
+ # # :enabled=>true,
237
+ # # :validated=>true,
238
+ # # :columns=>[:employee_id],
239
+ # # :ref_constraint=>:employee_pk,
240
+ # # :table=>:assignments
241
+ # # },
242
+ # # :bonus_recipient_fk=>{
243
+ # # :rely=>false,
244
+ # # :enabled=>true,
245
+ # # :validated=>true,
246
+ # # :columns=>[:recipient_id],
247
+ # # :ref_constraint=>:employee_pk,
248
+ # # :table=>:bonuses
249
+ # # } }
250
+ def references(table, options={})
251
+ table_constraints table, 'R', options.merge(:table_name_column=>:t__table_name)
252
+ end
253
+
254
+ private
255
+
256
+ # Overridden because Oracle has slightly different syntax.
257
+ def alter_table_sql(table, op)
258
+ alter_table_op = case op[:op]
259
+ when :add_column
260
+ "ADD #{column_definition_sql(op)}"
261
+ else
262
+ return super(table, op)
263
+ end
264
+ "ALTER TABLE #{quote_schema_table(table)} #{alter_table_op}"
265
+ end
266
+
267
+ # Overridden because Oracle has a 30 character maximum identifier length.
268
+ def default_index_name(table_name, columns)
269
+ schema, table = schema_and_table(table_name)
270
+ ds = DB[:all_indexes].where(:table_name=>table,:dropped=>'NO')
271
+ ds = ds.where :owner=>schema unless schema.nil?
272
+ "#{table[0,25]}_ix%2.2d" % [ds.count + 1]
273
+ end
274
+
275
+ # SQL DDL statement for creating an index for the table with the given name
276
+ # and index specifications.
277
+ def index_definition_sql(table_name, index)
278
+ raise Error, "Partial indexes are not supported for this database" if index[:where]
279
+
280
+ # Basic index creation DDL.
281
+ sql = ["CREATE"]
282
+ case index[:type]
283
+ when :bitmap
284
+ raise Error, "Bitmap indexes cannot be unique" if index[:unique]
285
+ sql << 'BITMAP'
286
+ when NilClass, :normal
287
+ sql << 'UNIQUE' if index[:unique]
288
+ else
289
+ raise Error, "Index type #{index[:type].inspect} is not supported for this database"
290
+ end
291
+ index_name = index[:name] || default_index_name(table_name, index[:columns])
292
+ qualified_table_name = quote_schema_table table_name
293
+ sql << "INDEX #{quote_identifier(index_name)} ON #{qualified_table_name}"
294
+
295
+ # Index columns and join indexes.
296
+ index_join, index_columns = *index.values_at(:join,:columns)
297
+ sql << literal(index_columns)
298
+ if index_join
299
+ raise Error, "Join clauses are only supported for bitmap indexes" if index[:type]!=:bitmap
300
+ sql << "FROM #{qualified_table_name},"
301
+ sql << index_columns.map{|k| quote_identifier schema_and_table(k).first }.uniq.join(', ')
302
+
303
+ # TODO: Document this short-hand syntax: {:columns=>[:ref_table__ref_column], :join=>[:fk_column]}
304
+ if Array===index_join and index_join.length==index_columns.length and index_join.all?{|k| Symbol===k}
305
+ index_join = Hash[ index_join.map{|k| :"#{table_name}__#{k}" }.zip(index_columns) ]
306
+ end
307
+
308
+ sql << "WHERE #{filter_expr(index_join)}"
309
+ end
310
+
311
+ # Index attributes and options.
312
+ sql << 'LOCAL' if index[:partitioned]
313
+ sql << flag_option_sql(index, :parallel)
314
+ sql << flag_option_sql(index, :logging)
315
+ sql << "TABLESPACE #{quote_identifier(index[:tablespace])}" if index[:tablespace]
316
+ sql << flag_option_sql(index, :visible, 'INVISIBLE')
317
+ sql << compress_option_sql(index)
318
+ sql << index[:options] if String === index[:options]
319
+ sql << 'UNUSABLE' if FalseClass === index[:valid]
320
+ sql.compact.join ' '
321
+ end
322
+
323
+ # SQL DDL clause for specifying on/off flags
324
+ def flag_option_sql(attrs, key, off="NO#{key}".upcase, on=key.to_s.upcase, implicit=IMPLICIT_INDEX_ATTRIBUTES[key])
325
+ case attrs[key]
326
+ when NilClass, implicit
327
+ when TrueClass then on
328
+ when FalseClass then off
329
+ else raise Error, "Unsupported or invalid #{key} option"
330
+ end
89
331
  end
90
332
 
91
- private
92
-
333
+ # SQL DDL clause for specifying compression in a table or index.
334
+ def compress_option_sql(attrs)
335
+ case value=attrs[:compress]
336
+ when Fixnum, Integer then "COMPRESS(#{value})"
337
+ else flag_option_sql attrs, :compress
338
+ end
339
+ end
340
+
93
341
  # Internal helper method for introspection of table constraints.
94
- def table_constraints(qualified_table, constraint_type, options={})
342
+ def table_constraints(table, constraint_type, options={})
95
343
  ds, result = metadata_dataset, []
96
344
  outm = lambda{|k| ds.send :output_identifier, k}
97
- schema, table = ds.schema_and_table(qualified_table).map{|k| k.to_s.send(ds.identifier_input_method) if k}
345
+ schema, table = ds.schema_and_table(table).map{|k| k.to_s.send(ds.identifier_input_method) if k}
98
346
  x_cons = schema.nil? ? 'user_cons' : 'all_cons'
99
347
 
100
348
  # Build the dataset and apply filters for introspection of constraints.
@@ -113,31 +361,92 @@ module Sequel
113
361
  else
114
362
  ds = ds.select_more(:c__index_name)
115
363
  end
116
- ds = yield ds, table if block_given?
364
+ ds = ds.limit(1) if constraint_type == 'P'
117
365
 
118
- # Return the table constraints as an array of hashes, including a column list.
119
- hash = Hash.new do |h,k|
120
- result.push :constraint_name=>outm[k], :constraint_type=>constraint_type, :columns=>[]
121
- h[k] = result.last
122
- end
123
- ds.each do |row|
124
- ref = hash[row[:constraint_name]]
125
- ref[:table_name] = outm[row[:table_name]]
126
- ref[:rely] = row[:rely]=='RELY'
127
- ref[:enabled] = row[:status]=='ENABLED'
128
- ref[:validated] = row[:validated]=='VALIDATED'
129
- ref[:columns] << outm[row[:column_name]]
130
-
131
- if row.include? :r_constraint_name
132
- ref[:r_constraint_name] = outm[row[:r_constraint_name]]
133
- ref[:r_table_name] = outm[row[:r_table_name]]
366
+ # Return the table constraints as a hash of subhashes, including a column list.
367
+ hash = {}
368
+ ds.each do |row|
369
+ key = :"#{outm[row[:constraint_name]]}"
370
+ unless subhash = hash[key]
371
+ subhash = hash[key] = {
372
+ :rely=>(row[:rely]=='RELY'), :enabled=>(row[:status]=='ENABLED'),
373
+ :validated=>(row[:validated]=='VALIDATED'), :columns=>[]
374
+ }
375
+ if row.include? :r_constraint_name
376
+ subhash[:ref_constraint] = :"#{outm[row[:r_constraint_name]]}"
377
+ if options[:table_name_column]==:t__table_name
378
+ then subhash[:table] = :"#{outm[row[:table_name]]}"
379
+ else subhash[:ref_table] = :"#{outm[row[:r_table_name]]}"
380
+ end
381
+ elsif row.include? :index_name
382
+ subhash[:using_index] = :"#{outm[row[:index_name]]}"
383
+ end
134
384
  end
135
- if row[:index_name]
136
- ref[:index_name] = outm[row[:index_name]]
137
- end
138
- end
139
- result
385
+ subhash[:columns] << :"#{outm[row[:column_name]]}"
386
+ end
387
+ hash
140
388
  end
389
+ end
390
+
391
+ # Methods that override existing functionality on Sequel::Oracle::Database.
392
+ module DatabaseExtensions
393
+
394
+ private
395
+
396
+ # Implemented in order to override existing functionality on Sequel::Oracle::Database.
397
+ def self.append_features(base)
398
+ instance_methods(false).each do |k|
399
+ base.send :remove_method, k if base.instance_method(k).owner == base
400
+ end
401
+ super
402
+ end
403
+
404
+ public
405
+
406
+ # Overridden to collect additional table-level information from the metadata.
407
+ #
408
+ # See Sequel::Oracle::Database#schema_parse_table for the original implementation.
409
+ def schema_parse_table(table, opts={})
410
+ ds = dataset
411
+ ds.identifier_output_method = :downcase
412
+ schema_and_table = "#{"#{quote_identifier(opts[:schema])}." if opts[:schema]}#{quote_identifier(table)}"
413
+ table_schema = []
414
+ metadata = transaction(opts){|conn| conn.describe_table(schema_and_table)}
415
+ metadata.columns.each do |column|
416
+ table_schema << [
417
+ column.name.downcase.to_sym,
418
+ {
419
+ :type => column.data_type,
420
+ :db_type => column.type_string.split(' ')[0],
421
+ :type_string => column.type_string,
422
+ :charset_form => column.charset_form,
423
+ :char_used => column.char_used?,
424
+ :char_size => column.char_size,
425
+ :data_size => column.data_size,
426
+ :precision => column.precision,
427
+ :scale => column.scale,
428
+ :fsprecision => column.fsprecision,
429
+ :lfprecision => column.lfprecision,
430
+ :allow_null => column.nullable?
431
+ }
432
+ ]
433
+ end
434
+ table_schema.instance_variable_set :@features, {
435
+ :owner => :"#{metadata.obj_schema.downcase}",
436
+ :clustered => (metadata.clustered? rescue nil),
437
+ :temporary => (metadata.is_temporary? rescue nil),
438
+ :partitioned => (metadata.is_temporary? rescue nil),
439
+ :typed => (metadata.is_typed? rescue nil),
440
+ :index_only => (metadata.index_only? rescue nil)
441
+ }
442
+ table_schema
443
+ end
141
444
  end
142
445
  end
143
446
  end
447
+
448
+ Sequel.require 'adapters/oracle' unless defined? ::Sequel::Oracle::Database
449
+ ::Sequel::Oracle::Database.class_eval do
450
+ #remove_method :schema_parse_table
451
+ include ::Sequel::Oracle::DatabaseExtensions
452
+ end
@@ -1,56 +1,62 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{sequel_oracle_extensions}
8
- s.version = "0.5.5"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = [%q{Joe Khoobyar}]
12
- s.date = %q{2011-08-19}
13
- s.description = %q{Oracle extensions for Sequel, including MERGE statements, optimizer hints, and schema extensions.}
14
- s.email = %q{joe@ankhcraft.com}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".rspec",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "lib/sequel/oracle_extensions.rb",
27
- "lib/sequel/oracle_extensions/hints.rb",
28
- "lib/sequel/oracle_extensions/merge.rb",
29
- "lib/sequel/oracle_extensions/schemata.rb",
30
- "lib/sequel_oracle_extensions.rb",
31
- "sequel_oracle_extensions.gemspec",
32
- "spec/sequel/oracle_extensions/hints_spec.rb",
33
- "spec/sequel/oracle_extensions/merge_spec.rb",
34
- "spec/spec_helper.rb"
35
- ]
36
- s.homepage = %q{http://github.com/joekhoobyar/sequel_oracle_extensions}
37
- s.require_paths = [%q{lib}]
38
- s.rubygems_version = %q{1.8.8}
39
- s.summary = %q{Oracle MERGE, optimizer hints, an schema extensions for Sequel}
40
-
41
- if s.respond_to? :specification_version then
42
- s.specification_version = 3
43
-
44
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
- s.add_runtime_dependency(%q<sequel>, [">= 3.10.0"])
46
- s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
47
- else
48
- s.add_dependency(%q<sequel>, [">= 3.10.0"])
49
- s.add_dependency(%q<rspec>, [">= 2.0.0"])
50
- end
51
- else
52
- s.add_dependency(%q<sequel>, [">= 3.10.0"])
53
- s.add_dependency(%q<rspec>, [">= 2.0.0"])
54
- end
55
- end
56
-
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{sequel_oracle_extensions}
8
+ s.version = "0.6.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Joe Khoobyar"]
12
+ s.date = %q{2011-08-24}
13
+ s.description = %q{Oracle extensions for Sequel, including MERGE statements, optimizer hints, and schema extensions.}
14
+ s.email = %q{joe@ankhcraft.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/sequel/oracle_extensions.rb",
27
+ "lib/sequel/oracle_extensions/hints.rb",
28
+ "lib/sequel/oracle_extensions/merge.rb",
29
+ "lib/sequel/oracle_extensions/schemata.rb",
30
+ "lib/sequel_oracle_extensions.rb",
31
+ "sequel_oracle_extensions.gemspec",
32
+ "spec/sequel/oracle_extensions/hints_spec.rb",
33
+ "spec/sequel/oracle_extensions/merge_spec.rb",
34
+ "spec/spec_helper.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/joekhoobyar/sequel_oracle_extensions}
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.7}
39
+ s.summary = %q{Oracle MERGE, optimizer hints, and schema extensions for Sequel}
40
+ s.test_files = [
41
+ "spec/sequel/oracle_extensions/hints_spec.rb",
42
+ "spec/sequel/oracle_extensions/merge_spec.rb",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
+ s.add_runtime_dependency(%q<sequel>, [">= 3.25.0"])
52
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
53
+ else
54
+ s.add_dependency(%q<sequel>, [">= 3.25.0"])
55
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<sequel>, [">= 3.25.0"])
59
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
60
+ end
61
+ end
62
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_oracle_extensions
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
- prerelease:
4
+ hash: 7
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 5
10
- version: 0.5.5
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joe Khoobyar
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-19 00:00:00 Z
18
+ date: 2011-08-24 00:00:00 -04:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: sequel
@@ -25,12 +26,12 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
28
- hash: 47
29
+ hash: 99
29
30
  segments:
30
31
  - 3
31
- - 10
32
+ - 25
32
33
  - 0
33
- version: 3.10.0
34
+ version: 3.25.0
34
35
  type: :runtime
35
36
  version_requirements: *id001
36
37
  - !ruby/object:Gem::Dependency
@@ -74,6 +75,7 @@ files:
74
75
  - spec/sequel/oracle_extensions/hints_spec.rb
75
76
  - spec/sequel/oracle_extensions/merge_spec.rb
76
77
  - spec/spec_helper.rb
78
+ has_rdoc: true
77
79
  homepage: http://github.com/joekhoobyar/sequel_oracle_extensions
78
80
  licenses: []
79
81
 
@@ -103,9 +105,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
105
  requirements: []
104
106
 
105
107
  rubyforge_project:
106
- rubygems_version: 1.8.8
108
+ rubygems_version: 1.3.7
107
109
  signing_key:
108
110
  specification_version: 3
109
- summary: Oracle MERGE, optimizer hints, an schema extensions for Sequel
110
- test_files: []
111
-
111
+ summary: Oracle MERGE, optimizer hints, and schema extensions for Sequel
112
+ test_files:
113
+ - spec/sequel/oracle_extensions/hints_spec.rb
114
+ - spec/sequel/oracle_extensions/merge_spec.rb
115
+ - spec/spec_helper.rb