fireruby 0.2.2-i586-linux

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/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.