ruby-plsql 0.4.0 → 0.4.1
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/History.txt +19 -0
- data/License.txt +1 -1
- data/README.rdoc +9 -4
- data/VERSION +1 -1
- data/lib/plsql/connection.rb +24 -9
- data/lib/plsql/helpers.rb +9 -0
- data/lib/plsql/jdbc_connection.rb +38 -9
- data/lib/plsql/oci8_patches.rb +25 -0
- data/lib/plsql/oci_connection.rb +46 -12
- data/lib/plsql/package.rb +25 -12
- data/lib/plsql/procedure.rb +23 -29
- data/lib/plsql/procedure_call.rb +53 -4
- data/lib/plsql/schema.rb +114 -45
- data/lib/plsql/sequence.rb +1 -1
- data/lib/plsql/sql_statements.rb +7 -2
- data/lib/plsql/table.rb +80 -25
- data/lib/plsql/type.rb +87 -0
- data/lib/plsql/variable.rb +146 -0
- data/lib/plsql/version.rb +1 -1
- data/lib/plsql/view.rb +41 -0
- data/lib/ruby_plsql.rb +1 -1
- data/spec/plsql/connection_spec.rb +112 -50
- data/spec/plsql/package_spec.rb +19 -10
- data/spec/plsql/procedure_spec.rb +159 -126
- data/spec/plsql/schema_spec.rb +109 -1
- data/spec/plsql/sql_statements_spec.rb +14 -32
- data/spec/plsql/table_spec.rb +75 -9
- data/spec/plsql/type_spec.rb +133 -0
- data/spec/plsql/variable_spec.rb +458 -0
- data/spec/plsql/version_spec.rb +8 -0
- data/spec/plsql/view_spec.rb +259 -0
- data/spec/spec_helper.rb +1 -1
- metadata +15 -2
data/lib/plsql/table.rb
CHANGED
@@ -12,12 +12,18 @@ module PLSQL
|
|
12
12
|
elsif (row = schema.select_first(
|
13
13
|
"SELECT t.owner, t.table_name
|
14
14
|
FROM all_synonyms s, all_tables t
|
15
|
-
WHERE s.owner
|
15
|
+
WHERE s.owner = :owner
|
16
16
|
AND s.synonym_name = :synonym_name
|
17
17
|
AND t.owner = s.table_owner
|
18
18
|
AND t.table_name = s.table_name
|
19
|
-
|
20
|
-
|
19
|
+
UNION ALL
|
20
|
+
SELECT t.owner, t.table_name
|
21
|
+
FROM all_synonyms s, all_tables t
|
22
|
+
WHERE s.owner = 'PUBLIC'
|
23
|
+
AND s.synonym_name = :synonym_name
|
24
|
+
AND t.owner = s.table_owner
|
25
|
+
AND t.table_name = s.table_name",
|
26
|
+
schema.schema_name, table.to_s.upcase, table.to_s.upcase))
|
21
27
|
new(schema, row[1], row[0])
|
22
28
|
else
|
23
29
|
nil
|
@@ -36,16 +42,17 @@ module PLSQL
|
|
36
42
|
@table_name = table.to_s.upcase
|
37
43
|
@columns = {}
|
38
44
|
|
39
|
-
@schema.
|
40
|
-
SELECT c.column_name, c.column_id position,
|
45
|
+
@schema.select_all(
|
46
|
+
"SELECT c.column_name, c.column_id position,
|
41
47
|
c.data_type, c.data_length, c.data_precision, c.data_scale, c.char_used,
|
42
|
-
c.data_type_owner, c.data_type_mod,
|
43
|
-
|
48
|
+
c.data_type_owner, c.data_type_mod,
|
49
|
+
CASE WHEN c.data_type_owner IS NULL THEN NULL
|
50
|
+
ELSE (SELECT t.typecode FROM all_types t
|
51
|
+
WHERE t.owner = c.data_type_owner
|
52
|
+
AND t.type_name = c.data_type) END typecode
|
53
|
+
FROM all_tab_columns c
|
44
54
|
WHERE c.owner = :owner
|
45
|
-
AND c.table_name = :table_name
|
46
|
-
AND t.owner(+) = c.data_type_owner
|
47
|
-
AND t.type_name(+) = c.data_type
|
48
|
-
ORDER BY c.column_id",
|
55
|
+
AND c.table_name = :table_name",
|
49
56
|
@schema_name, @table_name
|
50
57
|
) do |r|
|
51
58
|
column_name, position,
|
@@ -65,6 +72,11 @@ module PLSQL
|
|
65
72
|
end
|
66
73
|
end
|
67
74
|
|
75
|
+
# list of table column names
|
76
|
+
def column_names
|
77
|
+
@column_names ||= @columns.keys.sort_by{|k| columns[k][:position]}
|
78
|
+
end
|
79
|
+
|
68
80
|
# General select method with :first, :all or :count as first parameter.
|
69
81
|
# It is recommended to use #first, #all or #count method instead of this one.
|
70
82
|
def select(first_or_all, sql_params='', *bindvars)
|
@@ -87,6 +99,8 @@ module PLSQL
|
|
87
99
|
sql_params.each do |k,v|
|
88
100
|
if k == :order_by
|
89
101
|
order_by_sql = "ORDER BY #{v} "
|
102
|
+
elsif v.nil?
|
103
|
+
where_sqls << "#{k} IS NULL"
|
90
104
|
else
|
91
105
|
where_sqls << "#{k} = :#{k}"
|
92
106
|
bindvars << v
|
@@ -150,10 +164,44 @@ module PLSQL
|
|
150
164
|
return nil
|
151
165
|
end
|
152
166
|
|
153
|
-
|
167
|
+
table_proc = TableProcedure.new(@schema, self, :insert)
|
168
|
+
table_proc.add_insert_arguments(record)
|
169
|
+
|
170
|
+
call = ProcedureCall.new(table_proc, table_proc.argument_values)
|
154
171
|
call.exec
|
155
172
|
end
|
156
173
|
|
174
|
+
# Insert record or records in table using array of values. Examples:
|
175
|
+
#
|
176
|
+
# # with values for all columns
|
177
|
+
# plsql.employees.insert_values [1, 'First', 'Last', Time.local(2000,01,31)]
|
178
|
+
# # => INSERT INTO employees VALUES (1, 'First', 'Last', ...)
|
179
|
+
#
|
180
|
+
# # with values for specified columns
|
181
|
+
# plsql.employees.insert_values [:employee_id, :first_name, :last_name], [1, 'First', 'Last']
|
182
|
+
# # => INSERT INTO employees (employee_id, first_name, last_name) VALUES (1, 'First', 'Last')
|
183
|
+
#
|
184
|
+
# # with values for many records
|
185
|
+
# plsql.employees.insert_values [:employee_id, :first_name, :last_name], [1, 'First', 'Last'], [2, 'Second', 'Last']
|
186
|
+
# # => INSERT INTO employees (employee_id, first_name, last_name) VALUES (1, 'First', 'Last')
|
187
|
+
# # => INSERT INTO employees (employee_id, first_name, last_name) VALUES (2, 'Second', 'Last')
|
188
|
+
#
|
189
|
+
def insert_values(*args)
|
190
|
+
raise ArgumentError, "no arguments given" unless args.first
|
191
|
+
# if first argument is array of symbols then use it as list of fields
|
192
|
+
if args.first.all?{|a| a.instance_of?(Symbol)}
|
193
|
+
fields = args.shift
|
194
|
+
# otherwise use all columns as list of fields
|
195
|
+
else
|
196
|
+
fields = column_names
|
197
|
+
end
|
198
|
+
args.each do |record|
|
199
|
+
raise ArgumentError, "record should be Array of values" unless record.is_a?(Array)
|
200
|
+
raise ArgumentError, "wrong number of column values" unless record.size == fields.size
|
201
|
+
insert(ArrayHelpers::to_hash(fields, record))
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
157
205
|
# Update table records using optional conditions. Example:
|
158
206
|
#
|
159
207
|
# plsql.employees.update(:first_name => 'Second', :where => {:employee_id => 1})
|
@@ -194,12 +242,6 @@ module PLSQL
|
|
194
242
|
@schema.execute(delete_sql, *bindvars)
|
195
243
|
end
|
196
244
|
|
197
|
-
private
|
198
|
-
|
199
|
-
def get_typecode(owner, type_name)
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
245
|
# wrapper class to simulate Procedure class for ProcedureClass#exec
|
204
246
|
class TableProcedure #:nodoc:
|
205
247
|
attr_reader :arguments, :argument_list, :return, :out_list, :schema
|
@@ -214,11 +256,10 @@ module PLSQL
|
|
214
256
|
|
215
257
|
case @operation
|
216
258
|
when :insert
|
217
|
-
@argument_list = [[
|
218
|
-
@arguments = [{
|
219
|
-
|
220
|
-
|
221
|
-
}}]
|
259
|
+
@argument_list = [[]]
|
260
|
+
@arguments = [{}]
|
261
|
+
@insert_columns = []
|
262
|
+
@insert_values = []
|
222
263
|
when :update
|
223
264
|
@argument_list = [[]]
|
224
265
|
@arguments = [{}]
|
@@ -237,6 +278,15 @@ module PLSQL
|
|
237
278
|
nil
|
238
279
|
end
|
239
280
|
|
281
|
+
def add_insert_arguments(params)
|
282
|
+
params.each do |k,v|
|
283
|
+
raise ArgumentError, "Invalid column name #{k.inspect} specified as argument" unless (column_metadata = @table.columns[k])
|
284
|
+
@argument_list[0] << k
|
285
|
+
@arguments[0][k] = column_metadata
|
286
|
+
@insert_values << v
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
240
290
|
def add_set_arguments(params)
|
241
291
|
params.each do |k,v|
|
242
292
|
raise ArgumentError, "Invalid column name #{k.inspect} specified as argument" unless (column_metadata = @table.columns[k])
|
@@ -263,13 +313,18 @@ module PLSQL
|
|
263
313
|
end
|
264
314
|
|
265
315
|
def argument_values
|
266
|
-
|
316
|
+
case @operation
|
317
|
+
when :insert
|
318
|
+
@insert_values
|
319
|
+
when :update
|
320
|
+
@set_values + @where_values
|
321
|
+
end
|
267
322
|
end
|
268
323
|
|
269
324
|
def call_sql(params_string)
|
270
325
|
case @operation
|
271
326
|
when :insert
|
272
|
-
"INSERT INTO \"#{@table.schema_name}\".\"#{@table.table_name}\" VALUES #{params_string};\n"
|
327
|
+
"INSERT INTO \"#{@table.schema_name}\".\"#{@table.table_name}\"(#{@argument_list[0].map{|a| a.to_s}.join(', ')}) VALUES (#{params_string});\n"
|
273
328
|
when :update
|
274
329
|
update_sql = "UPDATE \"#{@table.schema_name}\".\"#{@table.table_name}\" SET #{@set_sqls.join(', ')}"
|
275
330
|
update_sql << " WHERE #{@where_sqls.join(' AND ')}" unless @where_sqls.empty?
|
data/lib/plsql/type.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module PLSQL
|
2
|
+
|
3
|
+
module TypeClassMethods #:nodoc:
|
4
|
+
def find(schema, type)
|
5
|
+
if schema.select_first(
|
6
|
+
"SELECT type_name FROM all_types
|
7
|
+
WHERE owner = :owner
|
8
|
+
AND type_name = :table_name",
|
9
|
+
schema.schema_name, type.to_s.upcase)
|
10
|
+
new(schema, type)
|
11
|
+
# search for synonym
|
12
|
+
elsif (row = schema.select_first(
|
13
|
+
"SELECT t.owner, t.type_name
|
14
|
+
FROM all_synonyms s, all_types t
|
15
|
+
WHERE s.owner = :owner
|
16
|
+
AND s.synonym_name = :synonym_name
|
17
|
+
AND t.owner = s.table_owner
|
18
|
+
AND t.type_name = s.table_name
|
19
|
+
UNION ALL
|
20
|
+
SELECT t.owner, t.type_name
|
21
|
+
FROM all_synonyms s, all_types t
|
22
|
+
WHERE s.owner = 'PUBLIC'
|
23
|
+
AND s.synonym_name = :synonym_name
|
24
|
+
AND t.owner = s.table_owner
|
25
|
+
AND t.type_name = s.table_name",
|
26
|
+
schema.schema_name, type.to_s.upcase, type.to_s.upcase))
|
27
|
+
new(schema, row[1], row[0])
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Type
|
35
|
+
extend TypeClassMethods
|
36
|
+
|
37
|
+
attr_reader :typecode, :attributes, :schema_name, :type_name #:nodoc:
|
38
|
+
|
39
|
+
def initialize(schema, type, override_schema_name = nil) #:nodoc:
|
40
|
+
@schema = schema
|
41
|
+
@schema_name = override_schema_name || schema.schema_name
|
42
|
+
@type_name = type.to_s.upcase
|
43
|
+
@attributes = {}
|
44
|
+
|
45
|
+
@typecode = @schema.select_first(
|
46
|
+
"SELECT typecode FROM all_types
|
47
|
+
WHERE owner = :owner
|
48
|
+
AND type_name = :type_name",
|
49
|
+
@schema_name, @type_name)[0]
|
50
|
+
|
51
|
+
@schema.select_all(
|
52
|
+
"SELECT attr_name, attr_no,
|
53
|
+
attr_type_name, length, precision, scale,
|
54
|
+
attr_type_owner, attr_type_mod,
|
55
|
+
(SELECT t.typecode FROM all_types t
|
56
|
+
WHERE t.owner = attr_type_owner
|
57
|
+
AND t.type_name = attr_type_name) typecode
|
58
|
+
FROM all_type_attrs
|
59
|
+
WHERE owner = :owner
|
60
|
+
AND type_name = :type_name
|
61
|
+
ORDER BY attr_no",
|
62
|
+
@schema_name, @type_name
|
63
|
+
) do |r|
|
64
|
+
attr_name, position,
|
65
|
+
data_type, data_length, data_precision, data_scale,
|
66
|
+
data_type_owner, data_type_mod, typecode = r
|
67
|
+
@attributes[attr_name.downcase.to_sym] = {
|
68
|
+
:position => position && position.to_i,
|
69
|
+
:data_type => data_type_owner && (typecode == 'COLLECTION' ? 'TABLE' : 'OBJECT' ) || data_type,
|
70
|
+
:data_length => data_type_owner ? nil : data_length && data_length.to_i,
|
71
|
+
:data_precision => data_precision && data_precision.to_i,
|
72
|
+
:data_scale => data_scale && data_scale.to_i,
|
73
|
+
:type_owner => data_type_owner,
|
74
|
+
:type_name => data_type_owner && data_type,
|
75
|
+
:sql_type_name => data_type_owner && "#{data_type_owner}.#{data_type}"
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# list of object type attribute names
|
81
|
+
def attribute_names
|
82
|
+
@attribute_names ||= @attributes.keys.sort_by{|k| @attributes[k][:position]}
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module PLSQL
|
2
|
+
|
3
|
+
module VariableClassMethods #:nodoc:
|
4
|
+
def find(schema, variable, package, override_schema_name = nil)
|
5
|
+
variable_upcase = variable.to_s.upcase
|
6
|
+
schema.select_all(
|
7
|
+
"SELECT text FROM all_source
|
8
|
+
WHERE owner = :owner
|
9
|
+
AND name = :object_name
|
10
|
+
AND type = 'PACKAGE'
|
11
|
+
AND UPPER(text) LIKE :variable_name",
|
12
|
+
override_schema_name || schema.schema_name, package, "%#{variable_upcase}%").each do |row|
|
13
|
+
if row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([0-9,]+\))?)\s*(NOT\s+NULL)?\s*((:=|DEFAULT).*)?;\s*(--.*)?$/i
|
14
|
+
return new(schema, variable, package, $2.strip, override_schema_name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Variable #:nodoc:
|
22
|
+
extend VariableClassMethods
|
23
|
+
|
24
|
+
attr_reader :schema_name, :package_name, :variable_name #:nodoc:
|
25
|
+
|
26
|
+
def initialize(schema, variable, package, variable_type, override_schema_name = nil)
|
27
|
+
@schema = schema
|
28
|
+
@schema_name = override_schema_name || schema.schema_name
|
29
|
+
@variable_name = variable.to_s.upcase
|
30
|
+
@package_name = package
|
31
|
+
@variable_type = variable_type.upcase
|
32
|
+
@metadata = metadata(@variable_type)
|
33
|
+
end
|
34
|
+
|
35
|
+
def value
|
36
|
+
@variable_get_proc ||= VariableProcedure.new(@schema, self, :get, @metadata)
|
37
|
+
ProcedureCall.new(@variable_get_proc).exec
|
38
|
+
end
|
39
|
+
|
40
|
+
def value=(new_value)
|
41
|
+
@variable_set_proc ||= VariableProcedure.new(@schema, self, :set, @metadata)
|
42
|
+
ProcedureCall.new(@variable_set_proc, [new_value]).exec
|
43
|
+
new_value
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def metadata(type_string)
|
49
|
+
case type_string
|
50
|
+
when /^(VARCHAR2|CHAR|NVARCHAR2|NCHAR)(\((\d+)\))?$/
|
51
|
+
{:data_type => $1, :data_length => $3.to_i, :in_out => 'IN/OUT'}
|
52
|
+
when /^(CLOB|NCLOB|BLOB)$/,
|
53
|
+
/^(NUMBER)(\(.*\))?$/, /^(PLS_INTEGER|BINARY_INTEGER)$/,
|
54
|
+
/^(DATE|TIMESTAMP|TIMESTAMP WITH TIME ZONE|TIMESTAMP WITH LOCAL TIME ZONE)$/
|
55
|
+
{:data_type => $1, :in_out => 'IN/OUT'}
|
56
|
+
when /^INTEGER$/
|
57
|
+
{:data_type => 'NUMBER', :in_out => 'IN/OUT'}
|
58
|
+
when /^BOOLEAN$/
|
59
|
+
{:data_type => 'PL/SQL BOOLEAN', :in_out => 'IN/OUT'}
|
60
|
+
when /^(\w+\.)?(\w+)\.(\w+)%TYPE$/
|
61
|
+
schema = $1 ? plsql.send($1.chop) : plsql
|
62
|
+
table = schema.send($2.downcase.to_sym)
|
63
|
+
column = table.columns[$3.downcase.to_sym]
|
64
|
+
{:data_type => column[:data_type], :data_length => column[:data_length], :sql_type_name => column[:sql_type_name], :in_out => 'IN/OUT'}
|
65
|
+
when /^(\w+\.)?(\w+)$/
|
66
|
+
schema = $1 ? plsql.send($1.chop) : plsql
|
67
|
+
begin
|
68
|
+
type = schema.send($2.downcase.to_sym)
|
69
|
+
raise ArgumentError unless type.is_a?(PLSQL::Type)
|
70
|
+
typecode = case type.typecode
|
71
|
+
when 'COLLECTION' then 'TABLE'
|
72
|
+
else 'OBJECT'
|
73
|
+
end
|
74
|
+
{:data_type => typecode, :data_length => nil, :sql_type_name => "#{type.schema_name}.#{type.type_name}", :in_out => 'IN/OUT'}
|
75
|
+
rescue ArgumentError
|
76
|
+
raise ArgumentError, "Package variable data type #{type_string} is not object type defined in schema"
|
77
|
+
end
|
78
|
+
when /^(\w+\.)?(\w+)%ROWTYPE$/
|
79
|
+
schema = $1 ? plsql.send($1.chop) : plsql
|
80
|
+
table = schema.send($2.downcase.to_sym)
|
81
|
+
record_metadata = {
|
82
|
+
:data_type => 'PL/SQL RECORD',
|
83
|
+
:in_out => 'IN/OUT',
|
84
|
+
:fields => {}
|
85
|
+
}
|
86
|
+
table.columns.each do |name, column|
|
87
|
+
record_metadata[:fields][name] =
|
88
|
+
{:data_type => column[:data_type], :data_length => column[:data_length], :sql_type_name => column[:sql_type_name],
|
89
|
+
:position => column[:position], :in_out => 'IN/OUT'}
|
90
|
+
end
|
91
|
+
record_metadata
|
92
|
+
else
|
93
|
+
raise ArgumentError, "Package variable data type #{type_string} is not supported"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# wrapper class to simulate Procedure class for ProcedureClass#exec
|
98
|
+
class VariableProcedure #:nodoc:
|
99
|
+
attr_reader :arguments, :argument_list, :return, :out_list, :schema
|
100
|
+
|
101
|
+
def initialize(schema, variable, operation, metadata)
|
102
|
+
@schema = schema
|
103
|
+
@variable = variable
|
104
|
+
@operation = operation
|
105
|
+
@metadata = metadata
|
106
|
+
|
107
|
+
@out_list = [[]]
|
108
|
+
|
109
|
+
case @operation
|
110
|
+
when :get
|
111
|
+
@argument_list = [[]]
|
112
|
+
@arguments = [{}]
|
113
|
+
@return = [@metadata]
|
114
|
+
when :set
|
115
|
+
@argument_list = [[:value]]
|
116
|
+
@arguments = [{:value => @metadata}]
|
117
|
+
@return = [nil]
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
def overloaded?
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
126
|
+
def procedure
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
def call_sql(params_string)
|
131
|
+
sql = (schema_name = @variable.schema_name) ? "#{schema_name}." : ""
|
132
|
+
sql << "#{@variable.package_name}.#{@variable.variable_name}"
|
133
|
+
case @operation
|
134
|
+
when :get
|
135
|
+
# params string contains assignment to return variable
|
136
|
+
"#{params_string} #{sql};\n"
|
137
|
+
when :set
|
138
|
+
"#{sql} := #{params_string};\n"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
data/lib/plsql/version.rb
CHANGED
data/lib/plsql/view.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module PLSQL
|
2
|
+
|
3
|
+
module ViewClassMethods #:nodoc:
|
4
|
+
def find(schema, view)
|
5
|
+
if schema.select_first(
|
6
|
+
"SELECT view_name FROM all_views
|
7
|
+
WHERE owner = :owner
|
8
|
+
AND view_name = :view_name",
|
9
|
+
schema.schema_name, view.to_s.upcase)
|
10
|
+
new(schema, view)
|
11
|
+
# search for synonym
|
12
|
+
elsif (row = schema.select_first(
|
13
|
+
"SELECT v.owner, v.view_name
|
14
|
+
FROM all_synonyms s, all_views v
|
15
|
+
WHERE s.owner = :owner
|
16
|
+
AND s.synonym_name = :synonym_name
|
17
|
+
AND v.owner = s.table_owner
|
18
|
+
AND v.view_name = s.table_name
|
19
|
+
UNION ALL
|
20
|
+
SELECT v.owner, v.view_name
|
21
|
+
FROM all_synonyms s, all_views v
|
22
|
+
WHERE s.owner = 'PUBLIC'
|
23
|
+
AND s.synonym_name = :synonym_name
|
24
|
+
AND v.owner = s.table_owner
|
25
|
+
AND v.view_name = s.table_name",
|
26
|
+
schema.schema_name, view.to_s.upcase, view.to_s.upcase))
|
27
|
+
new(schema, row[1], row[0])
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class View < Table
|
35
|
+
extend ViewClassMethods
|
36
|
+
|
37
|
+
alias :view_name :table_name #:nodoc:
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|