flash-gordons-ruby-plsql 0.5.0
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.
- checksums.yaml +15 -0
- data/Gemfile +14 -0
- data/History.txt +172 -0
- data/License.txt +20 -0
- data/README.md +182 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/plsql/connection.rb +233 -0
- data/lib/plsql/helpers.rb +9 -0
- data/lib/plsql/jdbc_connection.rb +542 -0
- data/lib/plsql/oci8_patches.rb +25 -0
- data/lib/plsql/oci_connection.rb +339 -0
- data/lib/plsql/package.rb +80 -0
- data/lib/plsql/procedure.rb +269 -0
- data/lib/plsql/procedure_call.rb +124 -0
- data/lib/plsql/schema.rb +309 -0
- data/lib/plsql/sequence.rb +49 -0
- data/lib/plsql/sql_statements.rb +87 -0
- data/lib/plsql/table.rb +348 -0
- data/lib/plsql/type.rb +275 -0
- data/lib/plsql/variable.rb +146 -0
- data/lib/plsql/version.rb +3 -0
- data/lib/plsql/view.rb +41 -0
- data/lib/ruby-plsql.rb +1 -0
- data/lib/ruby_plsql.rb +18 -0
- data/ruby-plsql.gemspec +87 -0
- data/spec/plsql/connection_spec.rb +495 -0
- data/spec/plsql/package_spec.rb +149 -0
- data/spec/plsql/procedure_spec.rb +2048 -0
- data/spec/plsql/schema_spec.rb +331 -0
- data/spec/plsql/sequence_spec.rb +67 -0
- data/spec/plsql/sql_statements_spec.rb +91 -0
- data/spec/plsql/table_spec.rb +371 -0
- data/spec/plsql/type_spec.rb +304 -0
- data/spec/plsql/variable_spec.rb +505 -0
- data/spec/plsql/version_spec.rb +8 -0
- data/spec/plsql/view_spec.rb +264 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +79 -0
- metadata +159 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
module PLSQL
|
2
|
+
class ProcedureCall < SubprogramCall #:nodoc:
|
3
|
+
attr_reader :output_stream
|
4
|
+
|
5
|
+
def initialize(procedure, args = [], options = {})
|
6
|
+
@output_stream = procedure.schema.dbms_output_stream
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def exec
|
11
|
+
# puts "DEBUG: sql = #{@sql.gsub("\n","<br/>\n")}"
|
12
|
+
@cursor = @schema.connection.parse(@sql)
|
13
|
+
|
14
|
+
@binds[:values].each do |arg, value|
|
15
|
+
@cursor.bind_param(":#{arg}", value, @binds[:metadata][arg])
|
16
|
+
end
|
17
|
+
|
18
|
+
@return[:variables].each do |var|
|
19
|
+
@cursor.bind_param(":#{var}", nil, @return[:metadata][var])
|
20
|
+
end
|
21
|
+
|
22
|
+
@cursor.exec
|
23
|
+
|
24
|
+
dbms_output_log
|
25
|
+
|
26
|
+
if block_given?
|
27
|
+
yield get_return_value
|
28
|
+
nil
|
29
|
+
else
|
30
|
+
get_return_value
|
31
|
+
end
|
32
|
+
ensure
|
33
|
+
@cursor.close if @cursor
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def construct_sql(arguments)
|
39
|
+
prepare_sql_construction
|
40
|
+
call_sql = ""
|
41
|
+
call_sql << add_return if return_metadata
|
42
|
+
|
43
|
+
# construct procedure call if procedure name is available
|
44
|
+
# otherwise will get surrounding call_sql from @procedure (used for table statements)
|
45
|
+
if subprogram_name
|
46
|
+
call_sql << "#{full_subprogram_name}(#{add_arguments(arguments)});\n"
|
47
|
+
else
|
48
|
+
call_sql << add_arguments(arguments)
|
49
|
+
call_sql = @subprogram.call_sql(call_sql)
|
50
|
+
end
|
51
|
+
|
52
|
+
add_out_variables
|
53
|
+
|
54
|
+
dbms_output_enable_sql, dbms_output_get_sql = dbms_output_sql
|
55
|
+
|
56
|
+
@sql = <<-SQL
|
57
|
+
DECLARE
|
58
|
+
#{@declare_sql}
|
59
|
+
BEGIN
|
60
|
+
#{@assignment_sql}
|
61
|
+
#{dbms_output_enable_sql}
|
62
|
+
#{call_sql}
|
63
|
+
#{dbms_output_get_sql}
|
64
|
+
#{@return[:sql]}
|
65
|
+
END;
|
66
|
+
SQL
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_return_value
|
70
|
+
# create output hash if there are any out variables
|
71
|
+
output = out_list.inject({}) {|res, k| res[k] = out_variable_value(k); res} if out_list.size > 0
|
72
|
+
# if function with output parameters
|
73
|
+
if return_metadata && out_list.size > 0
|
74
|
+
[function_return_value, output]
|
75
|
+
# if function without output parameters
|
76
|
+
elsif return_metadata
|
77
|
+
function_return_value
|
78
|
+
# if procedure with output parameters
|
79
|
+
elsif out_list.size > 0
|
80
|
+
output
|
81
|
+
end
|
82
|
+
# nil if procedure without output parameters
|
83
|
+
end
|
84
|
+
|
85
|
+
def dbms_output_sql
|
86
|
+
return ["", ""] unless output_stream
|
87
|
+
|
88
|
+
dbms_output_enable_sql = "DBMS_OUTPUT.ENABLE(#{@schema.dbms_output_buffer_size});\n"
|
89
|
+
# if database version is at least 10.2 then use DBMS_OUTPUT.GET_LINES with SYS.DBMSOUTPUT_LINESARRAY
|
90
|
+
if (@schema.connection.database_version <=> [10, 2, 0, 0]) >= 0
|
91
|
+
add_variable_declaration('dbms_output_numlines', 'integer', :value => Schema::DBMS_OUTPUT_MAX_LINES)
|
92
|
+
dbms_output_get_sql = "DBMS_OUTPUT.GET_LINES(:dbms_output_lines, l_dbms_output_numlines);\n"
|
93
|
+
bind_value(:dbms_output_lines, nil,
|
94
|
+
:data_type => 'TABLE', :data_length => nil,
|
95
|
+
:sql_type_name => "SYS.DBMSOUTPUT_LINESARRAY", :in_out => 'OUT')
|
96
|
+
# if database version is less than 10.2 then use individual DBMS_OUTPUT.GET_LINE calls
|
97
|
+
else
|
98
|
+
dbms_output_get_sql = ""
|
99
|
+
end
|
100
|
+
[dbms_output_enable_sql, dbms_output_get_sql]
|
101
|
+
end
|
102
|
+
|
103
|
+
def dbms_output_log
|
104
|
+
return unless output_stream
|
105
|
+
|
106
|
+
# if database version is at least 10.2 then :dbms_output_lines output bind variable has dbms_output lines
|
107
|
+
if @binds[:metadata][:dbms_output_lines]
|
108
|
+
@cursor[':dbms_output_lines'].each {|line| output_stream.puts("DBMS_OUTPUT: #{line}") if line}
|
109
|
+
# if database version is less than 10.2 then use individual DBMS_OUTPUT.GET_LINE calls
|
110
|
+
else
|
111
|
+
cursor = @schema.connection.parse("BEGIN sys.dbms_output.get_line(:line, :status); END;")
|
112
|
+
while true do
|
113
|
+
cursor.bind_param(':line', nil, :data_type => 'VARCHAR2', :in_out => 'OUT')
|
114
|
+
cursor.bind_param(':status', nil, :data_type => 'NUMBER', :in_out => 'OUT')
|
115
|
+
cursor.exec
|
116
|
+
break unless cursor[':status'] == 0
|
117
|
+
output_stream.puts "DBMS_OUTPUT: #{cursor[':line']}"
|
118
|
+
end
|
119
|
+
cursor.close
|
120
|
+
end
|
121
|
+
output_stream.flush
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/plsql/schema.rb
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
module PLSQL
|
2
|
+
class Schema
|
3
|
+
include SQLStatements
|
4
|
+
|
5
|
+
@@schemas = {}
|
6
|
+
|
7
|
+
class <<self
|
8
|
+
def find_or_new(connection_alias) #:nodoc:
|
9
|
+
connection_alias ||= :default
|
10
|
+
if @@schemas[connection_alias]
|
11
|
+
@@schemas[connection_alias]
|
12
|
+
else
|
13
|
+
@@schemas[connection_alias] = self.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(raw_conn = nil, schema = nil, original_schema = nil) #:nodoc:
|
20
|
+
self.connection = raw_conn
|
21
|
+
@schema_name = schema ? schema.to_s.upcase : nil
|
22
|
+
@original_schema = original_schema
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns connection wrapper object (this is not raw OCI8 or JDBC connection!)
|
26
|
+
attr_reader :connection
|
27
|
+
|
28
|
+
def root_schema #:nodoc:
|
29
|
+
@original_schema || self
|
30
|
+
end
|
31
|
+
|
32
|
+
def raw_connection=(raw_conn) #:nodoc:
|
33
|
+
@connection = raw_conn ? Connection.create(raw_conn) : nil
|
34
|
+
reset_instance_variables
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set connection to OCI8 or JDBC connection:
|
38
|
+
#
|
39
|
+
# plsql.connection = OCI8.new(database_user, database_password, database_name)
|
40
|
+
#
|
41
|
+
# or
|
42
|
+
#
|
43
|
+
# plsql.connection = java.sql.DriverManager.getConnection(
|
44
|
+
# "jdbc:oracle:thin:@#{database_host}:#{database_port}:#{database_name}",
|
45
|
+
# database_user, database_password)
|
46
|
+
#
|
47
|
+
def connection=(conn)
|
48
|
+
if conn.is_a?(Connection)
|
49
|
+
@connection = conn
|
50
|
+
reset_instance_variables
|
51
|
+
else
|
52
|
+
self.raw_connection = conn
|
53
|
+
end
|
54
|
+
conn
|
55
|
+
end
|
56
|
+
|
57
|
+
# Create new OCI8 or JDBC connection using one of the following ways:
|
58
|
+
#
|
59
|
+
# plsql.connect! username, password, database_tns_alias
|
60
|
+
# plsql.connect! username, password, :host => host, :port => port, :database => database
|
61
|
+
# plsql.connect! :username => username, :password => password, :database => database_tns_alias
|
62
|
+
# plsql.connect! :username => username, :password => password, :host => host, :port => port, :database => database
|
63
|
+
#
|
64
|
+
def connect!(*args)
|
65
|
+
params = {}
|
66
|
+
params[:username] = args.shift if args[0].is_a?(String)
|
67
|
+
params[:password] = args.shift if args[0].is_a?(String)
|
68
|
+
params[:database] = args.shift if args[0].is_a?(String)
|
69
|
+
params.merge!(args.shift) if args[0].is_a?(Hash)
|
70
|
+
raise ArgumentError, "Wrong number of arguments" unless args.empty?
|
71
|
+
self.connection = Connection.create_new(params)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Set connection to current ActiveRecord connection (use in initializer file):
|
75
|
+
#
|
76
|
+
# plsql.activerecord_class = ActiveRecord::Base
|
77
|
+
#
|
78
|
+
def activerecord_class=(ar_class)
|
79
|
+
@connection = ar_class ? Connection.create(nil, ar_class) : nil
|
80
|
+
reset_instance_variables
|
81
|
+
ar_class
|
82
|
+
end
|
83
|
+
|
84
|
+
# Disconnect from Oracle
|
85
|
+
def logoff
|
86
|
+
@connection.logoff
|
87
|
+
self.connection = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Current Oracle schema name
|
91
|
+
def schema_name
|
92
|
+
return nil unless connection
|
93
|
+
@schema_name ||= select_first("SELECT SYS_CONTEXT('userenv','session_user') FROM dual")[0]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Default timezone to which database values will be converted - :utc or :local
|
97
|
+
def default_timezone
|
98
|
+
if @original_schema
|
99
|
+
@original_schema.default_timezone
|
100
|
+
else
|
101
|
+
@default_timezone ||
|
102
|
+
# Use ActiveRecord class default_timezone when ActiveRecord connection is used
|
103
|
+
(@connection && (ar_class = @connection.activerecord_class) && ar_class.default_timezone) ||
|
104
|
+
# default to local timezone
|
105
|
+
:local
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Set default timezone to which database values will be converted - :utc or :local
|
110
|
+
def default_timezone=(value)
|
111
|
+
if [:local, :utc].include?(value)
|
112
|
+
@default_timezone = value
|
113
|
+
else
|
114
|
+
raise ArgumentError, "default timezone should be :local or :utc"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Same implementation as for ActiveRecord
|
119
|
+
# DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
|
120
|
+
def local_timezone_offset #:nodoc:
|
121
|
+
::Time.local(2007).utc_offset.to_r / 86400
|
122
|
+
end
|
123
|
+
|
124
|
+
# DBMS_OUTPUT buffer size (default is 20_000)
|
125
|
+
def dbms_output_buffer_size
|
126
|
+
if @original_schema
|
127
|
+
@original_schema.dbms_output_buffer_size
|
128
|
+
else
|
129
|
+
@dbms_output_buffer_size || 20_000
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Seet DBMS_OUTPUT buffer size (default is 20_000). Example:
|
134
|
+
#
|
135
|
+
# plsql.dbms_output_buffer_size = 100_000
|
136
|
+
#
|
137
|
+
def dbms_output_buffer_size=(value)
|
138
|
+
@dbms_output_buffer_size = value
|
139
|
+
end
|
140
|
+
|
141
|
+
# Maximum line numbers for DBMS_OUTPUT in one PL/SQL call (from DBMSOUTPUT_LINESARRAY type)
|
142
|
+
DBMS_OUTPUT_MAX_LINES = 2147483647
|
143
|
+
|
144
|
+
# Specify IO stream where to log DBMS_OUTPUT from PL/SQL procedures. Example:
|
145
|
+
#
|
146
|
+
# plsql.dbms_output_stream = STDOUT
|
147
|
+
#
|
148
|
+
def dbms_output_stream=(stream)
|
149
|
+
@dbms_output_stream = stream
|
150
|
+
if @dbms_output_stream.nil? && @connection
|
151
|
+
sys.dbms_output.disable
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# IO stream where to log DBMS_OUTPUT from PL/SQL procedures.
|
156
|
+
def dbms_output_stream
|
157
|
+
if @original_schema
|
158
|
+
@original_schema.dbms_output_stream
|
159
|
+
else
|
160
|
+
@dbms_output_stream
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def reset_instance_variables
|
167
|
+
if @connection
|
168
|
+
@schema_objects = {}
|
169
|
+
else
|
170
|
+
@schema_objects = nil
|
171
|
+
end
|
172
|
+
@schema_name = nil
|
173
|
+
@default_timezone = nil
|
174
|
+
end
|
175
|
+
|
176
|
+
def method_missing(method, *args, &block)
|
177
|
+
raise ArgumentError, "No database connection" unless connection
|
178
|
+
# search in database if not in cache at first
|
179
|
+
object = (@schema_objects[method] ||= find_database_object(method) || find_other_schema(method) ||
|
180
|
+
find_public_synonym(method) || find_standard_procedure(method))
|
181
|
+
|
182
|
+
raise ArgumentError, "No database object '#{method.to_s.upcase}' found" unless object
|
183
|
+
|
184
|
+
if object.is_a?(Procedure)
|
185
|
+
object.exec(*args, &block)
|
186
|
+
elsif object.is_a?(Type) && !args.empty?
|
187
|
+
object.new(*args, &block)
|
188
|
+
else
|
189
|
+
object
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def find_database_object(name, override_schema_name = nil)
|
194
|
+
object_schema_name = override_schema_name || schema_name
|
195
|
+
object_name = name.to_s.upcase
|
196
|
+
if (row = select_first(<<-SQL, object_schema_name, object_name))
|
197
|
+
SELECT o.object_type,
|
198
|
+
o.object_id,
|
199
|
+
o.status,
|
200
|
+
(CASE
|
201
|
+
WHEN o.object_type = 'PACKAGE' THEN
|
202
|
+
(SELECT ob.status
|
203
|
+
FROM all_objects ob
|
204
|
+
WHERE ob.owner = o.owner
|
205
|
+
AND ob.object_name = o.object_name
|
206
|
+
AND ob.object_type = 'PACKAGE BODY')
|
207
|
+
ELSE NULL
|
208
|
+
END) body_status,
|
209
|
+
(CASE
|
210
|
+
WHEN o.object_type = 'FUNCTION' THEN
|
211
|
+
(SELECT p.pipelined
|
212
|
+
FROM all_procedures p
|
213
|
+
WHERE p.owner = o.owner
|
214
|
+
AND p.object_name = o.object_name
|
215
|
+
AND p.object_type = 'FUNCTION')
|
216
|
+
ELSE NULL
|
217
|
+
END) pipelined
|
218
|
+
FROM all_objects o
|
219
|
+
WHERE owner = :owner
|
220
|
+
AND object_name = :object_name
|
221
|
+
AND object_type IN ('PROCEDURE','FUNCTION','PACKAGE','TABLE','VIEW','SEQUENCE','TYPE','SYNONYM')
|
222
|
+
SQL
|
223
|
+
|
224
|
+
object_type, object_id, status, body_status, pipelined = row
|
225
|
+
raise ArgumentError, "Database object '#{object_schema_name}.#{object_name}' is not in valid status\n#{
|
226
|
+
_errors(object_schema_name, object_name, object_type)}" if status == 'INVALID'
|
227
|
+
raise ArgumentError, "Package '#{object_schema_name}.#{object_name}' body is not in valid status\n#{
|
228
|
+
_errors(object_schema_name, object_name, 'PACKAGE BODY')}" if body_status == 'INVALID'
|
229
|
+
case object_type
|
230
|
+
when 'PROCEDURE'
|
231
|
+
Procedure.new(self, name, nil, override_schema_name, object_id)
|
232
|
+
when 'FUNCTION'
|
233
|
+
if pipelined == 'NO'
|
234
|
+
Procedure.new(self, name, nil, override_schema_name, object_id)
|
235
|
+
else
|
236
|
+
PipelinedFunction.new(self, name, nil, override_schema_name, object_id)
|
237
|
+
end
|
238
|
+
when 'PACKAGE'
|
239
|
+
Package.new(self, name, override_schema_name)
|
240
|
+
when 'TABLE'
|
241
|
+
Table.new(self, name, override_schema_name)
|
242
|
+
when 'VIEW'
|
243
|
+
View.new(self, name, override_schema_name)
|
244
|
+
when 'SEQUENCE'
|
245
|
+
Sequence.new(self, name, override_schema_name)
|
246
|
+
when 'TYPE'
|
247
|
+
Type.new(self, name, override_schema_name)
|
248
|
+
when 'SYNONYM'
|
249
|
+
target_schema_name, target_object_name = @connection.describe_synonym(object_schema_name, object_name)
|
250
|
+
find_database_object(target_object_name, target_schema_name)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def _errors(object_schema_name, object_name, object_type)
|
256
|
+
result = ""
|
257
|
+
previous_line = 0
|
258
|
+
select_all(
|
259
|
+
"SELECT e.line, e.position, e.text error_text, s.text source_text
|
260
|
+
FROM all_errors e, all_source s
|
261
|
+
WHERE e.owner = :owner AND e.name = :name AND e.type = :type
|
262
|
+
AND s.owner = e.owner AND s.name = e.name AND s.type = e.type AND s.line = e.line
|
263
|
+
ORDER BY e.sequence",
|
264
|
+
object_schema_name, object_name, object_type
|
265
|
+
).each do |line, position, error_text, source_text|
|
266
|
+
result << "Error on line #{'%4d' % line}: #{source_text}" if line > previous_line
|
267
|
+
result << " position #{'%4d' % position}: #{error_text}\n"
|
268
|
+
previous_line = line
|
269
|
+
end
|
270
|
+
result unless result.empty?
|
271
|
+
end
|
272
|
+
|
273
|
+
def find_other_schema(name)
|
274
|
+
return nil if @original_schema
|
275
|
+
if select_first("SELECT username FROM all_users WHERE username = :username", name.to_s.upcase)
|
276
|
+
Schema.new(connection, name, self)
|
277
|
+
else
|
278
|
+
nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def find_standard_procedure(name)
|
283
|
+
return nil if @original_schema
|
284
|
+
Procedure.find(self, name, 'STANDARD', 'SYS')
|
285
|
+
end
|
286
|
+
|
287
|
+
def find_public_synonym(name)
|
288
|
+
return nil if @original_schema
|
289
|
+
target_schema_name, target_object_name = @connection.describe_synonym('PUBLIC', name)
|
290
|
+
find_database_object(target_object_name, target_schema_name) if target_schema_name
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
module Kernel
|
297
|
+
# Returns current schema object. You can now chain either database object (packages, procedures, tables, sequences)
|
298
|
+
# in current schema or specify different schema name. Examples:
|
299
|
+
#
|
300
|
+
# plsql.test_function('some parameter')
|
301
|
+
# plsql.test_package.test_function('some parameter')
|
302
|
+
# plsql.other_schema.test_package.test_function('some parameter')
|
303
|
+
# plsql.table_name.all
|
304
|
+
# plsql.other_schema.table_name.all
|
305
|
+
#
|
306
|
+
def plsql(connection_alias = nil)
|
307
|
+
PLSQL::Schema.find_or_new(connection_alias)
|
308
|
+
end
|
309
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module PLSQL
|
2
|
+
|
3
|
+
module SequenceClassMethods #:nodoc:
|
4
|
+
def find(schema, sequence)
|
5
|
+
if schema.select_first(
|
6
|
+
"SELECT sequence_name FROM all_sequences
|
7
|
+
WHERE sequence_owner = :owner
|
8
|
+
AND sequence_name = :sequence_name",
|
9
|
+
schema.schema_name, sequence.to_s.upcase)
|
10
|
+
new(schema, sequence)
|
11
|
+
# search for synonym
|
12
|
+
elsif (row = schema.select_first(
|
13
|
+
"SELECT t.sequence_owner, t.sequence_name
|
14
|
+
FROM all_synonyms s, all_sequences t
|
15
|
+
WHERE s.owner IN (:owner, 'PUBLIC')
|
16
|
+
AND s.synonym_name = :synonym_name
|
17
|
+
AND t.sequence_owner = s.table_owner
|
18
|
+
AND t.sequence_name = s.table_name
|
19
|
+
ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0)",
|
20
|
+
schema.schema_name, sequence.to_s.upcase))
|
21
|
+
new(schema, row[1], row[0])
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Sequence
|
29
|
+
extend SequenceClassMethods
|
30
|
+
|
31
|
+
def initialize(schema, sequence, override_schema_name = nil) #:nodoc:
|
32
|
+
@schema = schema
|
33
|
+
@schema_name = override_schema_name || schema.schema_name
|
34
|
+
@sequence_name = sequence.to_s.upcase
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get NEXTVAL of sequence
|
38
|
+
def nextval
|
39
|
+
@schema.select_one "SELECT \"#{@schema_name}\".\"#{@sequence_name}\".NEXTVAL FROM dual"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get CURRVAL of sequence (can be called just after nextval)
|
43
|
+
def currval
|
44
|
+
@schema.select_one "SELECT \"#{@schema_name}\".\"#{@sequence_name}\".CURRVAL FROM dual"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|