ruby-plsql 0.2.2 → 0.2.3

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