ruby-plsql 0.2.2 → 0.2.3

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 CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.2.3 2008-10-17
2
+ * Improvements
3
+ * Added CLOB data type support for input and output parameters and function return values
4
+ (both for MRI/OCI and JRuby/JDBC)
5
+ (ruby-oci8 version should be at least 1.0.3 as it contains CLOB handling bug fixes)
6
+ * Bug fixes
7
+ * Fixed calling of procedures without parameters
8
+
1
9
  == 0.2.2 2008-08-20
2
10
  * Bug fixes
3
11
  * Workaround for strange Oracle data dictionary bug when procedure with no parameters has row with empty fields in all_arguments
data/README.txt CHANGED
@@ -14,7 +14,7 @@ Look ar RSpec tests under spec directory for usage examples.
14
14
 
15
15
  == FEATURES/PROBLEMS:
16
16
 
17
- * Currently just NUMBER, VARCHAR2, DATE, TIMESTAMP argument types are supported for PL/SQL procedures
17
+ * Currently just NUMBER, VARCHAR2, DATE, TIMESTAMP, CLOB argument types are supported for PL/SQL procedures
18
18
 
19
19
  == SYNOPSIS:
20
20
 
@@ -37,7 +37,7 @@ plsql.logoff
37
37
  == REQUIREMENTS:
38
38
 
39
39
  MRI
40
- * Requires ruby-oci8 library to connect to Oracle
40
+ * Requires ruby-oci8 library to connect to Oracle (please use version 1.0.3 or later)
41
41
  JRuby
42
42
  * Requires Oracle JDBC driver (ojdbc14.jar should be somewhere in PATH) to connect to Oracle
43
43
 
@@ -63,426 +63,5 @@ module PLSQL
63
63
  end
64
64
 
65
65
  end
