fireruby 0.4.1-mswin32 → 0.4.2-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/doc/README +456 -456
  2. data/doc/license.txt +411 -411
  3. data/examples/example01.rb +65 -65
  4. data/lib/SQLType.rb +223 -227
  5. data/lib/fireruby.rb +22 -22
  6. data/lib/fr_lib.so +0 -0
  7. data/lib/mkdoc +1 -1
  8. data/lib/src.rb +1795 -1795
  9. data/test/AddRemoveUserTest.rb +56 -55
  10. data/test/BackupRestoreTest.rb +99 -99
  11. data/test/BlobTest.rb +57 -0
  12. data/test/CharacterSetTest.rb +63 -63
  13. data/test/ConnectionTest.rb +111 -111
  14. data/test/DDLTest.rb +54 -54
  15. data/test/DatabaseTest.rb +83 -83
  16. data/test/GeneratorTest.rb +50 -50
  17. data/test/KeyTest.rb +140 -140
  18. data/test/ResultSetTest.rb +162 -162
  19. data/test/RoleTest.rb +73 -0
  20. data/test/RowCountTest.rb +65 -65
  21. data/test/RowTest.rb +203 -203
  22. data/test/SQLTest.rb +182 -182
  23. data/test/SQLTypeTest.rb +101 -101
  24. data/test/ServiceManagerTest.rb +29 -29
  25. data/test/StatementTest.rb +135 -135
  26. data/test/TestSetup.rb +11 -11
  27. data/test/TransactionTest.rb +112 -112
  28. data/test/TypeTest.rb +92 -92
  29. data/test/UnitTest.rb +65 -64
  30. metadata +49 -110
  31. data/doc/CVS/Entries +0 -3
  32. data/doc/CVS/Entries.Log +0 -2
  33. data/doc/CVS/Repository +0 -1
  34. data/doc/CVS/Root +0 -1
  35. data/doc/classes/CVS/Entries +0 -1
  36. data/doc/classes/CVS/Entries.Log +0 -1
  37. data/doc/classes/CVS/Repository +0 -1
  38. data/doc/classes/CVS/Root +0 -1
  39. data/doc/classes/FireRuby/CVS/Entries +0 -1
  40. data/doc/classes/FireRuby/CVS/Entries.Log +0 -7
  41. data/doc/classes/FireRuby/CVS/Repository +0 -1
  42. data/doc/classes/FireRuby/CVS/Root +0 -1
  43. data/doc/classes/FireRuby/Connection.src/CVS/Entries +0 -1
  44. data/doc/classes/FireRuby/Connection.src/CVS/Repository +0 -1
  45. data/doc/classes/FireRuby/Connection.src/CVS/Root +0 -1
  46. data/doc/classes/FireRuby/Database.src/CVS/Entries +0 -1
  47. data/doc/classes/FireRuby/Database.src/CVS/Repository +0 -1
  48. data/doc/classes/FireRuby/Database.src/CVS/Root +0 -1
  49. data/doc/classes/FireRuby/FireRubyError.src/CVS/Entries +0 -1
  50. data/doc/classes/FireRuby/FireRubyError.src/CVS/Repository +0 -1
  51. data/doc/classes/FireRuby/FireRubyError.src/CVS/Root +0 -1
  52. data/doc/classes/FireRuby/Generator.src/CVS/Entries +0 -1
  53. data/doc/classes/FireRuby/Generator.src/CVS/Repository +0 -1
  54. data/doc/classes/FireRuby/Generator.src/CVS/Root +0 -1
  55. data/doc/classes/FireRuby/ResultSet.src/CVS/Entries +0 -1
  56. data/doc/classes/FireRuby/ResultSet.src/CVS/Repository +0 -1
  57. data/doc/classes/FireRuby/ResultSet.src/CVS/Root +0 -1
  58. data/doc/classes/FireRuby/Statement.src/CVS/Entries +0 -1
  59. data/doc/classes/FireRuby/Statement.src/CVS/Repository +0 -1
  60. data/doc/classes/FireRuby/Statement.src/CVS/Root +0 -1
  61. data/doc/classes/FireRuby/Transaction.src/CVS/Entries +0 -1
  62. data/doc/classes/FireRuby/Transaction.src/CVS/Repository +0 -1
  63. data/doc/classes/FireRuby/Transaction.src/CVS/Root +0 -1
  64. data/doc/files/CVS/Entries +0 -1
  65. data/doc/files/CVS/Repository +0 -1
  66. data/doc/files/CVS/Root +0 -1
  67. data/examples/CVS/Entries +0 -2
  68. data/examples/CVS/Repository +0 -1
  69. data/examples/CVS/Root +0 -1
  70. data/lib/CVS/Entries +0 -6
  71. data/lib/CVS/Repository +0 -1
  72. data/lib/CVS/Root +0 -1
  73. data/test/CVS/Entries +0 -20
  74. data/test/CVS/Repository +0 -1
  75. data/test/CVS/Root +0 -1
