fireruby 0.2.2-i586-linux

Sign up to get free protection for your applications and to get access to all the features.
data/doc/README ADDED
@@ -0,0 +1,289 @@
1
+ == FireRuby Version 0.2.1
2
+ This is a bug fix release for version 0.2.0 of the FireRuby library. FireRuby is
3
+ an extension to the Ruby language that provides access to the functionality of
4
+ the Firebird relational database management system.
5
+
6
+ == Enhancements & Alterations
7
+
8
+ No new functionality added for this release.
9
+
10
+ == Bug Fixes
11
+
12
+ - Fixed an intermittent bug that was causing an access violation when the Ruby
13
+ interpreter attempted to clean up at exited. The access violation was
14
+ occurring in a Firebird function call so I'm not exactly sure why it was
15
+ happening. The code has been restructured to bypass the issue.
16
+
17
+ - Fixed a bug in the code for the Generator object that was leaving an active
18
+ transaction lying around whenever an exception occurred in a call to fetch a
19
+ value from the Generator.
20
+
21
+ - Fixed a buffer overrun bug were the size of an input string was being used
22
+ to determine values written rather than the size of an output field.
23
+
24
+ == Issues
25
+
26
+ Nothing is perfect so this section outlines those issues that are known to
27
+ exist as of this release.
28
+
29
+ - The library currently does not support array columns. This may be implemented
30
+ for a later release depending on demand.
31
+
32
+ - There is an issue with the use of anonymous transactions inside of a block
33
+ for the Database#connect method. An attempt is made to close the connection
34
+ when the block exits. If, within the block, there is a call to the
35
+ Connection#execute_immediate method that generates a result set and,
36
+ subsequently, an exception is raised the anonymous transaction used in the
37
+ execute_immediate will be unavailable for closure. This will, in turn,
38
+ make it impossible to close the connection, resulting in an exception. As
39
+ a work around, don't use anonymous transactions for queries.
40
+
41
+ == Installation & Usage
42
+
43
+ The library is provided as a gem and built for use with Ruby 1.8+. Testing
44
+ against an earlier release of Ruby has not been performed. Installation requires
45
+ the Ruby Gems package to be installed. Assuming that these installation criteria
46
+ have been met the library can be installed on Windows by executing a command
47
+ such as the following...
48
+
49
+ gem install fireruby-0.2.0-mswin32.gem
50
+
51
+ On the Mac OS X platform you may require super user privilege if your Ruby is
52
+ installed to the default location (i.e. /usr/local/lib). In this case you can
53
+ use the sudo command to make the installation like this...
54
+
55
+ sudo gem install fireruby-0.2.0-powerpc-darwin.gem
56
+
57
+ Once the gem installation is complete the FireRuby functionality can be accessed
58
+ in code with the usual gem style requires...
59
+
60
+ require 'rubygems'
61
+ require_gem 'fireruby'
62
+
63
+ == Build Details
64
+
65
+ The FireRuby library is an extension of the Ruby language written in C. For Mac
66
+ OS X the library was built against Firebird installed as a framework, version
67
+ 1.5.1, and with Ruby version 1.8.2. For the Windows platform the library was
68
+ built against a Ruby installation created using the one-click installer, version
69
+ 1.8.2. The Windows build was created using the freely available Microsoft
70
+ compilers and SDKs and built against a standard installation of Firebird,
71
+ version 1.5.2.
72
+
73
+ == So How Do I Use It?
74
+
75
+ This section will provide some examples of usage for the the FireRuby classes.
76
+ Throughout the code the following set of assumptions are made.
77
+
78
+ - The user name and password that will be employed to attach to the database
79
+ are 'sysdba' and 'masterkey' respectively (the Firebird defaults).
80
+
81
+ - The databases attached to will all be local (i.e. they will all reside on the
82
+ same machine) as the test code.
83
+
84
+ A database, from the Firebird perspective, is made up of one or more files. From
85
+ a FireRuby perspective a user interaction with a database starts through the
86
+ Database class. This class provides facilities that allow for creating, dropping
87
+ and connecting to database instances. For example, to obtain a connection to a
88
+ database you would use something like the following...
89
+
90
+ require 'rubygems'
91
+ require_gem 'fireruby'
92
+
93
+ include FireRuby
94
+
95
+ db = Database.new('./test.fdb')
96
+ c = db.connect('sysdba', 'masterkey')
97
+
98
+ This example starts by requiring the necessary files and including the FireRuby
99
+ module locally - later examples will not detail these lines but they are always
100
+ required to use the FireRuby code.
101
+
102
+ The first line of code after the include creates a new database object. This
103
+ process does not actually create the database file (see the Database#create
104
+ method API documentation if that is what you want to do), it simple creates an
105
+ abstract reference to a database. In creating the Database object we had to
106
+ provide a database specification string which identifies the database we want to
107
+ access. In this case we are specifying a database in the current working
108
+ directory called 'test.fdb'. See the Firebird documentation for details on the
109
+ structure of more complex database specifications.
110
+
111
+ The last line of code in the example given above opens a connection to the
112
+ database. In doing this we had to provide two parameters, the database user
113
+ name and password. These are required to gain access to the database.
114
+
115
+ A connection represents a conduit to a database and obtaining a connection is a
116
+ prerequisite to working with the database. The FireRuby library support having
117
+ multiple connections, to one or more databases, using one or more users, active
118
+ simultaneously. FireRuby represents a database connection through objects of the
119
+ Connection class. This class provides functionality to determine the current
120
+ state a database connection (open or closed) and for closing the connection.
121
+ Connections take up resources, both locally and on the database server and
122
+ should be explicitly closed when they are no longer required.
123
+
124
+ The connection class also provides a set of conveniences methods to allow for
125
+ the execution of SQL against a database. These methods, execute_immediate and
126
+ execute, represently two slightly different approaches to executing SQL against
127
+ the database. Refer to the API documentation for more information.
128
+
129
+ An advantage of using a relational database management system like Firebird is
130
+ that it provides transactions. A transaction represents a block of work that is
131
+ either all completed successful or none of it is applied. From the perspective
132
+ of the database this means that a series of steps that make changes to the
133
+ tables in the database can be wrapped in a transaction to insure that they
134
+ either all complete or that none of the changes are applied.
135
+
136
+ The FireRuby library represents a database transaction through instances of the
137
+ Transaction class. There are two ways of obtaining a Transaction using the
138
+ library, both requiring you to have an open database connection. The first way
139
+ is to construct a new Transaction object like so...
140
+
141
+ tx = Transaction.new(connection)
142
+
143
+ The Transaction constructor takes a single parameter which must be either a
144
+ Connection object or an array of Connection objects. If you pass an array of
145
+ Connection objects to this constructor then the Transaction created will apply
146
+ across all of the databases that the connections refer to, allowing you to
147
+ have transactional control of work that must utilise more than one database. The
148
+ second way to obtain a transaction is to simply request one from a Connection
149
+ object, like so.
150
+
151
+ tx = connection.start_transaction
152
+
153
+ In this case the transaction will only ever apply to one database, the one that
154
+ the connection relates to. This method also accepts a block, taking a single
155
+ parameter. The parameter passed to the block will be the transaction created.
156
+ In this case the lifetime of the transaction is delimited by the block. If the
157
+ block completes successfully then the work of the transaction will be committed
158
+ to the database. If the block raises an exception then the transactional work
159
+ will be rolled back.
160
+
161
+ When the block of work associated with a transaction is complete the user must
162
+ instruct the system to either apply the changes implemented by the work or to
163
+ discard them. This can be done by calling the commit or rollback methods of the
164
+ Transaction class respectively. Once a transaction has been committed or rolled
165
+ back it can no longer be used and should be discarded. Note that attempts to
166
+ close a connection that has an active transaction against it will fail, so one
167
+ of the commit or rollback methods should be explictly called in code. The
168
+ block technique detailed above helps protect against the failure to do this and
169
+ is a useful technique.
170
+
171
+ The Transaction object provides a number of other informational and utility
172
+ methods. Check the API documentation for this class for more information.
173
+
174
+ So we've looked at connections and transactions, but how do we actually do
175
+ something practical with the database. Well there are a number of possible
176
+ approaches that we can take to this. Both the Connection and Transaction classes
177
+ have convenience method for the execution of SQL statements and these are useful
178
+ for quick SQL. Where you want something that you can repeatedly reuse and,
179
+ optionally, pass parameters to then you need the Statement class.
180
+
181
+ The Statement class represents a SQL statement that has been validated and
182
+ prepared for execution. Here's an example of creating a SQL statement...
183
+
184
+ s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE', 3)
185
+
186
+ In this example we have created a Statement object that wraps a SQL select from
187
+ a table called MY_TABLE. The first parameter to the constructor is a Connection
188
+ object and the second is a Transaction, both mandatory. You may be thinking
189
+ 'why do I need a transaction here, I'm not changing anything?'. This is true
190
+ (well sort of) but it's a requirement of the underlying database system. This
191
+ is also the case for the final parameter to the constructor. The value 3 is
192
+ the SQL dialect to be used with the Statement. This exists for reason arising
193
+ from the move from closed source Interbase to open source Firebird. The
194
+ parameter should be given a value of between 1 and 3. If you're not sure what
195
+ this is and you're only using Firebird it's probably safe to use a value of
196
+ 3 here. Other values are for backward compatibility. Consult the Firebird and
197
+ Interbase documentation for more details.
198
+
199
+ Anyway, now that we have our Statement how do we use it. Well, there are two
200
+ approaches to using the Statement object. For statements like the one used
201
+ above, queries that take no parameters, you can use the Statement object to
202
+ build a ResultSet object, like so...
203
+
204
+ r = ResultSet.new(s)
205
+
206
+ The ResultSet class will be covered in a little more detail below. The other
207
+ means by which a Statement can be used is to call one of it's execute methods.
208
+ The one to be called depends on whether the Statement requires parameters or
209
+ not. What are parameters you ask? Well, look at the following...
210
+
211
+ s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE WHERE MYID = ?', 3)
212
+
213
+ Note that the SQL select for this Statement contains a '?'. This is a position
214
+ holder for a value that the statement expects to be provided later. A Statement
215
+ that wraps such a piece of SQL must be provided with the necessary parameters
216
+ to execute properly. Where a Statement object represents SQL that requires a
217
+ parameter then the execute_for method must be called, like this...
218
+
219
+ r = s.execute_for([25])
220
+
221
+ This code executes the SQL substituting the parameters from the array of data
222
+ passed to the function call. If a Statement object represents SQL that does not
223
+ require parameter values a call to the execute method will suffice, such as the
224
+ following...
225
+
226
+ r = s.execute
227
+
228
+ The execute methods for the Statement class, as with all of the execute methods
229
+ for the FireRuby library, have two potential return values. They will either
230
+ return nil or they will return a ResultSet object. A ResultSet object will only
231
+ be returned for SQL statements that constitute a query, irrespective of whether
232
+ that query returns any data. For all other SQL statements the various execute
233
+ method will return nil.
234
+
235
+ A ResultSet object represents a handle by which the data retrieved for a SQL
236
+ query can be accessed. To fetch a row of data from a ResultSet object you call
237
+ the fetch method, like the following...
238
+
239
+ row = r.fetch
240
+
241
+ This fetches a single row of data for a query represented as a Row object (which
242
+ will be covered shortly). The ResultSet class also provides for iteration across
243
+ the contents of a result set by providing an each method. The block to the each
244
+ method will be passed the data for the ResultSet, a row at a time.
245
+
246
+ It should be noted that both the Statement and ResultSet objects hold resources
247
+ while they are active. They both possess close methods and these should be
248
+ explicitly called to release the associated resources. The exception to this
249
+ rule is for ResultSets. If you select all of the rows from a ResultSet then the
250
+ resources for the ResultSet are automatically released. It is still safe to call
251
+ close on such a ResultSet as this will not cause errors.
252
+
253
+ Okay, so you've gotten a row of data in the form of a Row object from your
254
+ ResultSet, how do we get the data out of it? Well, there are a number of ways
255
+ of doing this. You can treat the Row object like an array and dereference the
256
+ columns of data within the row like this...
257
+
258
+ value = row[1]
259
+
260
+ The index specified to the array dereference operator specifies the column that
261
+ you want the data for. Column indices start at 0. Alternatively you can use the
262
+ column name to access the data, like this...
263
+
264
+ value = row['MYID']
265
+
266
+ This is beneficial as it frees you from the constraint of knowing the ordering
267
+ of the columns within the row. For more information of the Row class please
268
+ consult the API documentation.
269
+
270
+ Well that covers the bulk of the classes provided by the FireRuby library. The
271
+ three which haven't been touched upon are the Generator class, the Blob class
272
+ and the FireRubyException class.
273
+
274
+ The Generator class is a wrapper around the Firebird generator facility. A
275
+ generator, also known as a sequence, provides a means of creating a list of
276
+ numeric values in a way that is guaranteed to be thread and process safe. Used
277
+ properly generators can be employed to create unique sequences that make perfect
278
+ table keys. Consult the API documentation for more details on the Generator
279
+ class.
280
+
281
+ The Blob class is returned as part of the Row object data obtained from a
282
+ ResultSet. The class wraps the concept of a binary large object stored in the
283
+ database. Consult the API documentation for further information.
284
+
285
+ The FireRubyException class is the error class used by the FireRuby library
286
+ whenever it hits trouble. If an exception is raised by the FireRuby code then
287
+ its extremely likely that it will be an instance of this class. The class
288
+ provides a means of finding out a little more about what exactly has gone
289
+ wrong. Again, consult the API documentation for more details.