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 +2 -3
- data/VERSION +1 -1
- data/lib/sequel/oracle_extensions/schemata.rb +398 -89
- data/sequel_oracle_extensions.gemspec +62 -56
- metadata +17 -13
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,
|
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.
|
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.
|
1
|
+
0.6.0
|
@@ -6,95 +6,343 @@ module Sequel
|
|
6
6
|
module Oracle
|
7
7
|
module DatabaseMethods
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
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(
|
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
|
-
:
|
23
|
-
|
24
|
-
from(:"
|
25
|
-
join(:"
|
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 => (
|
30
|
-
unless
|
31
|
-
pk = from(:
|
32
|
-
where(:c__index_name
|
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
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
57
|
-
|
58
|
-
#
|
59
|
-
#
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
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(
|
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(
|
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 =
|
364
|
+
ds = ds.limit(1) if constraint_type == 'P'
|
117
365
|
|
118
|
-
# Return the table constraints as
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
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
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = %q{sequel_oracle_extensions}
|
8
|
-
s.version = "0.
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = [
|
12
|
-
s.date = %q{2011-08-
|
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 = [
|
38
|
-
s.rubygems_version = %q{1.
|
39
|
-
s.summary = %q{Oracle MERGE, optimizer hints,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 7
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
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-
|
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:
|
29
|
+
hash: 99
|
29
30
|
segments:
|
30
31
|
- 3
|
31
|
-
-
|
32
|
+
- 25
|
32
33
|
- 0
|
33
|
-
version: 3.
|
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.
|
108
|
+
rubygems_version: 1.3.7
|
107
109
|
signing_key:
|
108
110
|
specification_version: 3
|
109
|
-
summary: Oracle MERGE, optimizer hints,
|
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
|