data/doc/README CHANGED
@@ -1,456 +1,456 @@
1
- = FireRuby Version 0.4.1
2
- FireRuby is an extension for the Ruby programming language that provides access
3
- to the Firebird open source RDBMS. The FireRuby library is release under the
4
- Mozilla Public Licence version 1.1 and is free for commercial use.
5
-
6
- ---
7
-
8
- == Enhancements & Alterations
9
-
10
- This release has been brought about as a direct result of efforts to get the
11
- library working on a 64 bit platform. This process exposed some code of
12
- questionable quality. All of the issues raised in getting a 64 bit build have
13
- been addressed and it's only fair that the improvements obtained be passed on
14
- to all platforms. Functionally nothing has changed since the last release and
15
- the new version should replace the old with no problems.
16
-
17
- === Bug Fixes
18
-
19
- A number of bug fixes were implemented as part of the effort to get the library
20
- working on a 64 bit platform. None of these had been raised as bugs against the
21
- library so I have nothing specific to tick off.
22
-
23
- === Backward Compatibility
24
-
25
- Version 0.4.0 of the library made fundamental changes to functionality that was
26
- available in earlier versions of the library. To help accommodate this change
27
- elements were added to support backward compatibility. The relevant details are
28
- listed here...
29
-
30
- - Row objects were switched from keying on column names to keying on column
31
- aliases. To revert to the older functionality assign a value of true to the
32
- $FireRubySettings[:ALIAS_KEYS] global setting.
33
-
34
- - DATE columns were switched from being returned as Time objects to be returned
35
- as Date objects. To revert to the older functionality assign a value of true
36
- to the $FireRubySettings[:DATE_AS_DATE] global setting.
37
-
38
- One other point to note is that, as of version 0.4.0, Enumerable is included in
39
- the Row and ResultSet classes.
40
-
41
- === Issues
42
-
43
- Nothing is perfect so this section outlines those issues that are known to
44
- exist as of this release.
45
-
46
- - The service manager functionality does not appear to work on the Mac OS X
47
- platform. I don't believe that this is a problem in the FireRuby code as I
48
- have tested the Firebird gbak utility with the -service option and it gives
49
- the same result. If anyone knows this to be untrue or of a work around let me
50
- know.
51
-
52
- - The library currently does not support array columns. This may be implemented
53
- for a later release depending on demand. No-one has asked for this so far so
54
- I'm starting to think that people don't make much use of array columns.
55
-
56
- - The library can be a bit touchy if you don't clean up after yourself. This
57
- can result in a segmentation violation whenever your program stops if you've
58
- left a ResultSet or Statement object unclosed. Check through your code to
59
- insure that this isn't the case before contacting me about problems in this
60
- line.
61
-
62
- - The unit tests are currently set up on the assumption that the password for
63
- your sysdba account is 'masterkey'. If this is not the case, or if you wish
64
- to use an alternative user for testing, edit the TestSetup.rb file in the
65
- unit test directory and update the entries there as appropriate. I should also
66
- note that you may need to alter permissions on the test directory to run the
67
- actual unit tests on Linux/Unix.
68
-
69
- ---
70
-
71
- == Credit Where Credit Is Due
72
-
73
- Over its lifetime the FireRuby library has benefitted from input provided by a
74
- number of individuals. This section acknowledges these inputs...
75
-
76
- <b>Ken Kunz</b>: Ken has been a strong supporter of the library from early on and
77
- has contributed through feedback, testing and suggestions. For some time he
78
- produced and tested the Linux builds of the library.
79
-
80
- <b>David Walthour</b>: David basically executed all of the work to generate the
81
- 64 bit version of the library, along the way exposing some flaws in the code
82
- (amazing what a bit of peer review can find!). David produced the 64 bit version
83
- of the library gem.
84
-
85
- <b>John Wood</b>: John currently builds and tests the Mac OS X version of the
86
- library.
87
-
88
- <b>Art Federov</b>: Art provided input on handling and testing character sets.
89
-
90
- ---
91
-
92
- == Installation & Usage
93
-
94
- The library is provided as a gem and built for use with Ruby 1.8+. Testing
95
- against an earlier release of Ruby has not been performed. Installation requires
96
- the Ruby Gems package to be installed. Assuming that these installation criteria
97
- have been met the library can be installed on Windows by executing a command
98
- such as the following...
99
-
100
- gem install fireruby-0.4.1-mswin32.gem
101
-
102
- On the Mac OS X platform you may require super user privilege if your Ruby is
103
- installed to the default location (i.e. /usr/local/lib). In this case you can
104
- use the sudo command to make the installation like this...
105
-
106
- sudo gem install fireruby-0.4.1-powerpc-darwin.gem
107
-
108
- Once the gem installation is complete the FireRuby functionality can be accessed
109
- in code with the usual gem style requires...
110
-
111
- require 'rubygems'
112
- require 'fireruby'
113
-
114
- === Build Details
115
-
116
- The FireRuby library is a Ruby extension written in C. The avoid build issues
117
- binary versions are provided for a number of platforms, including...
118
-
119
- - Windows: Built against a version of Ruby installed using the one-click
120
- installer and using the freely available Microsoft development tools. This
121
- version was compiled against version 1.5.2 of Firebird.
122
-
123
- - Linux: Built on Ubuntu Linux (Breezy Badger) using a version of Ruby 1.8.2
124
- installed via the Synaptic package manager. This package manager was also
125
- used to make an installation of Firebird.
126
-
127
- - Mac OS X: Build on version 10.4.3 of OS X against the 1.8.2 version of Ruby
128
- that comes with the operating system. A framework installation of Firebird
129
- version 1.5.1 was used to make the build.
130
-
131
- Its possible to try and build the library on other platforms so I'll provide a
132
- few details as to how to go about doing this. The first step is to download the
133
- CVS tar ball from the Ruby Forge site and expand it into a local directory. This
134
- will create a directory called fireruby. Change into this directory and then
135
- into the fireruby/src subdirectory.
136
-
137
- This directory contains a file called extconf.rb that is used to create the
138
- make file used to build the library. The make file is created by executing this
139
- file but before you do there are a number of parameters that you should be
140
- aware of. The main one of these is --with-firebird-dir. This parameter is used
141
- to indicate the whereabouts of the Firebird headers and libraries. The following
142
- is an example of how this might be used...
143
-
144
- ruby extconf.rb --with-firebird-dir=/usr/local/firebird
145
-
146
- You may need to customise the path for your own Firebird installation. The path
147
- specified should be a directory that contains subdirectories called 'lib' and
148
- 'include'. The lib subdirectory should contain the fbclient shared library and
149
- include should contain the ibase.h header file.
150
-
151
- A note for Windows users. The library requires the free Microsoft C++ compiler,
152
- the Windows SDK, the .NET SDK and nmake to build. If you have all of these
153
- and Firebird installed to default locations then you can create a make file
154
- using the mkmf.bat batch file in the src directory.
155
-
156
- Once you have the make file you can attempt a library build using either make
157
- (on Unix/Linux) or nmake (on Windows). If it builds successfully you can move
158
- on to creating a gem file for installation. To do this, change into the ../gem
159
- directory. In this directory you can do the following (on Windows)...
160
-
161
- make_gem
162
-
163
- ...or the following (on Unix/Linux)...
164
-
165
- ruby make_gem.rb
166
-
167
- This will create the gem file in the main fireruby directory. Install this and
168
- execute the unit tests to check whether you're version is working.
169
-
170
- === So How Do I Use It?
171
-
172
- This section will provide some examples of usage for the the FireRuby classes.
173
- Throughout the code the following set of assumptions are made.
174
-
175
- - The user name and password that will be employed to attach to the database
176
- are 'sysdba' and 'masterkey' respectively (the Firebird defaults).
177
-
178
- - The databases attached to will all be local (i.e. they will all reside on the
179
- same machine) as the test code.
180
-
181
- A database, from the Firebird perspective, is made up of one or more files. From
182
- a FireRuby perspective a user interaction with a database starts through the
183
- Database class. This class provides facilities that allow for creating, dropping
184
- and connecting to database instances. For example, to obtain a connection to a
185
- database you would use something like the following...
186
-
187
- require 'rubygems'
188
- require 'fireruby'
189
-
190
- include FireRuby
191
-
192
- db = Database.new('./test.fdb')
193
- c = db.connect('sysdba', 'masterkey')
194
-
195
- This example starts by requiring the necessary files and including the FireRuby
196
- module locally - later examples will not detail these lines but they are always
197
- required to use the FireRuby code.
198
-
199
- The first line of code after the include creates a new database object. This
200
- process does not actually create the database file (see the Database#create
201
- method API documentation if that is what you want to do), it simple creates an
202
- abstract reference to a database. In creating the Database object we had to
203
- provide a database specification string which identifies the database we want to
204
- access. In this case we are specifying a database in the current working
205
- directory called 'test.fdb'. See the Firebird documentation for details on the
206
- structure of more complex database specifications.
207
-
208
- The last line of code in the example given above opens a connection to the
209
- database. In doing this we had to provide two parameters, the database user
210
- name and password. These are required to gain access to the database.
211
-
212
- A connection represents a conduit to a database and obtaining a connection is a
213
- prerequisite to working with the database. The FireRuby library support having
214
- multiple connections, to one or more databases, using one or more users, active
215
- simultaneously. FireRuby represents a database connection through objects of the
216
- Connection class. This class provides functionality to determine the current
217
- state a database connection (open or closed) and for closing the connection.
218
- Connections take up resources, both locally and on the database server and
219
- should be explicitly closed when they are no longer required.
220
-
221
- The connection class also provides a set of conveniences methods to allow for
222
- the execution of SQL against a database. These methods, execute_immediate and
223
- execute, represently two slightly different approaches to executing SQL against
224
- the database. Refer to the API documentation for more information.
225
-
226
- An advantage of using a relational database management system like Firebird is
227
- that it provides transactions. A transaction represents a block of work that is
228
- either all completed successful or none of it is applied. From the perspective
229
- of the database this means that a series of steps that make changes to the
230
- tables in the database can be wrapped in a transaction to insure that they
231
- either all complete or that none of the changes are applied.
232
-
233
- The FireRuby library represents a database transaction through instances of the
234
- Transaction class. There are two ways of obtaining a Transaction using the
235
- library, both requiring you to have an open database connection. The first way
236
- is to construct a new Transaction object like so...
237
-
238
- tx = Transaction.new(connection)
239
-
240
- The Transaction constructor takes a single parameter which must be either a
241
- Connection object or an array of Connection objects. If you pass an array of
242
- Connection objects to this constructor then the Transaction created will apply
243
- across all of the databases that the connections refer to, allowing you to
244
- have transactional control of work that must utilise more than one database. The
245
- second way to obtain a transaction is to simply request one from a Connection
246
- object, like so.
247
-
248
- tx = connection.start_transaction
249
-
250
- In this case the transaction will only ever apply to one database, the one that
251
- the connection relates to. This method also accepts a block, taking a single
252
- parameter. The parameter passed to the block will be the transaction created.
253
- In this case the lifetime of the transaction is delimited by the block. If the
254
- block completes successfully then the work of the transaction will be committed
255
- to the database. If the block raises an exception then the transactional work
256
- will be rolled back.
257
-
258
- When the block of work associated with a transaction is complete the user must
259
- instruct the system to either apply the changes implemented by the work or to
260
- discard them. This can be done by calling the commit or rollback methods of the
261
- Transaction class respectively. Once a transaction has been committed or rolled
262
- back it can no longer be used and should be discarded. Note that attempts to
263
- close a connection that has an active transaction against it will fail, so one
264
- of the commit or rollback methods should be explictly called in code. The
265
- block technique detailed above helps protect against the failure to do this and
266
- is a useful technique.
267
-
268
- The Transaction object provides a number of other informational and utility
269
- methods. Check the API documentation for this class for more information.
270
-
271
- So we've looked at connections and transactions, but how do we actually do
272
- something practical with the database. Well there are a number of possible
273
- approaches that we can take to this. Both the Connection and Transaction classes
274
- have convenience method for the execution of SQL statements and these are useful
275
- for quick SQL. Where you want something that you can repeatedly reuse and,
276
- optionally, pass parameters to then you need the Statement class.
277
-
278
- The Statement class represents a SQL statement that has been validated and
279
- prepared for execution. Here's an example of creating a SQL statement...
280
-
281
- s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE', 3)
282
-
283
- In this example we have created a Statement object that wraps a SQL select from
284
- a table called MY_TABLE. The first parameter to the constructor is a Connection
285
- object and the second is a Transaction, both mandatory. You may be thinking
286
- 'why do I need a transaction here, I'm not changing anything?'. This is true
287
- (well sort of) but it's a requirement of the underlying database system. This
288
- is also the case for the final parameter to the constructor. The value 3 is
289
- the SQL dialect to be used with the Statement. This exists for reason arising
290
- from the move from closed source Interbase to open source Firebird. The
291
- parameter should be given a value of between 1 and 3. If you're not sure what
292
- this is and you're only using Firebird it's probably safe to use a value of
293
- 3 here. Other values are for backward compatibility. Consult the Firebird and
294
- Interbase documentation for more details.
295
-
296
- Anyway, now that we have our Statement how do we use it? Well, the answer is
297
- that we call once of the Statement objects execute methods. The one to be called
298
- depends on whether the Statement requires parameters or not. What are parameters
299
- you ask? Well, look at the following...
300
-
301
- s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE WHERE MYID = ?', 3)
302
-
303
- Note that the SQL select for this Statement contains a '?'. This is a position
304
- holder for a value that the statement expects to be provided later. A Statement
305
- that wraps such a piece of SQL must be provided with the necessary parameters
306
- to execute properly. Where a Statement object represents SQL that requires a
307
- parameter then the execute_for method must be called, like this...
308
-
309
- s.execute_for([25])
310
-
311
- This code executes the SQL substituting the parameters from the array of data
312
- passed to the function call. If a Statement object represents SQL that does not
313
- require parameter values a call to the execute method will suffice, such as the
314
- following...
315
-
316
- s.execute
317
-
318
- The execute methods for the Statement class, as with all of the execute methods
319
- for the FireRuby library, have three potential return values. They will either
320
- return an Integer, a ResultSet object or nil. A ResultSet object will only be
321
- returned for SQL statements that constitute a query, irrespective of whether
322
- that query returns any data. For all other SQL statements (inserts, updates and
323
- deletes) the execute method will return a count of the number of rows affected
324
- by the statement execution. For any other SQL statements the various execute
325
- methods will return nil.
326
-
327
- A ResultSet object represents a handle by which the data retrieved for a SQL
328
- query can be accessed. While it's possible to obtain a ResultSet from one of the
329
- execute methods on the Connection, Transaction or Statement classes it is more
330
- efficient to create one directly. The constructor for the ResultSet class
331
- accepts the same arguments as the constructor for the Statement class but will
332
- throw an exception if the SQL statement specified is not a query.
333
-
334
- Once we have obtained a ResultSet we can extract the rows of data for a query
335
- from it. To fetch a row of data from a ResultSet object you call the fetch
336
- method, like the following...
337
-
338
- row = r.fetch
339
-
340
- This fetches a single row of data for a query represented as a Row object (which
341
- will be covered shortly). The ResultSet class also provides for iteration across
342
- the contents of a result set by providing an each method. The block to the each
343
- method will be passed the data for the ResultSet, a row at a time.
344
-
345
- It should be noted that both the Statement and ResultSet objects hold resources
346
- while they are active. They both possess close methods and these should be
347
- explicitly called to release the associated resources. The exception to this
348
- rule is for ResultSets. If you select all of the rows from a ResultSet then the
349
- resources for the ResultSet are automatically released. It is still safe to call
350
- close on such a ResultSet as this will not cause errors.
351
-
352
- Okay, so you've gotten a row of data in the form of a Row object from your
353
- ResultSet, how do we get the data out of it? Well, there are a number of ways
354
- of doing this. You can treat the Row object like an array and dereference the
355
- columns of data within the row like this...
356
-
357
- value = row[1]
358
-
359
- The index specified to the array dereference operator specifies the column that
360
- you want the data for. Column indices start at 0. Alternatively you can treat
361
- the Row object like a read only Hash object and use the column name to access
362
- the data, like this...
363
-
364
- value = row['MYID']
365
-
366
- This is beneficial as it frees you from the constraint of knowing the ordering
367
- of the columns within the row. For more information of the Row class please
368
- consult the API documentation.
369
-
370
- That covers the bulk of the SQL classes provided by the FireRuby library. The
371
- two which haven't been touched upon are the Generator class and the Blob class.
372
-
373
- The Generator class is a wrapper around the Firebird generator facility. A
374
- generator, also known as a sequence, provides a means of creating a list of
375
- numeric values in a way that is guaranteed to be thread and process safe. Used
376
- properly generators can be employed to create unique sequences that make perfect
377
- table keys. Consult the API documentation for more details on the Generator
378
- class.
379
-
380
- The Blob class is returned as part of the Row object data obtained from a
381
- ResultSet. The class wraps the concept of a binary large object stored in the
382
- database. Consult the API documentation for further information.
383
-
384
- === Errors
385
-
386
- Whenever a problem occurs within a FireRuby library class then it is likely that
387
- a FireRubyException will be thrown. The FireRubyException class is the error
388
- class used by the FireRuby library whenever it hits trouble. The class provides
389
- a means of finding out a little more about what exactly has gone wrong. Again,
390
- consult the API documentation for more details.
391
-
392
- === Firebird Service Manager
393
-
394
- The FireRuby library provides a set of class that provide for an interaction
395
- with the Firebird service manager. This interaction allows for the execution of
396
- tasks, such as the backing up of a database, on the database server. To execute
397
- such tasks against the service manager for a Firebird instance you first need
398
- to obtain a ServiceManager class instance. This can be done as follows...
399
-
400
- sm = ServiceManager.new('localhost')
401
-
402
- The constructor for the ServiceManager class takes a single parameter that is
403
- the host name of the server running the Firebird instance. In the example above
404
- this would be a local machine but could be any machine that can be reached over
405
- the network (NOTE: although Firebird supports a number of underlying transport
406
- protocols in accessing a service manager currently only TCP/IP is supported for
407
- the FireRuby library).
408
-
409
- The next step in executing service manager tasks involves connecting your
410
- ServiceManager object to the service manager for a Firebird instance. To do this
411
- you must supply a user name and password. The user name and password used must
412
- be a user that exists on the Firebird instance. The user you connect as can
413
- affect the access to services that you receive. For example, to connect as the
414
- database administrator you might do the following...
415
-
416
- sm.connect('sysdba', 'masterkey')
417
-
418
- Assuming that this succeeds you are now ready to execute tasks through your
419
- ServiceManager object. Within the FireRuby library individual task are broken
420
- out into separate classes. For this release (0.4.1) there are four task classes
421
- provided in the library - Backup, Restore, AddUser and RemoveUser. I think the
422
- class names are relatively self explanatory but if you want more information
423
- consult the API documentation for a class.
424
-
425
- To use the task classes you construct a class instance, configure it as you may
426
- need and then execute it. Here's an example of going through this procedure to
427
- create a database backup...
428
-
429
- b = Backup.new('c:\database\work.fdb', 'c:\temp\work.bak')
430
- b.metadata_only = true
431
- b.execute(sm)
432
-
433
- The first list creates the new Backup object. The first parameter passed to this
434
- call is the path and name of the primary file of the database to be backed up
435
- (NOTE: All paths are relative to the database server). The second parameter is
436
- the path and name of the database backup file to be created. The second line
437
- sets an attribute on the class to indicate that only the metadata (i.e. it's
438
- schema but not it's data) for the specified database should be included in the
439
- backup. The final line begins the execution of the backup task on the database
440
- server. This will block until completion.
441
-
442
- Its also possible to execute a batch of tasks against a service manager. To do
443
- this you would accumulate the tasks to be executed and then pass them all at the
444
- same time to the ServiceManager#execute method, like so...
445
-
446
- t = Array.new
447
- t.push(Backup.new('c:\database\work.fdb', 'c:\temp\work.bak'))
448
- ...
449
- # Create more tasks here and add them to the array.
450
-
451
- sm.execute(*t)
452
-
453
- The tasks will be executed in the order they are specified to the ServiceManager
454
- object. For the example above this would mean in the order they were added to
455
- the array. For more details on the ServiceManager class and the various task
456
- classes please consult the API documentation.
1
+ = FireRuby Version 0.4.1
2
+ FireRuby is an extension for the Ruby programming language that provides access
3
+ to the Firebird open source RDBMS. The FireRuby library is release under the
4
+ Mozilla Public Licence version 1.1 and is free for commercial use.
5
+
6
+ ---
7
+
8
+ == Enhancements & Alterations
9
+
10
+ This release has been brought about as a direct result of efforts to get the
11
+ library working on a 64 bit platform. This process exposed some code of
12
+ questionable quality. All of the issues raised in getting a 64 bit build have
13
+ been addressed and it's only fair that the improvements obtained be passed on
14
+ to all platforms. Functionally nothing has changed since the last release and
15
+ the new version should replace the old with no problems.
16
+
17
+ === Bug Fixes
18
+
19
+ A number of bug fixes were implemented as part of the effort to get the library
20
+ working on a 64 bit platform. None of these had been raised as bugs against the
21
+ library so I have nothing specific to tick off.
22
+
23
+ === Backward Compatibility
24
+
25
+ Version 0.4.0 of the library made fundamental changes to functionality that was
26
+ available in earlier versions of the library. To help accommodate this change
27
+ elements were added to support backward compatibility. The relevant details are
28
+ listed here...
29
+
30
+ - Row objects were switched from keying on column names to keying on column
31
+ aliases. To revert to the older functionality assign a value of true to the
32
+ $FireRubySettings[:ALIAS_KEYS] global setting.
33
+
34
+ - DATE columns were switched from being returned as Time objects to be returned
35
+ as Date objects. To revert to the older functionality assign a value of true
36
+ to the $FireRubySettings[:DATE_AS_DATE] global setting.
37
+
38
+ One other point to note is that, as of version 0.4.0, Enumerable is included in
39
+ the Row and ResultSet classes.
40
+
41
+ === Issues
42
+
43
+ Nothing is perfect so this section outlines those issues that are known to
44
+ exist as of this release.
45
+
46
+ - The service manager functionality does not appear to work on the Mac OS X
47
+ platform. I don't believe that this is a problem in the FireRuby code as I
48
+ have tested the Firebird gbak utility with the -service option and it gives
49
+ the same result. If anyone knows this to be untrue or of a work around let me
50
+ know.
51
+
52
+ - The library currently does not support array columns. This may be implemented
53
+ for a later release depending on demand. No-one has asked for this so far so
54
+ I'm starting to think that people don't make much use of array columns.
55
+
56
+ - The library can be a bit touchy if you don't clean up after yourself. This
57
+ can result in a segmentation violation whenever your program stops if you've
58
+ left a ResultSet or Statement object unclosed. Check through your code to
59
+ insure that this isn't the case before contacting me about problems in this
60
+ line.
61
+
62
+ - The unit tests are currently set up on the assumption that the password for
63
+ your sysdba account is 'masterkey'. If this is not the case, or if you wish
64
+ to use an alternative user for testing, edit the TestSetup.rb file in the
65
+ unit test directory and update the entries there as appropriate. I should also
66
+ note that you may need to alter permissions on the test directory to run the
67
+ actual unit tests on Linux/Unix.
68
+
69
+ ---
70
+
71
+ == Credit Where Credit Is Due
72
+
73
+ Over its lifetime the FireRuby library has benefitted from input provided by a
74
+ number of individuals. This section acknowledges these inputs...
75
+
76
+ <b>Ken Kunz</b>: Ken has been a strong supporter of the library from early on and
77
+ has contributed through feedback, testing and suggestions. For some time he
78
+ produced and tested the Linux builds of the library.
79
+
80
+ <b>David Walthour</b>: David basically executed all of the work to generate the
81
+ 64 bit version of the library, along the way exposing some flaws in the code
82
+ (amazing what a bit of peer review can find!). David produced the 64 bit version
83
+ of the library gem.
84
+
85
+ <b>John Wood</b>: John currently builds and tests the Mac OS X version of the
86
+ library.
87
+
88
+ <b>Art Federov</b>: Art provided input on handling and testing character sets.
89
+
90
+ ---
91
+
92
+ == Installation & Usage
93
+
94
+ The library is provided as a gem and built for use with Ruby 1.8+. Testing
95
+ against an earlier release of Ruby has not been performed. Installation requires
96
+ the Ruby Gems package to be installed. Assuming that these installation criteria
97
+ have been met the library can be installed on Windows by executing a command
98
+ such as the following...
99
+
100
+ gem install fireruby-0.4.1-mswin32.gem
101
+
102
+ On the Mac OS X platform you may require super user privilege if your Ruby is
103
+ installed to the default location (i.e. /usr/local/lib). In this case you can
104
+ use the sudo command to make the installation like this...
105
+
106
+ sudo gem install fireruby-0.4.1-powerpc-darwin.gem
107
+
108
+ Once the gem installation is complete the FireRuby functionality can be accessed
109
+ in code with the usual gem style requires...
110
+
111
+ require 'rubygems'
112
+ require 'fireruby'
113
+
114
+ === Build Details
115
+
116
+ The FireRuby library is a Ruby extension written in C. The avoid build issues
117
+ binary versions are provided for a number of platforms, including...
118
+
119
+ - Windows: Built against a version of Ruby installed using the one-click
120
+ installer and using the freely available Microsoft development tools. This
121
+ version was compiled against version 1.5.2 of Firebird.
122
+
123
+ - Linux: Built on Ubuntu Linux (Breezy Badger) using a version of Ruby 1.8.2
124
+ installed via the Synaptic package manager. This package manager was also
125
+ used to make an installation of Firebird.
126
+
127
+ - Mac OS X: Build on version 10.4.3 of OS X against the 1.8.2 version of Ruby
128
+ that comes with the operating system. A framework installation of Firebird
129
+ version 1.5.1 was used to make the build.
130
+
131
+ Its possible to try and build the library on other platforms so I'll provide a
132
+ few details as to how to go about doing this. The first step is to download the
133
+ CVS tar ball from the Ruby Forge site and expand it into a local directory. This
134
+ will create a directory called fireruby. Change into this directory and then
135
+ into the fireruby/src subdirectory.
136
+
137
+ This directory contains a file called extconf.rb that is used to create the
138
+ make file used to build the library. The make file is created by executing this
139
+ file but before you do there are a number of parameters that you should be
140
+ aware of. The main one of these is --with-firebird-dir. This parameter is used
141
+ to indicate the whereabouts of the Firebird headers and libraries. The following
142
+ is an example of how this might be used...
143
+
144
+ ruby extconf.rb --with-firebird-dir=/usr/local/firebird
145
+
146
+ You may need to customise the path for your own Firebird installation. The path
147
+ specified should be a directory that contains subdirectories called 'lib' and
148
+ 'include'. The lib subdirectory should contain the fbclient shared library and
149
+ include should contain the ibase.h header file.
150
+
151
+ A note for Windows users. The library requires the free Microsoft C++ compiler,
152
+ the Windows SDK, the .NET SDK and nmake to build. If you have all of these
153
+ and Firebird installed to default locations then you can create a make file
154
+ using the mkmf.bat batch file in the src directory.
155
+
156
+ Once you have the make file you can attempt a library build using either make
157
+ (on Unix/Linux) or nmake (on Windows). If it builds successfully you can move
158
+ on to creating a gem file for installation. To do this, change into the ../gem
159
+ directory. In this directory you can do the following (on Windows)...
160
+
161
+ make_gem
162
+
163
+ ...or the following (on Unix/Linux)...
164
+
165
+ ruby make_gem.rb
166
+
167
+ This will create the gem file in the main fireruby directory. Install this and
168
+ execute the unit tests to check whether you're version is working.
169
+
170
+ === So How Do I Use It?
171
+
172
+ This section will provide some examples of usage for the the FireRuby classes.
173
+ Throughout the code the following set of assumptions are made.
174
+
175
+ - The user name and password that will be employed to attach to the database
176
+ are 'sysdba' and 'masterkey' respectively (the Firebird defaults).
177
+
178
+ - The databases attached to will all be local (i.e. they will all reside on the
179
+ same machine) as the test code.
180
+
181
+ A database, from the Firebird perspective, is made up of one or more files. From
182
+ a FireRuby perspective a user interaction with a database starts through the
183
+ Database class. This class provides facilities that allow for creating, dropping
184
+ and connecting to database instances. For example, to obtain a connection to a
185
+ database you would use something like the following...
186
+
187
+ require 'rubygems'
188
+ require 'fireruby'
189
+
190
+ include FireRuby
191
+
192
+ db = Database.new('./test.fdb')
193
+ c = db.connect('sysdba', 'masterkey')
194
+
195
+ This example starts by requiring the necessary files and including the FireRuby
196
+ module locally - later examples will not detail these lines but they are always
197
+ required to use the FireRuby code.
198
+
199
+ The first line of code after the include creates a new database object. This
200
+ process does not actually create the database file (see the Database#create
201
+ method API documentation if that is what you want to do), it simple creates an
202
+ abstract reference to a database. In creating the Database object we had to
203
+ provide a database specification string which identifies the database we want to
204
+ access. In this case we are specifying a database in the current working
205
+ directory called 'test.fdb'. See the Firebird documentation for details on the
206
+ structure of more complex database specifications.
207
+
208
+ The last line of code in the example given above opens a connection to the
209
+ database. In doing this we had to provide two parameters, the database user
210
+ name and password. These are required to gain access to the database.
211
+
212
+ A connection represents a conduit to a database and obtaining a connection is a
213
+ prerequisite to working with the database. The FireRuby library support having
214
+ multiple connections, to one or more databases, using one or more users, active
215
+ simultaneously. FireRuby represents a database connection through objects of the
216
+ Connection class. This class provides functionality to determine the current
217
+ state a database connection (open or closed) and for closing the connection.
218
+ Connections take up resources, both locally and on the database server and
219
+ should be explicitly closed when they are no longer required.
220
+
221
+ The connection class also provides a set of conveniences methods to allow for
222
+ the execution of SQL against a database. These methods, execute_immediate and
223
+ execute, represently two slightly different approaches to executing SQL against
224
+ the database. Refer to the API documentation for more information.
225
+
226
+ An advantage of using a relational database management system like Firebird is
227
+ that it provides transactions. A transaction represents a block of work that is
228
+ either all completed successful or none of it is applied. From the perspective
229
+ of the database this means that a series of steps that make changes to the
230
+ tables in the database can be wrapped in a transaction to insure that they
231
+ either all complete or that none of the changes are applied.
232
+
233
+ The FireRuby library represents a database transaction through instances of the
234
+ Transaction class. There are two ways of obtaining a Transaction using the
235
+ library, both requiring you to have an open database connection. The first way
236
+ is to construct a new Transaction object like so...
237
+
238
+ tx = Transaction.new(connection)
239
+
240
+ The Transaction constructor takes a single parameter which must be either a
241
+ Connection object or an array of Connection objects. If you pass an array of
242
+ Connection objects to this constructor then the Transaction created will apply
243
+ across all of the databases that the connections refer to, allowing you to
244
+ have transactional control of work that must utilise more than one database. The
245
+ second way to obtain a transaction is to simply request one from a Connection
246
+ object, like so.
247
+
248
+ tx = connection.start_transaction
249
+
250
+ In this case the transaction will only ever apply to one database, the one that
251
+ the connection relates to. This method also accepts a block, taking a single
252
+ parameter. The parameter passed to the block will be the transaction created.
253
+ In this case the lifetime of the transaction is delimited by the block. If the
254
+ block completes successfully then the work of the transaction will be committed
255
+ to the database. If the block raises an exception then the transactional work
256
+ will be rolled back.
257
+
258
+ When the block of work associated with a transaction is complete the user must
259
+ instruct the system to either apply the changes implemented by the work or to
260
+ discard them. This can be done by calling the commit or rollback methods of the
261
+ Transaction class respectively. Once a transaction has been committed or rolled
262
+ back it can no longer be used and should be discarded. Note that attempts to
263
+ close a connection that has an active transaction against it will fail, so one
264
+ of the commit or rollback methods should be explictly called in code. The
265
+ block technique detailed above helps protect against the failure to do this and
266
+ is a useful technique.
267
+
268
+ The Transaction object provides a number of other informational and utility
269
+ methods. Check the API documentation for this class for more information.
270
+
271
+ So we've looked at connections and transactions, but how do we actually do
272
+ something practical with the database. Well there are a number of possible
273
+ approaches that we can take to this. Both the Connection and Transaction classes
274
+ have convenience method for the execution of SQL statements and these are useful
275
+ for quick SQL. Where you want something that you can repeatedly reuse and,
276
+ optionally, pass parameters to then you need the Statement class.
277
+
278
+ The Statement class represents a SQL statement that has been validated and
279
+ prepared for execution. Here's an example of creating a SQL statement...
280
+
281
+ s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE', 3)
282
+
283
+ In this example we have created a Statement object that wraps a SQL select from
284
+ a table called MY_TABLE. The first parameter to the constructor is a Connection
285
+ object and the second is a Transaction, both mandatory. You may be thinking
286
+ 'why do I need a transaction here, I'm not changing anything?'. This is true
287
+ (well sort of) but it's a requirement of the underlying database system. This
288
+ is also the case for the final parameter to the constructor. The value 3 is
289
+ the SQL dialect to be used with the Statement. This exists for reason arising
290
+ from the move from closed source Interbase to open source Firebird. The
291
+ parameter should be given a value of between 1 and 3. If you're not sure what
292
+ this is and you're only using Firebird it's probably safe to use a value of
293
+ 3 here. Other values are for backward compatibility. Consult the Firebird and
294
+ Interbase documentation for more details.
295
+
296
+ Anyway, now that we have our Statement how do we use it? Well, the answer is
297
+ that we call once of the Statement objects execute methods. The one to be called
298
+ depends on whether the Statement requires parameters or not. What are parameters
299
+ you ask? Well, look at the following...
300
+
301
+ s = Statement.new(cxn, tx, 'SELECT * FROM MY_TABLE WHERE MYID = ?', 3)
302
+
303
+ Note that the SQL select for this Statement contains a '?'. This is a position
304
+ holder for a value that the statement expects to be provided later. A Statement
305
+ that wraps such a piece of SQL must be provided with the necessary parameters
306
+ to execute properly. Where a Statement object represents SQL that requires a
307
+ parameter then the execute_for method must be called, like this...
308
+
309
+ s.execute_for([25])
310
+
311
+ This code executes the SQL substituting the parameters from the array of data
312
+ passed to the function call. If a Statement object represents SQL that does not
313
+ require parameter values a call to the execute method will suffice, such as the
314
+ following...
315
+
316
+ s.execute
317
+
318
+ The execute methods for the Statement class, as with all of the execute methods
319
+ for the FireRuby library, have three potential return values. They will either
320
+ return an Integer, a ResultSet object or nil. A ResultSet object will only be
321
+ returned for SQL statements that constitute a query, irrespective of whether
322
+ that query returns any data. For all other SQL statements (inserts, updates and
323
+ deletes) the execute method will return a count of the number of rows affected
324
+ by the statement execution. For any other SQL statements the various execute
325
+ methods will return nil.
326
+
327
+ A ResultSet object represents a handle by which the data retrieved for a SQL
328
+ query can be accessed. While it's possible to obtain a ResultSet from one of the
329
+ execute methods on the Connection, Transaction or Statement classes it is more
330
+ efficient to create one directly. The constructor for the ResultSet class
331
+ accepts the same arguments as the constructor for the Statement class but will
332
+ throw an exception if the SQL statement specified is not a query.
333
+
334
+ Once we have obtained a ResultSet we can extract the rows of data for a query
335
+ from it. To fetch a row of data from a ResultSet object you call the fetch
336
+ method, like the following...
337
+
338
+ row = r.fetch
339
+
340
+ This fetches a single row of data for a query represented as a Row object (which
341
+ will be covered shortly). The ResultSet class also provides for iteration across
342
+ the contents of a result set by providing an each method. The block to the each
343
+ method will be passed the data for the ResultSet, a row at a time.
344
+
345
+ It should be noted that both the Statement and ResultSet objects hold resources
346
+ while they are active. They both possess close methods and these should be
347
+ explicitly called to release the associated resources. The exception to this
348
+ rule is for ResultSets. If you select all of the rows from a ResultSet then the
349
+ resources for the ResultSet are automatically released. It is still safe to call
350
+ close on such a ResultSet as this will not cause errors.
351
+
352
+ Okay, so you've gotten a row of data in the form of a Row object from your
353
+ ResultSet, how do we get the data out of it? Well, there are a number of ways
354
+ of doing this. You can treat the Row object like an array and dereference the
355
+ columns of data within the row like this...
356
+
357
+ value = row[1]
358
+
359
+ The index specified to the array dereference operator specifies the column that
360
+ you want the data for. Column indices start at 0. Alternatively you can treat
361
+ the Row object like a read only Hash object and use the column name to access
362
+ the data, like this...
363
+
364
+ value = row['MYID']
365
+
366
+ This is beneficial as it frees you from the constraint of knowing the ordering
367
+ of the columns within the row. For more information of the Row class please
368
+ consult the API documentation.
369
+
370
+ That covers the bulk of the SQL classes provided by the FireRuby library. The
371
+ two which haven't been touched upon are the Generator class and the Blob class.
372
+
373
+ The Generator class is a wrapper around the Firebird generator facility. A
374
+ generator, also known as a sequence, provides a means of creating a list of
375
+ numeric values in a way that is guaranteed to be thread and process safe. Used
376
+ properly generators can be employed to create unique sequences that make perfect
377
+ table keys. Consult the API documentation for more details on the Generator
378
+ class.
379
+
380
+ The Blob class is returned as part of the Row object data obtained from a
381
+ ResultSet. The class wraps the concept of a binary large object stored in the
382
+ database. Consult the API documentation for further information.
383
+
384
+ === Errors
385
+
386
+ Whenever a problem occurs within a FireRuby library class then it is likely that
387
+ a FireRubyException will be thrown. The FireRubyException class is the error
388
+ class used by the FireRuby library whenever it hits trouble. The class provides
389
+ a means of finding out a little more about what exactly has gone wrong. Again,
390
+ consult the API documentation for more details.
391
+
392
+ === Firebird Service Manager
393
+
394
+ The FireRuby library provides a set of class that provide for an interaction
395
+ with the Firebird service manager. This interaction allows for the execution of
396
+ tasks, such as the backing up of a database, on the database server. To execute
397
+ such tasks against the service manager for a Firebird instance you first need
398
+ to obtain a ServiceManager class instance. This can be done as follows...
399
+
400
+ sm = ServiceManager.new('localhost')
401
+
402
+ The constructor for the ServiceManager class takes a single parameter that is
403
+ the host name of the server running the Firebird instance. In the example above
404
+ this would be a local machine but could be any machine that can be reached over
405
+ the network (NOTE: although Firebird supports a number of underlying transport
406
+ protocols in accessing a service manager currently only TCP/IP is supported for
407
+ the FireRuby library).
408
+
409
+ The next step in executing service manager tasks involves connecting your
410
+ ServiceManager object to the service manager for a Firebird instance. To do this
411
+ you must supply a user name and password. The user name and password used must
412
+ be a user that exists on the Firebird instance. The user you connect as can
413
+ affect the access to services that you receive. For example, to connect as the
414
+ database administrator you might do the following...
415
+
416
+ sm.connect('sysdba', 'masterkey')
417
+
418
+ Assuming that this succeeds you are now ready to execute tasks through your
419
+ ServiceManager object. Within the FireRuby library individual task are broken
420
+ out into separate classes. For this release (0.4.1) there are four task classes
421
+ provided in the library - Backup, Restore, AddUser and RemoveUser. I think the
422
+ class names are relatively self explanatory but if you want more information
423
+ consult the API documentation for a class.
424
+
425
+ To use the task classes you construct a class instance, configure it as you may
426
+ need and then execute it. Here's an example of going through this procedure to
427
+ create a database backup...
428
+
429
+ b = Backup.new('c:\database\work.fdb', 'c:\temp\work.bak')
430
+ b.metadata_only = true
431
+ b.execute(sm)
432
+
433
+ The first list creates the new Backup object. The first parameter passed to this
434
+ call is the path and name of the primary file of the database to be backed up
435
+ (NOTE: All paths are relative to the database server). The second parameter is
436
+ the path and name of the database backup file to be created. The second line
437
+ sets an attribute on the class to indicate that only the metadata (i.e. it's
438
+ schema but not it's data) for the specified database should be included in the
439
+ backup. The final line begins the execution of the backup task on the database
440
+ server. This will block until completion.
441
+
442
+ Its also possible to execute a batch of tasks against a service manager. To do
443
+ this you would accumulate the tasks to be executed and then pass them all at the
444
+ same time to the ServiceManager#execute method, like so...
445
+
446
+ t = Array.new
447
+ t.push(Backup.new('c:\database\work.fdb', 'c:\temp\work.bak'))
448
+ ...
449
+ # Create more tasks here and add them to the array.
450
+
451
+ sm.execute(*t)
452
+
453
+ The tasks will be executed in the order they are specified to the ServiceManager
454
+ object. For the example above this would mean in the order they were added to
455
+ the array. For more details on the ServiceManager class and the various task
456
+ classes please consult the API documentation.