beezwax 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ begin
11
11
  gem.homepage = "http://github.com/plardin/beezwax"
12
12
  gem.authors = ["Patrick Lardin"]
13
13
  gem.add_development_dependency "ffi", ">= 0.6.3"
14
+ gem.files.include %w(lib/btrieve/*.rb)
14
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
16
  end
16
17
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
@@ -0,0 +1,451 @@
1
+ module BtrCodes
2
+ PK_KEYS=[:"kid - date",:"kid - time",:"kid - user",:"kid - mult",:"kid - comm"]
3
+ OK = 0
4
+ OPEN = 0
5
+ CLOSE = 1
6
+ INSERT = 2
7
+ UPDATE = 3
8
+ DELETE = 4
9
+ GET_EQUAL = 5
10
+ GET_NEXT = 6
11
+ GET_GREATER_THAN_OR_EQUAL = 9
12
+ SET_DIRECTORY = 17
13
+ BEGIN_TRANSACTION = 19
14
+ END_TRANSACTION = 20
15
+ ABORT_TRANSACTION = 21
16
+ STEP_NEXT = 24
17
+ EOF = 9
18
+ POS_BLOCK_SIZE = 128
19
+ NULL_KEY = 0x00
20
+ NULL_BUFFER = ''
21
+ NORMAL_MODE = 0x00
22
+ ACCELERATED_MODE = 0xFF
23
+ READ_ONLY_MODE = 0xFE
24
+ VERIFY_MODE = 0xFD
25
+ EXCLUSIVE_MODE = 0xFC
26
+ LOCAL_NORMAL_MODE = 0x06
27
+ LOCAL_ACCELERATED_MODE = 0x07
28
+ LOCAL_READ_ONLY_MODE = 0x08
29
+ LOCAL_EXCLUSIVE_MODE = 0x08
30
+ REMOTE_NORMAL_MODE = 0x63
31
+ REMOTE_ACCELERATED_MODE = 0x64
32
+ REMOTE_READ_ONLY_MODE = 0x65
33
+ REMOTE_EXCLUSIVE_MODE = 0x67
34
+ NO_CURRENCY_CHANGE = 0xFF
35
+ MAX_DATATYPE = 200
36
+
37
+ EXCEPTION_MESSAGES = {
38
+ 1=>"The operation parameter is invalid.",
39
+ 2=>"The application encountered an I/O error.",
40
+ 3=>"The file is not open.",
41
+ 4=>"The application cannot find the key value.",
42
+ 5=>"The record has a key field containing a duplicate key value.",
43
+ 6=>"The key number parameter is invalid.",
44
+ 7=>"The key number has changed.",
45
+ 8=>"The current positioning is invalid.",
46
+ 9=>"The operation encountered the end-of-file.",
47
+ 10=>"The key field is not modifiable.",
48
+ 11=>"The specified filename is invalid.",
49
+ 12=>"The MicroKernel cannot find the specified file.",
50
+ 13=>"The MicroKernel could not open the extension file for an extended file.",
51
+ 14=>"The MicroKernel cannot create or open the pre-image file.",
52
+ 15=>"The application encountered an I/O error during pre-imaging.",
53
+ 16=>"The application encountered an expansion error.",
54
+ 18=>"The disk is full.",
55
+ 19=>"The application encountered an unrecoverable error.",
56
+ 20=>"The MicroKernel or Btrieve Requester is inactive.",
57
+ 21=>"The key buffer parameter is too short.",
58
+ 22=>"The data buffer parameter is too short.",
59
+ 23=>"The position block parameter is not 128 bytes long.",
60
+ 24=>"The page size or data buffer size is invalid.",
61
+ 25=>"The application cannot create the specified file.",
62
+ 26=>"The number of keys specified is invalid.",
63
+ 27=>"The key position is invalid.",
64
+ 28=>"The record length is invalid.",
65
+ 29=>"The key length is invalid.",
66
+ 30=>"The file specified is not a MicroKernel file.",
67
+ 31=>"The file is already extended.",
68
+ 32=>"The file cannot be extended.",
69
+ 33=>"The MicroKernel cannot unload.",
70
+ 34=>"The specified extension name is invalid.",
71
+ 35=>"The application encountered a directory error.",
72
+ 37=>"Another transaction is active.",
73
+ 38=>"The MicroKernel encountered a transaction control file I/O error.",
74
+ 39=>"A Begin Transaction operation must precede an End/Abort Transaction operation.",
75
+ 40=>"The file access request exceeds the maximum number of files allowed.",
76
+ 41=>"The MicroKernel does not allow the attempted operation.",
77
+ 42=>"A file previously opened in Accelerated mode was not closed.",
78
+ 43=>"The specified record address is invalid.",
79
+ 44=>"The specified key path is invalid.",
80
+ 45=>"The specified key flags are invalid.",
81
+ 46=>"Access to the requested file is denied.",
82
+ 47=>"The number of files opened exceeds the maximum allowed.",
83
+ 48=>"The alternate collating sequence definition is invalid.",
84
+ 49=>"The extended key type is invalid.",
85
+ 50=>"The file owner is already set.",
86
+ 51=>"The owner name is invalid.",
87
+ 52=>"An error occurred while writing to the cache.",
88
+ 53=>"The language interface version is invalid.",
89
+ 54=>"The variable-length portion of the record is corrupt.",
90
+ 55=>"The application specified an invalid attribute for an AUTOINCREMENT key.",
91
+ 56=>"An index is incomplete.",
92
+ 57=>"An expanded memory error occurred.",
93
+ 58=>"The compression buffer length is too short.",
94
+ 59=>"The specified file already exists.",
95
+ 60=>"The specified reject count has been reached.",
96
+ 61=>"The work space is too small.",
97
+ 62=>"The descriptor is incorrect.",
98
+ 63=>"The data buffer parameter specified on an Insert Extended operation is invalid.",
99
+ 64=>"The filter limit has been reached.",
100
+ 65=>"The field offset is incorrect.",
101
+ 66=>"The maximum number of open databases has been exceeded.",
102
+ 67=>"The MicroKernel cannot open the SQL data dictionary files.",
103
+ 68=>"The MicroKernel cannot perform the RI Delete Cascade operation.",
104
+ 69=>"The Delete operation specified a file that is damaged.",
105
+ 71=>"There is a violation of the RI definitions.",
106
+ 72=>"The MicroKernel cannot open the RI referenced file.",
107
+ 73=>"The RI definition is out of sync.",
108
+ 74=>"The MicroKernel aborted the transaction.",
109
+ 76=>"There is a conflict on the referenced file.",
110
+ 77=>"The application encountered a wait error.",
111
+ 78=>"The MicroKernel detected a deadlock condition.",
112
+ 79=>"A programming error occurred.",
113
+ 80=>"The MicroKernel encountered a record-level conflict.",
114
+ 81=>"The MicroKernel encountered a lock error.",
115
+ 82=>"The MicroKernel lost positioning.",
116
+ 83=>"The MicroKernel attempted to update or delete a record that was read outside the transaction.",
117
+ 84=>"The record or page is locked.",
118
+ 85=>"The file is locked.",
119
+ 86=>"The file table is full.",
120
+ 87=>"The handle table is full.",
121
+ 88=>"The application encountered an incompatible mode error.",
122
+ 89=>"A name error occurred.",
123
+ 90=>"The redirected device table is full.",
124
+ 91=>"The application encountered a server error.",
125
+ 92=>"The transaction table is full.",
126
+ 93=>"The record lock types are incompatible.",
127
+ 94=>"The application encountered a permission error.",
128
+ 95=>"The session is no longer valid.",
129
+ 96=>"A communications environment error occurred.",
130
+ 97=>"The data buffer is too small.",
131
+ 98=>"The MicroKernel detected an internal transaction error.",
132
+ 99=>"The Btrieve Requester is unable to access the NetWare Runtime server.",
133
+ 100=>"No cache buffers are available.",
134
+ 101=>"Insufficient operating system memory is available.",
135
+ 102=>"Insufficient stack space is available.",
136
+ 103=>"The chunk offset is too big.",
137
+ 104=>"The MicroKernel does not recognize the locale.",
138
+ 105=>"The file cannot be created with Variable-tail Allocation Tables (VATs).",
139
+ 106=>"The MicroKernel cannot perform a Get Next Chunk operation.",
140
+ 107=>"The application attempted to perform a chunk operation on a pre-v6.0 file.",
141
+ 109=>"An unknown error was encountered either creating or accessing a semaphore.",
142
+ 110=>"The MicroKernel cannot access the archival logging configuration file.",
143
+ 111=>"The specified filename was not found in the archival logging configuration file.",
144
+ 112=>"The specified file is in use by another client.",
145
+ 113=>"The MicroKernel cannot find the archival log for the specified file.",
146
+ 114=>"The archival log for the specified file is invalid.",
147
+ 115=>"The MicroKernel cannot access the archival logging dump file.",
148
+ 116=>"The file is owned by another Microkernel engine acting as a Gateway.",
149
+ 130=>"The MicroKernel ran out of system locks.",
150
+ 132=>"The file has reached its size limit.",
151
+ 133=>"More than 5 concurrent users attempted to access the same data file.",
152
+ 134=>"The MicroKernel cannot read the International Sorting Rule.",
153
+ 135=>"The specified ISR table is corrupt or otherwise invalid.",
154
+ 136=>"The MicroKernel cannot find the specified Alternate Collating Sequence in the file.",
155
+ 138=>"The NULL indicator position is invalid.",
156
+ 139=>"The MicroKernel has detected an unacceptable value in the key number.",
157
+ 140=>"The savepoint ID is invalid.",
158
+ 143=>"The MicroKernel cannot allow unauthorized access to files in a secure MicroKernel database.",
159
+ 146=>"Duplicate system key.",
160
+ 147=>"The log segment is missing.",
161
+ 148=>"A roll forward error occurred.",
162
+ 149=>"SQL Trigger.",
163
+ 161=>"The maximum number of user count licenses has been reached.",
164
+ 162=>"The client table is full. Try increasing the number of Active Clients in the MicroKernel Database Engine System Resource setting.",
165
+ 163=>"The NULL indicator cannot be the last segment.",
166
+ 1001=>"The lock parameter is out of range.",
167
+ 1002=>"A memory allocation error occurred.",
168
+ 1003=>"An invalid memory size parameter was specified.",
169
+ 1004=>"A page size error occurred.",
170
+ 1005=>"The pre-image or lock file drive parameter is invalid.",
171
+ 1006=>"The pre-image buffer parameter is out of range.",
172
+ 1007=>"The files parameter is out of range.",
173
+ 1008=>"The initialization parameter is invalid.",
174
+ 1009=>"The transaction filename parameter is invalid.",
175
+ 1010=>"An error occurred during the access of the transaction control file.",
176
+ 1011=>"The compression buffer parameter is out of range.",
177
+ 1012=>"Invalid /n: option.",
178
+ 1013=>"The task list is full.",
179
+ 1015=>"One of the pointer parameters passed to the MicroKernel is invalid.",
180
+ 1016=>"The MicroKernel is already initialized.",
181
+ 1017=>"The Btrieve Requester is unable to find the resource file WBTRVRES.DLL.",
182
+ 1018=>"The application attempted to call the MicroKernel from a Btrieve callback function.",
183
+ 1019=>"The MicroKernel cancelled the current Btrieve operation at the request of the application's Btrieve callback function.",
184
+ 1020=>"Btrieve Requester Interface communications error.",
185
+ 1021=>"The MicroKernel failed to initialize.",
186
+ 1022=>"The MicroKernel is shutting down.",
187
+ 2000=>"Internal error.",
188
+ 2001=>"The memory allocation is insufficient.",
189
+ 2003=>"The Requester does not allow local access to the specified file.",
190
+ 2004=>"SPX is not installed.",
191
+ 2005=>"An incorrect version of SPX is installed.",
192
+ 2006=>"There is no available SPX connection.",
193
+ 2007=>"A pointer parameter is invalid.",
194
+ 2008=>"Router cannot find engine.",
195
+ 2009=>"Cannot load MicroKernel Router component.",
196
+ 2010=>"Thunk not possible - the Win32 MicroKernel router could not be found or is incompatible.",
197
+ 2011=>"Btrieve requester resource DLL not loaded.",
198
+ 2012=>"The Btrieve requester encountered an operating system error.",
199
+ 2200=>"XLT Winsock Error.",
200
+ 2201=>"XLT RPC Error.",
201
+ 2300=>"No more database names are defined.",
202
+ 2301=>"The database name is invalid.",
203
+ 2302=>"Invalid buffer length.",
204
+ 2303=>"The database name must be unique; the specified database name already exists.",
205
+ 2304=>"The database type is invalid.",
206
+ 2305=>"The specified path for data dictionary or data file locations is invalid.",
207
+ 2306=>"DBNAMES.CFG could not be updated.",
208
+ 2307=>"Cannot open DBNAMES.CFG file.",
209
+ 2308=>"The specified RI flag is invalid.",
210
+ 2309=>"The database is in use.",
211
+ 2312=>"The bound database cannot share table data files.",
212
+ 2313=>"The bound database cannot share data dictionary files.",
213
+ 2314=>"Cannot create DBNAMES.CFG file.",
214
+ 2316=>"Cannot create DDF files for the bound database.",
215
+ 2324=>"Data dictionary files are not bound.",
216
+ 2325=>"Data dictionary files are already bound.",
217
+ 2326=>"Data dictionary files are bound, but do not need to be bound.",
218
+ 2329=>"Data file for a table is not bound.",
219
+ 2330=>"Data file for a table is bound, but does not need to be bound.",
220
+ 2331=>"Not allowed to change data dictionary location and change name at the same time.",
221
+ 2332=>"Not allowed to bind database and change name at the same time.",
222
+ 2333=>"Not allowed to unbind database and change name at the same time.",
223
+ 2334=>"Not allowed to create a data dictionary files and change name at the same time.",
224
+ 2335=>"Not allowed to change data locations and change name at the same time.",
225
+ 2336=>"Not allowed to change data dictionary location and bind database at the same time.",
226
+ 2337=>"Not allowed to change data dictionary location and unbind database at the same time.",
227
+ 2338=>"Not allowed to change the dictionary location and create dictionary files at the same time.",
228
+ 2339=>"Not allowed to create data dictionary files and bind database at the same time.",
229
+ 2340=>"Not allowed to create data dictionary and unbind database at the same time.",
230
+ 2341=>"Not allowed to bind database and change data locations at the same time.",
231
+ 2342=>"Not allowed to unbind database and change data locations at the same time.",
232
+ 2343=>"Named database general error.",
233
+ 3000=>"The MicroKernel router encountered a memory allocation error.",
234
+ 3001=>"Local access is unavailable to the MicroKernel router.",
235
+ 3002=>"The MicroKernel router resource DLL is unavailable.",
236
+ 3003=>"The MicroKernel router detected an incompatible network component.",
237
+ 3004=>"The MicroKernel is not responding to the MicroKernel router.",
238
+ 3005=>"The MicroKernel router encountered an operating system error.",
239
+ 3006=>"The MicroKernel router detected an invalid session.",
240
+ 3008=>"Invalid configuration for MicroKernel router.",
241
+ 3009=>"NETinterface.DLL is not loaded.",
242
+ 3010=>"NetWare API DLLs are not loaded.",
243
+ 3011=>"Thunk not possible - the Win32 MicroKernel router could not be found or is incompatible.",
244
+ 3012=>"Local engine is not accessible to the MicroKernel router.",
245
+ 3013=>"The remote engine is inaccessible to the MicroKernel router because the networking component is not loaded.",
246
+ 3014=>"The MicroKernel router cannot find an engine.",
247
+ 3015=>"The MicroKernel router encountered an initialization error.",
248
+ 3016=>"The MicroKernel router encountered an internal error.",
249
+ 3017=>"Data buffer of the local engine is too small.",
250
+ 3018=>"The file is already closed.",
251
+ 3019=>"The MicroKernel router encountered a semaphore error.",
252
+ 3020=>"An error occurred while loading the MicroKernel.",
253
+ 3021=>"The MicroKernel router received a badly formatted data packet.",
254
+ 3022=>"The MicroKernel router could not send the request to the remote engine because the specified data buffer length resulted in a data packet object that is too large.",
255
+ 3023=>"The task table of the MicroKernel router is full.",
256
+ 3025=>"Cannot load IDS client requester.",
257
+ 3026=>"Incompatible IDS client requester.",
258
+ 3027=>"Connection failure to IDS target server.",
259
+ 3028=>"Login failure to IDS target server.",
260
+ 3029=>"IDS Not Allowed.",
261
+ 3030=>"Remote access not allowed.",
262
+ 3103=>"Server name not found by Pervasive Network Services Layer.",
263
+ 3104=>"The Pervasive Network Services Layer encountered a permission error.",
264
+ 3105=>"No available transport protocol for the Pervasive Network Services Layer.",
265
+ 3106=>"The Pervasive Network Services Layer encountered a connection failure.",
266
+ 3107=>"The Pervasive Network Services Layer is out of memory.",
267
+ 3108=>"The Pervasive Network Services Layer detected an invalid session.",
268
+ 3110=>"The network layer is not connected.",
269
+ 3111=>"Failure during send to the target server.",
270
+ 3112=>"Failure during receive from the target server.",
271
+ 3114=>"The routing table of the Pervasive Network Services Layer is full.",
272
+ 3115=>"Pervasive Network Services Layer encountered a transport failure.",
273
+ 3119=>"No authentication context is available.",
274
+ 3124=>"Pervasive Network Services Layer task table is full.",
275
+ 3125=>"The Pervasive Network Services Layer was unable to resolve the Novell Directory Services name into a NetWare server name.",
276
+ 3126=>"The Pervasive Network Services Layer was unable to resolve the given filename into a valid path.",
277
+ 3127=>"Failure during send to the IDS target server.",
278
+ 3128=>"Failure during receive from the IDS target server.",
279
+ 3131=>"Pervasive Network Services Layer encountered an error while reconnecting.",
280
+ 4083=>"Component not loaded.",
281
+ 4086=>"An internal error occurred. Utilities Requester receive size too small.",
282
+ 7002=>"The key number is invalid.",
283
+ 7003=>"The User Count Manager cannot write to the key file.",
284
+ 7004=>"The User Count Manager cannot write to the specified file.",
285
+ 7005=>"The User Count Manager cannot read the key file.",
286
+ 7006=>"The User Count Manager cannot read the specified file.",
287
+ 7007=>"The User Count Manager encountered a premature end of file.",
288
+ 7008=>"The User Count Manager cannot open the specified file.",
289
+ 7009=>"The User Count Manager cannot modify the specified file.",
290
+ 7010=>"The User Count Manager cannot find the specified file.",
291
+ 7011=>"You cannot increase the user count with the same key number twice.",
292
+ 7012=>"The key file integrity has been compromised.",
293
+ 7013=>"The key type is invalid.",
294
+ 7014=>"The User Count Manager is already in use. Try again later.",
295
+ 7016=>"The User Count Manager cannot read the specified file; the file may be corrupt.",
296
+ 7017=>"UCMGR-310: Serial number synchronization error. Unable to find valid stamp area.",
297
+ 7018=>"UCMGR-311: Serial number synchronization error. Invalid stamp area read.",
298
+ 7019=>"UCMGR-312: Serial number synchronization error. One or more stamp numbers read do not match.",
299
+ 7020=>"UCMGR-313: Serial number synchronization error. Could not write stamp number to one of the files. Make sure the database engine is not loaded and that you have access rights to the files.",
300
+ 7021=>"UCMGR-314: Serial number synchronization error. Files have not been stamped and the user count key file exists.",
301
+ 7022=>"UCMGR-315: Serial number synchronization error. The key file stamp number does not match the stamp number in the other files.",
302
+ 7023=>"UCMGR-316: Serial number synchronization error. Files have been stamped but the user count key file does not exist. If you have made a backup copy of your user count key file (<plat>UCMGR.SYS), please restore it to the database engine directory.",
303
+ 7026=>"The User Count Manager cannot find the diskette key file: UCMGR.KEY.",
304
+ 7028=>"The diskette key has already been applied.",
305
+ 7029=>"The User Count Manager cannot read the diskette key file.",
306
+ 7030=>"DOS partition services are not present.",
307
+ 7031=>"The User Count Manager cannot copy the diskette key file.",
308
+ 7032=>"The User Count Manager cannot open the diskette key file.",
309
+ 7033=>"The User Count Manager cannot write to the diskette key file.",
310
+ 7035=>"The serial numbers do not match.",
311
+ 7036=>"The serial numbers do not match.",
312
+ 7037=>"The serial numbers do not match.",
313
+ 7038=>"The serial numbers do not match.",
314
+ 7039=>"The User Count Manager cannot delete the specified file.",
315
+ 7040=>"The User Count Manager cannot rename the specified file.",
316
+ 7041=>"The User Count Manager is not initialized.",
317
+ 7042=>"The User Count Manager cannot determine the platform.",
318
+ 7046=>"The User Count Manager cannot migrate Btrieve user count.",
319
+ 7048=>"The operation is invalid for Btrieve v6.1x migration.",
320
+ 7049=>"User count license is already unlimited for this product.",
321
+ 7050=>"Incorrect user count resource DLL.",
322
+ 7051=>"Incorrect major version of user count resource DLL.",
323
+ 7052=>"Incorrect minor version of user count resource DLL.",
324
+ 7053=>"Incorrect patch number for user count resource DLL.",
325
+ 7054=>"License key does not match product version.",
326
+ 7061=>"Your Pervasive Database engine expired on <date>. Please contact Pervasive Software for more information.",
327
+ 7062=>"Your Pervasive Database engine will expire on <date> because you have a temporary license key.",
328
+ 7063=>"Your user count license limit has been reached.",
329
+ 7064=>"The license you tried to remove does not exist.",
330
+ 7065=>"The product for which you requested the user count license does not exist.",
331
+ 8001=>"The Services DLL encountered an error while allocating memory.",
332
+ 8002=>"The component ID string was not found.",
333
+ 8003=>"Thunk path is not accessible to the Services DLL.",
334
+ 8005=>"Interface not initialized.",
335
+ 8006=>"The specified component was not found.",
336
+ 8007=>"Error retrieving Win32 version information.",
337
+ 8008=>"Information mismatch in component ID.",
338
+ 8009=>"Required information missing in component ID.",
339
+ 8010=>"Error while opening a file to retrieve component ID.",
340
+ 8012=>"Required information for binding rule is missing.",
341
+ 8013=>"Error locating a component.",
342
+ 8016=>"Invalid instance specified.",
343
+ 8017=>"Invalid version information structure.",
344
+ 8018=>"Item not found by Services DLL.",
345
+ 8019=>"Library not accepting interface requests.",
346
+ 8020=>"Error loading component.",
347
+ 8022=>"Component not initialized.",
348
+ 8023=>"Invalid filename passed to Services DLL.",
349
+ 8024=>"Invalid function name.",
350
+ 8027=>"Required attribute missing in component ID.",
351
+ 8030=>"Return buffer too small for information.",
352
+ 8032=>"Component ID is invalid.",
353
+ 8035=>"Invalid interface for NetWare platform.",
354
+ 8039=>"Invalid operating system handle specified.",
355
+ 8040=>"CRC check on component ID failed.",
356
+ 8500=>"An error occurred during the Smart Components initialization.",
357
+ 8502=>"An error occurred when trying to locate W3UPIXYY.DLL.",
358
+ 8503=>"An invalid W3UPIXYY.DLL has been found.",
359
+ 8504=>"An error occurred when trying to create system semaphore.",
360
+ 8505=>"An initialization error occurred when trying to establish a session with the workstation engine.",
361
+ 8506=>"A fatal error occurred when loading the MicroKernel.",
362
+ 8507=>"No valid session was found.",
363
+ 8508=>"An error occurred when attempting to enable Btrieve access.",
364
+ 8509=>"A timeout occurred during the initialization of the MicroKernel.",
365
+ 8510=>"A fatal error occurred when loading the Scalable SQL engine.",
366
+ 8511=>"An error occurred when attempting to enable SQL access.",
367
+ 8512=>"A timeout occurred during the initialization of the Scalable SQL engine.",
368
+ 8513=>"An error occurred when disabling Btrieve access.",
369
+ 8514=>"An error occurred when unloading the MicroKernel.",
370
+ 8515=>"An error occurred when disabling SQL access.",
371
+ 8516=>"An error occurred when unloading the Scalable SQL engine.",
372
+ 8517=>"An error occurred when closing the session with the workstation engine.",
373
+ 8518=>"An error occurred when attempting to allocate system memory.",
374
+ 8519=>"A fatal error occurred when loading the SRDE.",
375
+ 8520=>"A timeout occurred during the initialization of the SRDE module.",
376
+ 8521=>"An error occurred when unloading the SRDE module.",
377
+ 8590=>"An error occurred in the database manager while initializing Smart Components Manager.",
378
+ 8591=>"The database manager is already loaded.",
379
+ 8592=>"Insufficient memory to load the database manager.",
380
+ 8593=>"An error occurred while the database manager was creating a system thread.",
381
+ 8594=>"Engine cannot be restarted.",
382
+ 10000=>"You have been unexpectedly disconnected from the server.",
383
+ 10001=>"You have been unexpectedly disconnected from the server.",
384
+ 10002=>"You have been unexpectedly disconnected from the server.",
385
+ 10003=>"You have been unexpectedly disconnected from the server.",
386
+ 10004=>"You have been unexpectedly disconnected from the server.",
387
+ 10005=>"You have been unexpectedly disconnected from the server.",
388
+ 10006=>"You have been unexpectedly disconnected from the server.",
389
+ 10007=>"You have been unexpectedly disconnected from the server.",
390
+ 10008=>"You have been unexpectedly disconnected from the server.",
391
+ 10009=>"You have been unexpectedly disconnected from the server.",
392
+ 10010=>"You have been unexpectedly disconnected from the server.",
393
+ 10011=>"You have been unexpectedly disconnected from the server.",
394
+ 10012=>"You have been unexpectedly disconnected from the server.",
395
+ 10013=>"You have been unexpectedly disconnected from the server.",
396
+ 10014=>"You have been unexpectedly disconnected from the server.",
397
+ 10015=>"You have been unexpectedly disconnected from the server.",
398
+ 10016=>"You have been unexpectedly disconnected from the server.",
399
+ 10017=>"You have been unexpectedly disconnected from the server.",
400
+ 10018=>"You have been unexpectedly disconnected from the server.",
401
+ 10019=>"You have been unexpectedly disconnected from the server.",
402
+ 10020=>"You have been unexpectedly disconnected from the server.",
403
+ 10021=>"You have been unexpectedly disconnected from the server.",
404
+ 10022=>"You have been unexpectedly disconnected from the server.",
405
+ 10023=>"You have been unexpectedly disconnected from the server.",
406
+ 10024=>"You have been unexpectedly disconnected from the server.",
407
+ 10025=>"You have been unexpectedly disconnected from the server.",
408
+ 10026=>"You have been unexpectedly disconnected from the server.",
409
+ 10027=>"You have been unexpectedly disconnected from the server.",
410
+ 10028=>"You have been unexpectedly disconnected from the server.",
411
+ 10029=>"You have been unexpectedly disconnected from the server.",
412
+ 10030=>"You have been unexpectedly disconnected from the server.",
413
+ 10031=>"You have been unexpectedly disconnected from the server.",
414
+ 10032=>"You have been unexpectedly disconnected from the server.",
415
+ 10033=>"You have been unexpectedly disconnected from the server.",
416
+ 10034=>"You have been unexpectedly disconnected from the server.",
417
+ 10035=>"You have been unexpectedly disconnected from the server.",
418
+ 10036=>"You have been unexpectedly disconnected from the server.",
419
+ 10037=>"You have been unexpectedly disconnected from the server.",
420
+ 10038=>"You have been unexpectedly disconnected from the server.",
421
+ 10039=>"You have been unexpectedly disconnected from the server.",
422
+ 10040=>"You have been unexpectedly disconnected from the server.",
423
+ 10041=>"You have been unexpectedly disconnected from the server.",
424
+ 10042=>"You have been unexpectedly disconnected from the server.",
425
+ 10043=>"You have been unexpectedly disconnected from the server.",
426
+ 10044=>"You have been unexpectedly disconnected from the server.",
427
+ 10045=>"You have been unexpectedly disconnected from the server.",
428
+ 10046=>"You have been unexpectedly disconnected from the server.",
429
+ 10047=>"You have been unexpectedly disconnected from the server.",
430
+ 10048=>"You have been unexpectedly disconnected from the server.",
431
+ 10049=>"You have been unexpectedly disconnected from the server.",
432
+ 10050=>"You have been unexpectedly disconnected from the server.",
433
+ 10051=>"You have been unexpectedly disconnected from the server.",
434
+ 10052=>"You have been unexpectedly disconnected from the server.",
435
+ 10053=>"You have been unexpectedly disconnected from the server.",
436
+ 10054=>"You have been unexpectedly disconnected from the server.",
437
+ 10055=>"You have been unexpectedly disconnected from the server.",
438
+ 10056=>"You have been unexpectedly disconnected from the server.",
439
+ 10057=>"You have been unexpectedly disconnected from the server.",
440
+ 10058=>"You have been unexpectedly disconnected from the server.",
441
+ 10059=>"You have been unexpectedly disconnected from the server.",
442
+ 10060=>"You have been unexpectedly disconnected from the server.",
443
+ 10061=>"You have been unexpectedly disconnected from the server.",
444
+ 10062=>"You have been unexpectedly disconnected from the server.",
445
+ 10063=>"You have been unexpectedly disconnected from the server.",
446
+ 10064=>"You have been unexpectedly disconnected from the server.",
447
+ 10065=>"Connection attempt timed out."
448
+ }
449
+
450
+ end
451
+
@@ -0,0 +1,56 @@
1
+ require 'ffi'
2
+ require_relative 'btrieve_const'
3
+
4
+ module Btrieve
5
+ extend FFI::Library
6
+ include BtrCodes
7
+
8
+ if( RUBY_PLATFORM.match('mswin|mingw|cygwin'))
9
+ ffi_lib 'w3btrv7.dll'
10
+ elsif(RUBY_PLATFORM.match('linux'))
11
+ ffi_lib 'libpsqlmif.so'
12
+ else
13
+ raise Exception.new("Unknown RUBY_PLATFORM #{RUBY_PLATFORM} to perform FFI calls into PSQL.")
14
+ end
15
+
16
+ attach_function :BTRCALLID, [:int, :pointer, :pointer, :pointer, :pointer, :uchar, :uchar, :pointer], :int
17
+
18
+ def btr_op(session, ops, pos_buffer, data_buffer, key_buffer, key_number, valid_return_codes=[0])
19
+ data_length = [data_buffer.size].pack('L')
20
+ key_length = key_buffer.size
21
+ result_code = BTRCALLID(ops, pos_buffer, data_buffer, data_length, key_buffer, key_length, key_number, session.client_id)
22
+ unless valid_return_codes.include?(result_code)
23
+ p "ops=#{ops} data_buffer.length=#{data_buffer.length} key_buffer=#{key_buffer}, key_buffer.length=#{key_buffer.length}, key_number=#{key_number}, session.client_id=#{session.client_id}"
24
+ raise Exception.new("PSQL Exception Code #{result_code} - #{EXCEPTION_MESSAGES[result_code]}")
25
+ end
26
+ result_code
27
+ end
28
+
29
+ def self.create_string_buffer(size)
30
+ 0.chr*(size)
31
+ end
32
+ end
33
+
34
+ module Timer
35
+ def timer(&block)
36
+ start_time = Time.now
37
+ yield
38
+ end_time = Time.now
39
+ end_time - start_time
40
+ end
41
+
42
+ def timer2(out=nil, &block)
43
+ start_time = Time.now
44
+ out = yield out
45
+ [Time.now - start_time, out]
46
+ end
47
+ end
48
+
49
+ require_relative 'btrieve_session'
50
+ require_relative 'btrieve_table'
51
+ require_relative 'btrieve_schema'
52
+ require_relative 'btrieve_meta'
53
+ require_relative 'btrieve_record'
54
+ require_relative 'btrieve_model'
55
+ require_relative 'fos_code'
56
+
@@ -0,0 +1,63 @@
1
+ class BtrieveMeta
2
+ include Btrieve
3
+
4
+ TO_FOS_DATE=lambda{|date|Date.strptime(date,"%Y%m%d").jd-Date.parse("1900/01/01").jd+1}
5
+ FROM_FOS_DATE=lambda{|day|Date.jd(day.to_i+Date.parse("1900/01/01").jd-1)}
6
+ TO_FOS_TIME=lambda{|time|time[0,2].to_i*60+time[3,2].to_i}
7
+ FROM_FOS_TIME=lambda{|time|"#{time.to_i/60}:#{(time.to_i%60).to_s.rjust(2,"0")}"}
8
+
9
+ def initialize(session)
10
+ @session=session
11
+ @mapping={
12
+ "passengers"=>{
13
+ # "birthday"=>{:up=>FROM_FOS_DATE, :down=>TO_FOS_DATE},
14
+ # "last flown"=>{:up=>FROM_FOS_DATE, :down=>TO_FOS_DATE}
15
+ },
16
+ "trip legs"=>{
17
+ # "dept date act local"=>{:up=>FROM_FOS_DATE, :down=>TO_FOS_DATE},
18
+ # "dept time act local"=>{:up=>FROM_FOS_TIME, :down=>TO_FOS_TIME},
19
+ # "arr date act local"=>{:up=>FROM_FOS_DATE, :down=>TO_FOS_DATE},
20
+ # "arriv time act local"=>{:up=>FROM_FOS_TIME, :down=>TO_FOS_TIME},
21
+ # "flight time actual"=>{:up=>FROM_FOS_TIME, :down=>TO_FOS_TIME},
22
+ # "leg type code"=>{:up=>FROM_FOS_CODE('trip_type___'), :down=>TO_FOS_CODE('trip_type___')},
23
+ # "leg purpose code"=>{:up=>FROM_FOS_CODE('purpose_____'), :down=>TO_FOS_CODE('purpose_____')}
24
+ }
25
+ }
26
+ @codes={}
27
+ codes_table=@session.get_table("codes")[0]
28
+ codes_table.each_record(BtrCodes::READ_ONLY_MODE) do |row|
29
+ group=row[:name]
30
+ code=row[:code]
31
+ description=row[:description]
32
+ value=row[:value]
33
+ group_map=@codes[group]||={}
34
+ group_map[value]=FosCode.new(group, value, code, description)
35
+ end
36
+ end
37
+
38
+ def up(tablename, column_name, value)
39
+ db_cast(tablename, column_name, value, :up)
40
+ end
41
+
42
+ def down(tablename, column_name, value)
43
+ db_cast(tablename, column_name, value, :down)
44
+ end
45
+
46
+ private
47
+
48
+ def db_cast(tablename, column_name, value, mode)
49
+ table=@mapping[tablename.to_s]
50
+ return value if(table.nil?)
51
+ column=table[column_name.to_s]
52
+ return value if(column.nil?)
53
+ column[mode].call(value)
54
+ end
55
+
56
+ def FROM_FOS_CODE(groupname)
57
+ lambda{|value|@codes[groupname][value]}
58
+ end
59
+
60
+ def TO_FOS_CODE(groupname)
61
+ lambda{|value|@codes[groupname][value].value}
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ class BtrieveModel
2
+ include Btrieve
3
+ def initialize(classname, tablename)
4
+ session = BtrieveSession.get_session()
5
+ table = BtrieveTable.new(tablename, session)
6
+ session.model_classes[classname] = table
7
+ end
8
+
9
+ def self.new_record()
10
+ BtrieveRecord.new(get_table())
11
+ end
12
+
13
+ def self.find_in_unique_index(match, index_number)
14
+ get_table().find_in_unique_index(match, index_number)
15
+ end
16
+
17
+ def self.find_in_index(match, index_number)
18
+ get_table().find_in_index(match, index_number)
19
+ end
20
+
21
+ def self.each_record(mode=ACCELERATED_MODE, &block)
22
+ get_table().each_record(mode, &block)
23
+ end
24
+
25
+ def self.batch(mode=ACCELERATED_MODE, &block)
26
+ get_table().batch(mode, &block)
27
+ end
28
+
29
+ def self.one_to_one(association)
30
+ get_table().schema[:one_to_one][association[:name]]=association
31
+ end
32
+
33
+ def self.one_to_many(association)
34
+ get_table().schema[:one_to_many][association[:name]]=association
35
+ end
36
+
37
+ private
38
+
39
+ def self.get_table()
40
+ session = BtrieveSession.get_session()
41
+ session.model_classes[self.name.to_sym]
42
+ end
43
+ end
44
+
45
+ def BtrieveModel(classname, tablename)
46
+ raise Exception.new("The context is not set. Call 'Btrieve::Session.set_context( <pathname> )' before declaring model classes.") unless BtrieveSession.get_session() != nil
47
+ BtrieveModel.new(classname, tablename)
48
+ BtrieveModel
49
+ end
@@ -0,0 +1,127 @@
1
+ require 'digest/md5'
2
+
3
+ class BtrieveRecord
4
+ include Btrieve
5
+ attr_reader :data_buffer, :btrieve_table
6
+
7
+ def initialize(btrieve_table, data_buffer = nil )
8
+ @btrieve_table = btrieve_table
9
+ @data_buffer = data_buffer.nil? ? Btrieve.create_string_buffer(@btrieve_table.schema[:record_size]) : data_buffer
10
+ @session = @btrieve_table.session
11
+ end
12
+
13
+ def insert
14
+ btr_op(@session, INSERT, @btrieve_table.pos_buffer, @data_buffer, NULL_BUFFER, NO_CURRENCY_CHANGE)
15
+ end
16
+
17
+ def update
18
+ btr_op(@session, UPDATE, @btrieve_table.pos_buffer, @data_buffer, NULL_BUFFER, NO_CURRENCY_CHANGE)
19
+ end
20
+
21
+ def delete
22
+ btr_op(@session, DELETE, @btrieve_table.pos_buffer, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
23
+ end
24
+
25
+ def get_attributes(keys)
26
+ keys.inject({}){|vals, key| vals[key]=self[key]; vals}
27
+ end
28
+
29
+ def get_all_attributes()
30
+ get_attributes(self.btrieve_table.schema[:columns].keys.sort.inject([]){|array,column|array<<column;array})
31
+ end
32
+
33
+ def primary_key()
34
+ get_composite_key(PK_KEYS)
35
+ end
36
+
37
+ def foreign_key(prefix)
38
+ keys=PK_KEYS.map{|key|:"#{prefix} #{key.to_s}"}
39
+ get_composite_key(keys)
40
+ end
41
+
42
+ def get_unique_reference(association_name)
43
+ dereference(:one_to_one, association_name) do |map, target, index|
44
+ fk_columns = map.keys.inject([]){|vals, column| vals << column; vals}
45
+ fk_values = get_attributes(fk_columns)
46
+ pk_values = map.keys.inject({}){|vals, column| vals[map[column]] = fk_values[column]; vals}
47
+ target.find_in_unique_index(pk_values, index)
48
+ end
49
+ end
50
+
51
+ def get_multiple_references(association_name)
52
+ dereference(:one_to_many, association_name) do |map, target, index|
53
+ pk_columns = map.keys.inject([]){|vals, column| vals << map[column] unless map[column] == nil; vals}
54
+ pk_values = get_attributes(pk_columns)
55
+ fk_values = map.keys.inject({}){|vals, column| vals[column] = pk_values[map[column]]; vals}
56
+ target.find_in_index(fk_values, index)
57
+ end
58
+ end
59
+
60
+ def [](key_name)
61
+ schema_key=get_schema_key(key_name)
62
+ return nil if(schema_key.nil?)
63
+ raw_data=@data_buffer.unpack(schema_key[:unpacker])[0]
64
+ meta = @session.btrieve_meta
65
+ return raw_data if meta.nil? # BS LOC - I'm ashamed
66
+ meta.up(@btrieve_table.tablename, key_name, raw_data)
67
+ end
68
+
69
+ # def [](key_name)
70
+ # schema_key = get_schema_key(key_name)
71
+ # @data_buffer.unpack(schema_key[:unpacker])[0] if schema_key
72
+ # end
73
+
74
+ def []=(key_name, raw_data)
75
+ value=@session.btrieve_meta.down(@btrieve_table.tablename, key_name, raw_data)
76
+ schema_key = get_schema_key(key_name)
77
+ packer_string = schema_key[:unpacker]
78
+ match = packer_string.match(/@(\d+)([a-zA-Z]+)(\d*)/)
79
+ offset = match[1].to_i
80
+ datatype = match[2]
81
+ sizeof = BtrieveSchema.sizeof(datatype)
82
+ sizeof *= match[3].empty? ? 1 : match[3].to_i
83
+ packer = "#{datatype}#{sizeof}"
84
+ array = [value]
85
+ packed_value = array.pack(packer)
86
+ range = (offset..offset+sizeof-1)
87
+ @data_buffer[range] = packed_value
88
+ end
89
+
90
+ def to_s()
91
+ @btrieve_table.schema[:columns].keys.inject('') { |pretty_print, key| pretty_print = "#{pretty_print} #{key}=>#{self[key]}"; pretty_print }
92
+ end
93
+
94
+ def method_missing(symbol)
95
+ return get_unique_reference(symbol) if(@btrieve_table.schema[:one_to_one][symbol])
96
+ return get_multiple_references(symbol) if(@btrieve_table.schema[:one_to_many][symbol])
97
+ super(symbol)
98
+ end
99
+
100
+ def version()
101
+ Digest::MD5.hexdigest(@data_buffer)
102
+ end
103
+
104
+ private
105
+
106
+ def dereference(association_group, association_name, &block)
107
+ association = @btrieve_table.schema[association_group][association_name]
108
+ raise Exception.new("Unknown association '#{association_name}' for table '#{@btrieve_table.tablename}'.") unless association != nil
109
+ map = association[:map]
110
+ target = eval(association[:class].to_s)
111
+ index = association[:index]
112
+ yield(map, target, index)
113
+ end
114
+
115
+ def get_schema_key(key_name)
116
+ schema_key = @btrieve_table.schema[:columns][key_name]
117
+ # raising this exception is hurting the dbr process since I use keys that dont exist
118
+ # raise Exception.new("Unknown column '#{key_name}' for table '#{@btrieve_table.tablename}'.") unless schema_key != nil
119
+ schema_key
120
+ end
121
+
122
+ def get_composite_key(keys)
123
+ pk=keys.inject([]){|arr,col|arr<<self[col];arr}
124
+ pk[2]=pk[2].strip
125
+ pk.join('.')
126
+ end
127
+ end
@@ -0,0 +1,128 @@
1
+ class BtrieveSchema
2
+ include Btrieve
3
+ attr_reader :session, :xfile_records, :xfield_records
4
+
5
+ def initialize(session)
6
+ @session = session
7
+ if(!@session.cache[:schemas_loaded])
8
+ cache_system_table(:'x$file')
9
+ cache_system_table(:'x$field')
10
+ cache_system_table(:'x$index')
11
+ @session.cache[:schemas_loaded] = true
12
+ end
13
+ end
14
+
15
+ def load_schema(tablename)
16
+ schema = nil
17
+ xfile_index = nil
18
+ @session.cache[:'x$file'].each do |xfile|
19
+ next unless xfile[:'xf$name'].downcase.strip.to_sym == tablename
20
+ schema = {:filename=>xfile[:'xf$loc'].downcase.strip, :record_size=>0, :columns=>{}}
21
+ xfile_index = xfile[:'xf$id']
22
+ break
23
+ end
24
+ xfield_index = []
25
+ @session.cache[:'x$field'].each do |xfield|
26
+ next unless xfile_index == xfield[:'xe$file']
27
+ next unless xfield[:'xe$datatype'] < MAX_DATATYPE
28
+ id = xfield[:'xe$id']
29
+ name = xfield[:'xe$name'].strip.downcase
30
+ offset = xfield[:'xe$offset']
31
+ size = xfield[:'xe$size']
32
+ datatype = xfield[:'xe$datatype']
33
+ datatype = (name == 'kid - mult') ? 14 : datatype # BS line of code...
34
+ unpacker = BtrieveSchema.unpacker(offset, datatype, size)
35
+ schema[:columns][name.to_sym] = {:unpacker=>unpacker, :id=>id, :offset=>offset, :datatype=>datatype, :size=>size}
36
+ schema[:record_size] += size
37
+ xfield_index[id] = name.to_sym
38
+ end
39
+ @session.cache[:'x$index'].each do |xindex|
40
+ next unless xfile_index == xindex[:'xi$file']
41
+ indices = schema[:indices] ||= []
42
+ index = indices[xindex[:'xi$number']] ||= []
43
+ index[xindex[:'xi$part']] = xfield_index[xindex[:'xi$field']]
44
+ flags = schema[:index_flags] ||= []
45
+ flags[xindex[:'xi$number']] = flags[xindex[:'xi$number']].to_i | xindex[:'xi$flags'].to_i
46
+ end
47
+ raise Exception.new("Unknown table '#{tablename}'.") if schema.nil?
48
+ schema[:one_to_one] = {}
49
+ schema[:one_to_many] = {}
50
+ schema
51
+ end
52
+
53
+ def self.sizeof(code)
54
+ SIZEOF[code]
55
+ end
56
+
57
+ private
58
+
59
+ SYS_DDF = {
60
+ :'x$file'=>{:filename=>'file.ddf', :record_size=>97, :columns=>{:'xf$id'=>{:unpacker=>'@0S'}, :'xf$name'=>{:unpacker=>'@2a20'},:'xf$loc'=>{:unpacker=>'@22a64'}, :'xf$flags'=>{:unpacker=>'@86C'},:'xf$reserved'=>{:unpacker=>'@87a10'}}},
61
+ :'x$field'=>{:filename=>'field.ddf', :record_size=>32, :columns=>{:'xe$id'=>{:unpacker=>'@0S'}, :'xe$file'=>{:unpacker=>'@2S'}, :'xe$name'=>{:unpacker=>'@4a20'}, :'xe$datatype'=>{:unpacker=>'@24C'}, :'xe$offset'=>{:unpacker=>'@25S'}, :'xe$size'=>{:unpacker=>'@27S'}, :'xe$dec'=>{:unpacker=>'@29C'}, :'xe$flags'=>{:unpacker=>'@30S'}}},
62
+ :'x$index'=>{:filename=>'index.ddf', :record_size=>32, :columns=>{:'xi$file'=>{:unpacker=>'@0S'},:'xi$field'=>{:unpacker=>'@2S'},:'xi$number'=>{:unpacker=>'@4S'},:'xi$part'=>{:unpacker=>'@6S'},:'xi$flags'=>{:unpacker=>'@8S'}}}
63
+ }
64
+
65
+ CHAR = { :name=>'CHAR', :unpacker=>'a' }
66
+ TINYINT = { :name=>'TINYINT', :unpacker=>'c' }
67
+ SMALLINT = { :name=>'SMALLINT', :unpacker=>'s' }
68
+ INTEGER = { :name=>'INTEGER', :unpacker=>'i' }
69
+ REAL = { :name=>'REAL', :unpacker=>'f' }
70
+ DOUBLE = { :name=>'DOUBLE', :unpacker=>'d' }
71
+ DATE = { :name=>'DATE', :unpacker=>'ccs' } #day month year
72
+ TIME = { :name=>'TIME', :unpacker=>'cccc' } #100th sec min hour
73
+ BIT = { :name=>'BIT', :unpacker=>'c' }
74
+ VARCHAR = { :name=>'VARCHAR', :unpacker=>'A' }
75
+ LONGVARCHAR = { :name=>'LONGVARCHAR', :unpacker=>'A' }
76
+ UTINYINT = { :name=>'UTINYINT', :unpacker=>'C' }
77
+ USMALLINT = { :name=>'USMALLINT', :unpacker=>'S' }
78
+ UINTEGER = { :name=>'UINTEGER', :unpacker=>'I' }
79
+ UBIGINT = { :name=>'UBIGINT', :unpacker=>'Q' }
80
+
81
+ SIZEOF = {'a'=>1, 'c'=>1, 's'=>1, 'i'=>1, 'f'=>1, 'd'=>1, 'ccs'=>4, 'cccc'=>4, 'A'=>1, 'C'=>1, 'S'=>1, 'I'=>1, 'Q'=>1}
82
+
83
+ def self.unpacker(offset, datatype, size)
84
+ offsetter = "@#{offset}"
85
+ btrtype = lookup(datatype, size)
86
+ multiplier = btrtype[:name].match('CHAR') ? size : ''
87
+ "#{offsetter}#{btrtype[:unpacker]}#{multiplier}"
88
+ end
89
+
90
+ def self.readable_type(column)
91
+ c=column.to_a[0]
92
+ btrtype = lookup(c[1][:datatype],c[1][:size])
93
+ [:name=>c[0], :datatype=>btrtype[:name], :size=>c[1][:size]]
94
+ end
95
+
96
+ def self.sort(schema)
97
+ schema.inject([]){|array,column|array[column[1][:offset]]={column[0]=>column[1]};array}.compact
98
+ end
99
+
100
+ def self.lookup(datatype, size)
101
+ case datatype
102
+ when 0 then CHAR
103
+ when 1 then case size when 1 then TINYINT when 2 then SMALLINT when 4 then INTEGER else raise Exception.new("Unknown BTRTYPE for 'datatype'=#{datatype} and 'size'=#{size}."); end
104
+ when 2 then case size when 4 then REAL when 8 then DOUBLE else raise Exception.new("Unknown BTRTYPE for 'datatype'=#{datatype} and 'size'=#{size}."); end
105
+ when 3 then DATE
106
+ when 4 then TIME
107
+ when 7 then BIT
108
+ when 11 then VARCHAR
109
+ when 12 then LONGVARCHAR
110
+ when 14 then case size when 1 then UTINYINT when 2 then USMALLINT when 4 then UINTEGER when 8 then UBIGINT else raise Exception.new("Unknown BTRTYPE for 'datatype'=#{datatype} and 'size'=#{size}."); end
111
+ when 16 then BIT
112
+ when 21 then LONGVARCHAR
113
+ else raise Exception.new("Unknown BTRTYPE for 'datatype'=#{datatype} and 'size'=#{size}.")
114
+ end
115
+ end
116
+
117
+ def cache_system_table(tablename)
118
+ @session.cache[tablename] = []
119
+ schema_table = BtrieveTable.new(SYS_DDF[tablename][:filename], @session, SYS_DDF[tablename])
120
+ schema_table.each_record(ACCELERATED_MODE) {|value| @session.cache[tablename] << value}
121
+ end
122
+ end
123
+
124
+ class Array
125
+ def include_all?(other_array)
126
+ (self.size == other_array.size) && ((self & other_array).size == self.size)
127
+ end
128
+ end
@@ -0,0 +1,50 @@
1
+ class BtrieveSession
2
+ SESSIONS = {}
3
+ include Btrieve
4
+ attr_reader :pathname, :client_id, :cache, :model_classes, :btrieve_schema, :btrieve_meta
5
+
6
+ def self.set_context(pathname)
7
+ session = get_session
8
+ if session
9
+ raise Exception.new("The existing context in the current is set to a different pathname.") if(session.pathname != pathname)
10
+ else
11
+ SESSIONS[Thread.current] = new(pathname)
12
+ end
13
+ end
14
+
15
+ def self.get_session
16
+ SESSIONS[Thread.current]
17
+
18
+ end
19
+
20
+ def transaction(&block)
21
+ btr_op(self, BEGIN_TRANSACTION, NULL_BUFFER, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
22
+ begin
23
+ yield
24
+ rescue Exception => exception
25
+ btr_op(self, ABORT_TRANSACTION, NULL_BUFFER, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
26
+ raise Exception.new("PSQL TX ABORTED!!! - #{exception.message}\n#{exception.backtrace.join("\n\t")}")
27
+ end
28
+ btr_op(self, END_TRANSACTION, NULL_BUFFER, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
29
+ end
30
+
31
+ def get_table(url_tablename)
32
+ tablename=BtrieveTable.url_to_tablename(url_tablename)
33
+ table=@table_cache[tablename]||=BtrieveTable.new(tablename.to_sym, self)
34
+ [table,table.version]
35
+ end
36
+
37
+ private
38
+
39
+ def initialize(pathname)
40
+ @cache = {}
41
+ @model_classes = {}
42
+ @table_cache = {}
43
+ @pathname = pathname
44
+ @client_id = "#{0.chr*12}#{[0x5257].pack('S')}#{rand(65535)}"
45
+ btr_op(self, SET_DIRECTORY, NULL_BUFFER, NULL_BUFFER, @pathname, NULL_KEY)
46
+ @btrieve_schema = BtrieveSchema.new(self)
47
+ @btrieve_meta = BtrieveMeta.new(self)
48
+ end
49
+ end
50
+
@@ -0,0 +1,115 @@
1
+ require 'digest/md5'
2
+
3
+ class BtrieveTable
4
+ include Btrieve
5
+ attr_reader :tablename, :session, :pos_buffer, :schema
6
+
7
+ def initialize(tablename, session, schema = nil)
8
+ @tablename = tablename
9
+ @session = session
10
+ @pos_buffer = Btrieve.create_string_buffer(POS_BLOCK_SIZE)
11
+ @schema = schema ? schema : @session.btrieve_schema.load_schema(@tablename)
12
+ end
13
+
14
+ def open(mode = NORMAL_MODE)
15
+ btr_op(@session, OPEN, @pos_buffer, NULL_BUFFER, @schema[:filename], mode)
16
+ end
17
+
18
+ def find_in_unique_index(match, index_number=nil)
19
+ finder(match, index_number) do |key_buffer, index|
20
+ btr_record = BtrieveRecord.new(self)
21
+ batch(){ btr_op(@session, GET_EQUAL, @pos_buffer, btr_record.data_buffer, key_buffer, index) }
22
+ btr_record
23
+ end
24
+ end
25
+
26
+ def find_in_index(match, index_number=nil)
27
+ finder(match, index_number) do |key_buffer, index|
28
+ absolute_match = match.keys.inject({}){|vals, key| vals[key] = match[key] if(match[key] != nil); vals}
29
+ absolute_match_keys = absolute_match.keys
30
+ result = []
31
+ batch() do
32
+ btr_record = BtrieveRecord.new(self)
33
+ btr_op(@session, GET_GREATER_THAN_OR_EQUAL, @pos_buffer, btr_record.data_buffer, key_buffer, index)
34
+ result << btr_record
35
+ while(true)
36
+ btr_record = BtrieveRecord.new(self)
37
+ op_result = btr_op(@session, GET_NEXT, @pos_buffer, btr_record.data_buffer, key_buffer, index_number, [OK, EOF, 21])
38
+ break unless btr_record.get_attributes(absolute_match_keys)==absolute_match and op_result!=EOF and op_result!=21
39
+ result << btr_record
40
+ end
41
+ end
42
+ result
43
+ end
44
+ end
45
+
46
+ def close
47
+ btr_op(@session, CLOSE, @pos_buffer, NULL_BUFFER, NULL_BUFFER, NULL_KEY)
48
+ end
49
+
50
+ def each_record(mode = READ_ONLY_MODE, &block)
51
+ batch(mode) do
52
+ while(record = step_next) do
53
+ yield record
54
+ end
55
+ end
56
+ end
57
+
58
+ def batch(mode = READ_ONLY_MODE, &block)
59
+ open(mode)
60
+ yield
61
+ close
62
+ end
63
+
64
+ def version()
65
+ Digest::MD5.hexdigest(BtrieveSchema.sort(schema[:columns]).inject([]){|array,column|array<<BtrieveSchema.readable_type(column);array}.to_s)
66
+ end
67
+
68
+ def self.primary_key_match(pk)
69
+ vals=pk.split('.')
70
+ {PK_KEYS[0]=>vals[0].to_i,PK_KEYS[1]=>vals[1].to_i,PK_KEYS[2]=>vals[2],PK_KEYS[3]=>vals[3].to_i,PK_KEYS[4]=>vals[4].to_i}
71
+ end
72
+
73
+ def self.tablename_to_url(tablename)
74
+ tablename.gsub(' & ','.and.').gsub('a/c ', 'ac.').gsub('es - o','es.o').gsub(' ','.')
75
+ end
76
+
77
+ def self.url_to_tablename(url_tablename)
78
+ url_tablename.gsub('.and.', ' & ').gsub('ac.', 'a/c ').gsub('es.o','es - o').gsub('.',' ')
79
+ end
80
+
81
+ private
82
+
83
+ def step_next
84
+ btr_record = BtrieveRecord.new(self)
85
+ result = btr_op(@session, STEP_NEXT, @pos_buffer, btr_record.data_buffer, NULL_BUFFER, NULL_KEY, [OK, EOF])
86
+ return false if(result == EOF)
87
+ btr_record
88
+ end
89
+
90
+ def find_matching_index(match)
91
+ keys = match.keys
92
+ indices = @schema[:indices]
93
+ indices.each_index(){ |index| return index if(indices[index].include_all?(keys)) }
94
+ raise Exception.new("No matching index for #{keys}")
95
+ end
96
+
97
+ def finder(match, index_number = nil, &block)
98
+ index_number ||= find_matching_index(match)
99
+ index = @schema[:indices][index_number]
100
+ columns = @schema[:columns]
101
+ key_components = index.inject([]) { |vals, key| vals << match[key]; vals}
102
+ key_packer = index.inject("") do |packer, key|
103
+ datatype = BtrieveSchema.lookup(columns[key][:datatype], columns[key][:size])
104
+ if(match[key] != nil)
105
+ packer += "#{datatype[:unpacker]}#{datatype[:name].match('CHAR') ? columns[key][:size] : ''}"
106
+ else
107
+ packer += 'x'*columns[key][:size]
108
+ end
109
+ packer
110
+ end
111
+ key_buffer = key_components.pack(key_packer)
112
+ yield(key_buffer, index_number)
113
+ end
114
+ end
115
+
@@ -0,0 +1,13 @@
1
+ class FosCode
2
+ attr_reader :group, :value, :code, :description
3
+ def initialize(group, value, code, description)
4
+ @group=group
5
+ @value=value
6
+ @code=code
7
+ @description=description
8
+ end
9
+
10
+ def to_s
11
+ @description
12
+ end
13
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beezwax
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 0.0.0
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Patrick Lardin
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-22 00:00:00 -07:00
18
+ date: 2010-08-23 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,6 +51,15 @@ files:
51
51
  - Rakefile
52
52
  - VERSION
53
53
  - lib/beezwax.rb
54
+ - lib/btrieve/btrieve_const.rb
55
+ - lib/btrieve/btrieve_core.rb
56
+ - lib/btrieve/btrieve_meta.rb
57
+ - lib/btrieve/btrieve_model.rb
58
+ - lib/btrieve/btrieve_record.rb
59
+ - lib/btrieve/btrieve_schema.rb
60
+ - lib/btrieve/btrieve_session.rb
61
+ - lib/btrieve/btrieve_table.rb
62
+ - lib/btrieve/fos_code.rb
54
63
  - test/helper.rb
55
64
  - test/test_beezwax.rb
56
65
  has_rdoc: true