66
-
67
- class OCIConnection < Connection
68
-
69
- def logoff
70
- raw_connection.logoff
71
- end
72
-
73
- def commit
74
- raw_connection.commit
75
- end
76
-
77
- def rollback
78
- raw_connection.rollback
79
- end
80
-
81
- def autocommit?
82
- raw_connection.autocommit?
83
- end
84
-
85
- def autocommit=(value)
86
- raw_connection.autocommit = value
87
- end
88
-
89
- def select_first(sql, *bindvars)
90
- cursor = raw_connection.exec(sql, *bindvars)
91
- result = cursor.fetch
92
- if result
93
- result.map { |val| ora_value_to_ruby_value(val) }
94
- else
95
- nil
96
- end
97
- ensure
98
- cursor.close rescue nil
99
- end
100
-
101
- def select_all(sql, *bindvars, &block)
102
- cursor = raw_connection.exec(sql, *bindvars)
103
- results = []
104
- row_count = 0
105
- while row = cursor.fetch
106
- row_with_typecast = row.map {|val| ora_value_to_ruby_value(val) }
107
- if block_given?
108
- yield(row_with_typecast)
109
- row_count += 1
110
- else
111
- results << row_with_typecast
112
- end
113
- end
114
- block_given? ? row_count : results
115
- ensure
116
- cursor.close rescue nil
117
- end
118
-
119
- def exec(sql, *bindvars)
120
- raw_connection.exec(sql, *bindvars)
121
- end
122
-
123
- class Cursor
124
- attr_accessor :raw_cursor
125
-
126
- def initialize(raw_cur)
127
- @raw_cursor = raw_cur
128
- end
129
-
130
- def bind_param(key, value, type=nil, length=nil, in_out='IN')
131
- raw_cursor.bind_param(key, value, type, length)
132
- end
133
-
134
- def exec(*bindvars)
135
- raw_cursor.exec(*bindvars)
136
- end
137
-
138
- def [](key)
139
- raw_cursor[key]
140
- end
141
-
142
- def close
143
- raw_cursor.close
144
- end
145
- end
146
-
147
- def parse(sql)
148
- Cursor.new(raw_connection.parse(sql))
149
- end
150
-
151
-
152
- def plsql_to_ruby_data_type(data_type, data_length)
153
- case data_type
154
- when "VARCHAR2"
155
- [String, data_length || 4000]
156
- when "NUMBER"
157
- [OraNumber, nil]
158
- when "DATE"
159
- [DateTime, nil]
160
- when "TIMESTAMP"
161
- [Time, nil]
162
- # CLOB
163
- # BLOB
164
- else
165
- [String, 4000]
166
- end
167
- end
168
-
169
- def ruby_value_to_ora_value(val, type)
170
- if type == OraNumber
171
- val.nil? || val.is_a?(Fixnum) ? val : val.to_f
172
- elsif type == DateTime
173
- val ? val.to_datetime : nil
174
- else
175
- val
176
- end
177
- end
178
-
179
- def ora_value_to_ruby_value(val)
180
- case val
181
- when Float, OraNumber
182
- ora_number_to_ruby_number(val)
183
- when DateTime, OraDate
184
- ora_date_to_ruby_date(val)
185
- else
186
- val
187
- end
188
- end
189
-
190
-
191
- private
192
-
193
- def ora_number_to_ruby_number(num)
194
- num.to_i == num.to_f ? num.to_i : num.to_f
195
- end
196
-
197
- def ora_date_to_ruby_date(val)
198
- case val
199
- when DateTime
200
- Time.parse(val.strftime("%c")) rescue val
201
- when OraDate
202
- val.to_time rescue val.to_datetime
203
- else
204
- val
205
- end
206
- end
207
-
208
- end
209
-
210
-
211
-
212
- class JDBCConnection < Connection
213
- def logoff
214
- raw_connection.close
215
- true
216
- rescue
217
- false
218
- end
219
-
220
- def commit
221
- raw_connection.commit
222
- end
223
-
224
- def rollback
225
- raw_connection.rollback
226
- end
227
-
228
- def autocommit?
229
- raw_connection.getAutoCommit
230
- end
231
-
232
- def autocommit=(value)
233
- raw_connection.setAutoCommit(value)
234
- end
235
-
236
- def select_first(sql, *bindvars)
237
- stmt = prepare_statement(sql, *bindvars)
238
- rset = stmt.executeQuery
239
- metadata = rset.getMetaData
240
- column_count = metadata.getColumnCount
241
- if rset.next
242
- (1..column_count).map do |i|
243
- get_ruby_value_from_result_set(rset,i,metadata.getColumnTypeName(i))
244
- end
245
- else
246
- nil
247
- end
248
- ensure
249
- rset.close rescue nil
250
- stmt.close rescue nil
251
- end
252
-
253
- def select_all(sql, *bindvars, &block)
254
- stmt = prepare_statement(sql, *bindvars)
255
- results = []
256
- row_count = 0
257
- rset = stmt.executeQuery
258
- metadata = rset.getMetaData
259
- column_count = metadata.getColumnCount
260
- while rset.next
261
- row_with_typecast = (1..column_count).map do |i|
262
- get_ruby_value_from_result_set(rset,i,metadata.getColumnTypeName(i))
263
- end
264
- if block_given?
265
- yield(row_with_typecast)
266
- row_count += 1
267
- else
268
- results << row_with_typecast
269
- end
270
- end
271
- block_given? ? row_count : results
272
- ensure
273
- rset.close rescue nil
274
- stmt.close rescue nil
275
- end
276
-
277
- def exec(sql, *bindvars)
278
- cs = prepare_call(sql, *bindvars)
279
- cs.execute
280
- true
281
- ensure
282
- cs.close rescue nil
283
- end
284
-
285
- class Cursor
286
-
287
- def initialize(sql, conn)
288
- @sql = sql
289
- @connection = conn
290
- @params = sql.scan(/\:\w+/)
291
- @out_types = {}
292
- @out_index = {}
293
- @statement = @connection.prepare_call(sql)
294
- end
295
-
296
- def bind_param(key, value, type=nil, length=nil, in_out='IN')
297
- @connection.set_bind_variable(@statement, key, value, type, length)
298
- if in_out =~ /OUT/
299
- @out_types[key] = type || value.class
300
- @out_index[key] = bind_param_index(key)
301
- @statement.registerOutParameter(@out_index[key],@connection.get_java_sql_type(value,type))
302
- end
303
- end
304
-
305
- def exec
306
- @statement.execute
307
- end
308
-
309
- def [](key)
310
- @connection.get_bind_variable(@statement, @out_index[key], @out_types[key])
311
- end
312
-
313
- def close
314
- @statement.close
315
- end
316
-
317
- private
318
-
319
- def bind_param_index(key)
320
- return key if key.kind_of? Integer
321
- key = ":#{key.to_s}" unless key.to_s =~ /^:/
322
- @params.index(key)+1
323
- end
324
- end
325
-
326
- def parse(sql)
327
- Cursor.new(sql, self)
328
- end
329
-
330
- def prepare_statement(sql, *bindvars)
331
- stmt = raw_connection.prepareStatement(sql)
332
- bindvars.each_with_index do |bv, i|
333
- set_bind_variable(stmt, i+1, bv)
334
- end
335
- stmt
336
- end
337
-
338
- def prepare_call(sql, *bindvars)
339
- stmt = raw_connection.prepareCall(sql)
340
- bindvars.each_with_index do |bv, i|
341
- set_bind_variable(stmt, i+1, bv)
342
- end
343
- stmt
344
- end
345
-
346
- def get_java_sql_type(value, type)
347
- case type ? type.to_s : value.class.to_s
348
- when 'Fixnum', 'Bignum', 'Integer'
349
- java.sql.Types::INTEGER
350
- when 'Float'
351
- java.sql.Types::FLOAT
352
- when 'BigDecimal'
353
- java.sql.Types::NUMERIC
354
- when 'String'
355
- java.sql.Types::VARCHAR
356
- when 'Date'
357
- java.sql.Types::DATE
358
- when 'Time'
359
- java.sql.Types::DATE
360
- when 'DateTime'
361
- java.sql.Types::DATE
362
- else
363
- java.sql.Types::VARCHAR
364
- end
365
- end
366
-
367
- def set_bind_variable(stmt, i, value, type=nil, length=nil)
368
- key = i.kind_of?(Integer) ? nil : i.to_s.gsub(':','')
369
- case !value.nil? && type ? type.to_s : value.class.to_s
370
- when 'Fixnum', 'Bignum', 'Integer'
371
- stmt.send("setInt#{key && "AtName"}", key || i, value)
372
- when 'Float'
373
- stmt.send("setFloat#{key && "AtName"}", key || i, value)
374
- when 'BigDecimal'
375
- stmt.send("setBigDecimal#{key && "AtName"}", key || i, java.math.BigDecimal.new(value.to_s))
376
- when 'String'
377
- stmt.send("setString#{key && "AtName"}", key || i, value)
378
- when 'Date'
379
- stmt.send("setDate#{key && "AtName"}", key || i, java.sql.Date.new(Time.parse(value.to_s).to_i*1000))
380
- when 'Time'
381
- stmt.send("setTime#{key && "AtName"}", key || i, java.sql.Time.new(value.to_i*1000))
382
- when 'DateTime'
383
- stmt.send("setTime#{key && "AtName"}", key || i, java.sql.Time.new(Time.parse(value.strftime("%c")).to_i*1000))
384
- when 'NilClass'
385
- stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type))
386
- end
387
- end
388
-
389
- def get_bind_variable(stmt, i, type)
390
- case type.to_s
391
- when 'Fixnum', 'Bignum', 'Integer'
392
- stmt.getInt(i)
393
- when 'Float'
394
- stmt.getFloat(i)
395
- when 'BigDecimal'
396
- bd = stmt.getBigDecimal(i)
397
- bd && BigDecimal.new(bd.to_s)
398
- when 'String'
399
- stmt.getString(i)
400
- when 'Date','Time','DateTime'
401
- ts = stmt.getTimestamp(i)
402
- # ts && Time.parse(Time.at(ts.getTime/1000).iso8601)
403
- ts && Time.local(1900+ts.year, ts.month+1, ts.date, ts.hours, ts.minutes, ts.seconds)
404
- end
405
- end
406
-
407
- def get_ruby_value_from_result_set(rset, i, type_name)
408
- case type_name
409
- when "CHAR", "VARCHAR2"
410
- rset.getString(i)
411
- when "NUMBER"
412
- d = rset.getBigDecimal(i)
413
- if d.nil?
414
- nil
415
- elsif d.scale == 0
416
- d.longValue
417
- else
418
- d.doubleValue
419
- end
420
- when "DATE", "TIMESTAMP"
421
- Time.at(rset.getTimestamp(i).getTime/1000)
422
- else
423
- nil
424
- end
425
- end
426
-
427
- def plsql_to_ruby_data_type(data_type, data_length)
428
- case data_type
429
- when "VARCHAR2"
430
- [String, data_length || 4000]
431
- when "NUMBER"
432
- [BigDecimal, nil]
433
- when "DATE"
434
- [Time, nil]
435
- when "TIMESTAMP"
436
- [Time, nil]
437
- # CLOB
438
- # BLOB
439
- else
440
- [String, 4000]
441
- end
442
- end
443
-
444
- def ruby_value_to_ora_value(val, type)
445
- if type == BigDecimal
446
- val.nil? || val.is_a?(Fixnum) ? val : val.to_f
447
- elsif type == Time
448
- date_to_time(val)
449
- else
450
- val
451
- end
452
- end
453
-
454
- def ora_value_to_ruby_value(val)
455
- case val
456
- when Float, BigDecimal
457
- ora_number_to_ruby_number(val)
458
- # when OraDate
459
- # ora_date_to_ruby_date(val)
460
- else
461
- val
462
- end
463
- end
464
-
465
- private
466
-
467
- def ora_number_to_ruby_number(num)
468
- num.to_i == num.to_f ? num.to_i : num.to_f
469
- end
470
-
471
- # def ora_date_to_ruby_date(val)
472
- # val.to_time
473
- # end
474
-
475
- def date_to_time(val)
476
- case val
477
- when Time
478
- val
479
- when DateTime
480
- Time.parse(val.strftime("%c"))
481
- when Date
482
- Time.parse(val.strftime("%c"))
483
- end
484
- end
485
-
486
- end
487
66
 
488
67
  end