ruby-informix 0.6.2-i386-mswin32 → 0.7.0-i386-mswin32

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/lib/informix.rb ADDED
@@ -0,0 +1,380 @@
1
+ # $Id: informix.rb,v 1.13 2008/04/01 01:17:21 santana Exp $
2
+ #
3
+ # Copyright (c) 2008, Gerardo Santana Gomez Garrido <gerardo.santana@gmail.com>
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions
8
+ # are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products
16
+ # derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
+ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ # POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ require 'informixc'
31
+ require 'informix/seqcursor'
32
+ require 'informix/scrollcursor'
33
+
34
+ module Informix
35
+ VERSION = "0.7.0"
36
+ VERSION.freeze
37
+
38
+ # Shortcut to create a +Database+ object connected to +dbname+ as
39
+ # +user+ with +password+. If these are not given, connects to
40
+ # +dbname+ as the current user.
41
+ #
42
+ # The +Database+ object is passed to the block if it's given, and
43
+ # automatically closes the connection when the block terminates,
44
+ # returning the value of the block.
45
+ #
46
+ # Examples:
47
+ #
48
+ # Connecting to stores with our current credentials:
49
+ # db = Informix.connect('stores')
50
+ #
51
+ # Same thing, using a block and using a different server. The connection is
52
+ # closed automatically when the block terminates.
53
+ # result = Informix.connect('stores@server_shm') do |db|
54
+ # # do something with db
55
+ # # the last expression evaluated will be returned
56
+ # done
57
+ def self.connect(dbname, user = nil, password = nil, &block)
58
+ Database.open(dbname, user, password, &block)
59
+ end
60
+
61
+ # Returns the version of this Ruby/Informix driver.
62
+ # Note that this is NOT the Informix database version.
63
+ #
64
+ # Informix.version => string
65
+ def self.version
66
+ VERSION
67
+ end
68
+
69
+ class Database
70
+ private_class_method :new
71
+
72
+ alias disconnect close
73
+
74
+ # Exact version of the database server to which a Database object is
75
+ # connected
76
+ attr_reader :version
77
+
78
+ # The +IfxVersion+ struct provides the exact version of the database server
79
+ # to which a Database object is connected.
80
+ #
81
+ # Examples:
82
+ #
83
+ # db.version.server_type #=> "IBM Informix Dynamic Server"
84
+ # db.version.level #=> "C6"
85
+ # db.version.to_s #=> "IBM Informix Dynamic Server Version 9.40.FC6"
86
+ class IfxVersion
87
+ # Returns the complete version string
88
+ def to_s
89
+ full.rstrip
90
+ end
91
+ end
92
+
93
+ # Creates a +Database+ object connected to +dbname+ as
94
+ # +user+ with +password+. If these are not given, connects to
95
+ # +dbname+ as the current user.
96
+ #
97
+ # The +Database+ object is passed to the block if it's given, and
98
+ # automatically closes the connection when the block terminates, returning
99
+ # the value of the block.
100
+ def self.open(dbname, user = nil, password = nil)
101
+ db = new(dbname, user, password)
102
+ return db unless block_given?
103
+ begin
104
+ yield db
105
+ ensure
106
+ db.close
107
+ end
108
+ end
109
+
110
+ # Shortcut to create a +Statement+ object from +query+.
111
+ #
112
+ # The +Statement+ object is passed to the block if it's given, and
113
+ # automatically dropped when the block terminates, returning
114
+ # the value of the block.
115
+ #
116
+ # +query+ may contain '?' placeholders for input parameters;
117
+ # it must <b>NOT</b> be a query returning more than one row
118
+ # (use <tt>Database#cursor</tt> instead.)
119
+ #
120
+ # Examples:
121
+ #
122
+ # Preparing a statement:
123
+ # st = db.prepare('delete from orders where order_date = ?')
124
+ #
125
+ # Using a block:
126
+ # query 'update items set quantity = ? where item_num = ?'
127
+ # db.prepare(query) do |st|
128
+ # # do something with st
129
+ # # the last expression evaluated will be returned
130
+ # end
131
+ def prepare(query, &block)
132
+ Statement.new(self, query, &block)
133
+ end
134
+
135
+ # Shortcut to create, <b>execute and drop</b> a +Statement+ object from
136
+ # +query+.
137
+ #
138
+ # +query+ may contain '?' placeholders for input parameters;
139
+ # it <b>cannot</b> be a query returning <b>more than one</b> row
140
+ # (use <tt>Database#cursor</tt> instead.)
141
+ #
142
+ # Returns the record retrieved, in the case of a singleton select, or the
143
+ # number of rows affected, in the case of any other statement.
144
+ #
145
+ # Examples:
146
+ #
147
+ # Deleting records:
148
+ # db.execute('delete from orders where order_date = ?', Date.today)
149
+ #
150
+ # Updating a record:
151
+ # db.execute('update items set quantity = ? where item_num = ?', 10, 101)
152
+ def execute(query, *args)
153
+ Statement.new(self, query) {|stmt| stmt.execute(*args) }
154
+ end
155
+
156
+ # Shortcut to create a cursor object based on +query+ using +options+.
157
+ #
158
+ # The cursor object is passed to the block if it's given, and
159
+ # automatically dropped when the block terminates, returning
160
+ # the value of the block.
161
+ #
162
+ # +query+ may contain '?' placeholders for input parameters.
163
+ #
164
+ # +options+ can be a Hash object with the following possible keys:
165
+ #
166
+ # :scroll => true or false
167
+ # :hold => true or false
168
+ #
169
+ # Examples:
170
+ #
171
+ # This creates a +SequentialCursor+
172
+ # cur = db.cursor('select * from orders where order_date > ?')
173
+ # This creates a +ScrollCursor+
174
+ # cur = db.cursor('select * from customer', :scroll => true)
175
+ # This creates an +InsertCursor+
176
+ # cur = db.cursor('insert into stock values(?, ?, ?, ?, ?, ?)')
177
+ def cursor(query, options = nil, &block)
178
+ Cursor.new(self, query, options, &block)
179
+ end
180
+
181
+ # Shortcut to create, <b>open and iterate</b> a cursor object based on
182
+ # +query+ using +options+. The records are retrieved as arrays.
183
+ #
184
+ # The cursor object is passed to the block and
185
+ # automatically dropped when the block terminates. Returns __self__.
186
+ #
187
+ # +query+ may contain '?' placeholders for input parameters.
188
+ #
189
+ # +options+ can be a Hash object with the following possible keys:
190
+ #
191
+ # :scroll => true or false
192
+ # :hold => true or false
193
+ # :params => input parameters as an Array or nil
194
+ #
195
+ # Examples:
196
+ #
197
+ # Iterating over a table:
198
+ # db.each('select * from customer') do |cust|
199
+ # # do something with cust
200
+ # puts "#{cust[0] cust[1]}"
201
+ # end
202
+ # Same thing, using input parameters:
203
+ # query = 'select * from orders where order_date = ?'
204
+ # db.each(query, :params => [Date.today]) do |order|
205
+ # # do something with order
206
+ # end
207
+ def each(query, options = nil, &block)
208
+ Cursor.open(self, query, options) {|cur| cur.each(&block)}
209
+ self
210
+ end
211
+
212
+ # Similar to +Database#each+, except that retrieves records as hashes
213
+ # instead of arrays.
214
+ #
215
+ # Examples:
216
+ #
217
+ # Iterating over a table:
218
+ # db.each_hash('select * from customer') do |cust|
219
+ # # do something with cust
220
+ # puts "#{cust['fname'] cust['lname']}"
221
+ # end
222
+ def each_hash(query, options = nil, &block)
223
+ Cursor.open(self, query, options) {|cur| cur.each_hash(&block)}
224
+ self
225
+ end
226
+
227
+ # Shortcut to create a +Slob+ object.
228
+ #
229
+ # The +Slob+ object is passed to the block if it's given, and
230
+ # automatically closes it when the block terminates, returning
231
+ # the value of the block.
232
+ #
233
+ # +type+ can be Slob::BLOB or Slob::CLOB
234
+ #
235
+ # +options+ can be a Hash object with the following possible
236
+ # keys:
237
+ #
238
+ # :sbspace => Sbspace name
239
+ # :estbytes => Estimated size, in bytes
240
+ # :extsz => Allocation extent size
241
+ # :createflags => Create-time flags
242
+ # :openflags => Access mode
243
+ # :maxbytes => Maximum size
244
+ # :col_info => Get the previous values from the column-level storage
245
+ # characteristics for the specified database column
246
+ #
247
+ # Examples:
248
+ #
249
+ # Creating a CLOB:
250
+ # slob = db.slob
251
+ # Creating a BLOB without log and passing it to a block:
252
+ # slob = db.slob(Slob::BLOB, :createflags=>Slob:NOLOG) do |slob|
253
+ # # do something with slob
254
+ # end
255
+ def slob(type = Slob::CLOB, options = nil, &block)
256
+ Slob.new(self, type, options, &block)
257
+ end
258
+ end # class Database
259
+
260
+ class Statement
261
+ alias call []
262
+ alias execute []
263
+
264
+ class << self
265
+ alias _new new
266
+ end
267
+
268
+ # Creates a +Statement+ object from +query+.
269
+ #
270
+ # The +Statement+ object is passed to the block if it's given, and
271
+ # automatically dropped when the block terminates, returning
272
+ # the value of the block.
273
+ #
274
+ # +query+ may contain '?' placeholders for input parameters;
275
+ # it must <b>NOT</b> be a query returning more than one row
276
+ # (use +Cursor+ instead.)
277
+ def self.new(dbname, query)
278
+ stmt = _new(dbname, query)
279
+ return stmt if !block_given?
280
+ begin
281
+ yield stmt
282
+ ensure
283
+ stmt.drop
284
+ end
285
+ end
286
+ end # class Statement
287
+
288
+ class Slob
289
+ alias pos tell
290
+
291
+ class << self
292
+ alias _new new
293
+ end
294
+
295
+ # Creates a +Slob+ object.
296
+ #
297
+ # The +Slob+ object is passed to the block if it's given, and
298
+ # automatically closes it when the block terminates, returning
299
+ # the value of the block.
300
+ #
301
+ # +type+ can be Slob::BLOB or Slob::CLOB
302
+ #
303
+ # +options+ can be a Hash object with the following possible
304
+ # keys:
305
+ #
306
+ # :sbspace => Sbspace name
307
+ # :estbytes => Estimated size, in bytes
308
+ # :extsz => Allocation extent size
309
+ # :createflags => Create-time flags
310
+ # :openflags => Access mode
311
+ # :maxbytes => Maximum size
312
+ # :col_info => Get the previous values from the column-level storage
313
+ # characteristics for the specified database column
314
+ def self.new(dbname, query, options = nil)
315
+ slob = _new(dbname, query, options)
316
+ return slob if !block_given?
317
+ begin
318
+ yield slob
319
+ ensure
320
+ slob.close
321
+ end
322
+ end
323
+ end # class Slob
324
+
325
+ module Cursor
326
+ private_class_method :new0
327
+
328
+ # Shortcut to create a cursor object based on +query+ using +options+.
329
+ #
330
+ # The cursor object is passed to the block if it's given, and
331
+ # automatically dropped when the block terminates, returning
332
+ # the value of the block.
333
+ #
334
+ # +options+ can be a Hash object with the following possible keys:
335
+ #
336
+ # :scroll => true or false
337
+ # :hold => true or false
338
+ def self.new(db, query, options = nil)
339
+ if options
340
+ Hash === options||raise(TypeError,"options must be supplied as a Hash")
341
+ end
342
+ cur = new0(db, query, options)
343
+ return cur unless block_given?
344
+ begin
345
+ yield cur
346
+ ensure
347
+ cur.drop
348
+ end
349
+ end
350
+
351
+ # Shortcut to create <b>and open</b> a cursor object based on +query+
352
+ # using +options+ in a single step.
353
+ #
354
+ # The cursor object is passed to the block if it's given, and
355
+ # automatically dropped when the block terminates, returning
356
+ # the value of the block.
357
+ #
358
+ # +options+ can be a Hash object with the following possible keys:
359
+ #
360
+ # :scroll => true or false
361
+ # :hold => true or false
362
+ # :params => input parameters as an Array or nil
363
+ def self.open(db, query, options = nil)
364
+ params = nil
365
+ if options
366
+ Hash === options||raise(TypeError,"options must be supplied as a Hash")
367
+ (params = options[:params]) && (Array === params ||
368
+ raise(TypeError,"params must be supplied as an Array"))
369
+ end
370
+ cur = new(db, query, options)
371
+ params ? cur.open(*params) : cur.open
372
+ return cur unless block_given?
373
+ begin
374
+ yield cur
375
+ ensure
376
+ cur.drop
377
+ end
378
+ end
379
+ end # module Cursor
380
+ end # module Informix
@@ -0,0 +1,161 @@
1
+ # $Id: exceptions.rb,v 1.2 2008/03/29 01:38:35 santana Exp $
2
+ #
3
+ # Copyright (c) 2008, Gerardo Santana Gomez Garrido <gerardo.santana@gmail.com>
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions
8
+ # are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products
16
+ # derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
+ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ # POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ #--
31
+ # The following code is a translation of the original C code written
32
+ # by Edwin M. Fine <emofine at finecomputerconsultants dot com>
33
+ #++
34
+
35
+ module Informix
36
+ ExcInfo = Struct.new(:sql_code, :sql_state, :class_origin, :subclass_origin,
37
+ :message, :server_name, :connection_name)
38
+
39
+ # The +ExcInfo+ class works as an object representation of an Informix
40
+ # error state
41
+ class ExcInfo
42
+ FORMAT = "%-15s: %s\n".freeze
43
+
44
+ # excinfo.to_s => string
45
+ #
46
+ # Returns a string representation of the error.
47
+ def to_s
48
+ ret = "\n"
49
+ each_pair do |member, value|
50
+ ret += sprintf(FORMAT, member.to_s, value)
51
+ end
52
+ ret
53
+ end
54
+ end # class ExcInfo
55
+
56
+ # The +Error+ class is the base class for the rest of the exception classes
57
+ # used in this extension. It works as a collection of +ExcInfo+ objects
58
+ # when an error condition occurs.
59
+ class Error < StandardError
60
+ include Enumerable
61
+
62
+ # Informix::Error.new([string|array]) => obj
63
+ #
64
+ # Optional string is the exception message.
65
+ # Optional array must contain only instances of Informix::ExcInfo structs.
66
+ #
67
+ # Examples:
68
+ # exc = Informix::Error.new
69
+ # arr = [ExcInfo.new(x,y,z...), ExcInfo.new(a,b,c...)]
70
+ # exc = Informix::Error.new(arr)
71
+ def initialize(v = nil)
72
+ case v
73
+ when NilClass
74
+ @info = []
75
+ when String
76
+ @info = []
77
+ super
78
+ when Array
79
+ return @info = v if v.all? {|e| ExcInfo === e}
80
+ raise(TypeError, "Array may contain only Informix::ExcInfo structs")
81
+ else
82
+ raise(TypeError,
83
+ "Expected string, or array of Informix::ExcInfo, as argument")
84
+ end
85
+ end
86
+
87
+ # exc.add_info(sql_code, sql_state, class_origin, subclass_origin,
88
+ # message, server_name, connection_name) => self
89
+ #
90
+ # Appends the given information to the exception.
91
+ def add_info(*v)
92
+ v.flatten!
93
+ raise(ArgumentError,
94
+ "Invalid number of arguments (got %d, need %d)", v.size, 7) \
95
+ if v.size != 7
96
+ @info.push ExcInfo.new(*v)
97
+ end
98
+
99
+ # exc.size => num
100
+ #
101
+ # Returns the number of Informix exception messages in the exception.
102
+ def size
103
+ @info.size
104
+ end
105
+
106
+ alias length size
107
+
108
+ # exc.each {|exc_info| block } => exc_info
109
+ #
110
+ # Calls block once for each Informix::ExcInfo object in the exception.
111
+ def each(&block)
112
+ @info.each(&block)
113
+ end
114
+
115
+ # exc[index] => info
116
+ #
117
+ # Returns the ExcInfo object at index.
118
+ def [](index)
119
+ @info[index]
120
+ end
121
+
122
+ # exc.to_s => string
123
+ #
124
+ # Returns a string representation of self.
125
+ def to_s
126
+ return super if @info.size == 0
127
+ ret = ""
128
+ @info.each do |info|
129
+ ret += info.to_s
130
+ end
131
+ ret
132
+ end
133
+
134
+ # exc.message => string
135
+ #
136
+ # Overrides Exception#message. Returns first message in ExcInfo array,
137
+ # or if the array is empty, delegates back to the parent class.
138
+ def message
139
+ @info.size > 0 ? @info[0].message : super
140
+ end
141
+
142
+ # exc.sqlcode => fixnum
143
+ #
144
+ # Returns the SQLCODE for the first stored ExcInfo struct, or 0
145
+ # if none are stored.
146
+ def sql_code
147
+ @info.size > 0 ? @info[0].sql_code : 0
148
+ end
149
+ end # class Error
150
+
151
+ class Warning < StandardError; end
152
+
153
+ class InterfaceError < Error; end
154
+ class DatabaseError < Error; end
155
+ class DataError < Error; end
156
+ class OperationalError < Error; end
157
+ class IntegrityError < Error; end
158
+ class InternalError < Error; end
159
+ class ProgrammingError < Error; end
160
+ class NotSupportedError < Error; end
161
+ end # module Informix