flash-gordons-ruby-plsql 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|