rubyfb 0.5.9 → 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/ResultSet.c CHANGED
@@ -36,12 +36,14 @@
36
36
 
37
37
  /* Function prototypes. */
38
38
  static VALUE allocateResultSet(VALUE);
39
- static VALUE initializeResultSet(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
39
+ static VALUE initializeResultSet(VALUE, VALUE, VALUE);
40
+ static VALUE getResultSetRow(VALUE);
40
41
  static VALUE fetchResultSetEntry(VALUE);
41
42
  static VALUE closeResultSet(VALUE);
42
43
  static VALUE getResultSetCount(VALUE);
43
44
  static VALUE getResultSetConnection(VALUE);
44
45
  static VALUE getResultSetTransaction(VALUE);
46
+ static VALUE getResultSetStatement(VALUE);
45
47
  static VALUE getResultSetSQL(VALUE);
46
48
  static VALUE getResultSetDialect(VALUE);
47
49
  static VALUE getResultSetColumnCount(VALUE);
@@ -52,14 +54,39 @@ static VALUE getResultSetColumnTable(VALUE, VALUE);
52
54
  static VALUE getResultSetColumnType(VALUE, VALUE);
53
55
  static VALUE eachResultSetRow(VALUE);
54
56
  static VALUE isResultSetExhausted(VALUE);
55
- static void resultSetMark(void *);
56
- static void cleanupHandle(isc_stmt_handle *handle);
57
- static void resolveResultsTransaction(ResultsHandle *results, char *resolveMethod);
58
-
59
57
 
60
58
  /* Globals. */
61
59
  VALUE cResultSet;
62
60
 
61
+ StatementHandle* getStatementHandle(VALUE self) {
62
+ StatementHandle *hStatement;
63
+ Data_Get_Struct(getResultSetStatement(self), StatementHandle, hStatement);
64
+
65
+ return (hStatement);
66
+ }
67
+
68
+ short isActiveResultSet(VALUE self) {
69
+ short result = 0;
70
+ if ((Qtrue == rb_obj_is_kind_of(self, cResultSet))) {
71
+ ResultsHandle *hResults = NULL;
72
+ Data_Get_Struct(self, ResultsHandle, hResults);
73
+ result = hResults->active;
74
+ }
75
+ return (result);
76
+ }
77
+
78
+ void resultSetManageTransaction(VALUE self) {
79
+ ResultsHandle *hResults = NULL;
80
+ Data_Get_Struct(self, ResultsHandle, hResults);
81
+ hResults->manage_transaction = 1;
82
+ }
83
+
84
+ void resultSetManageStatement(VALUE self) {
85
+ ResultsHandle *hResults = NULL;
86
+ Data_Get_Struct(self, ResultsHandle, hResults);
87
+ hResults->manage_statement = 1;
88
+ }
89
+
63
90
  /**
64
91
  * This method allocates a new ResultSet object.
65
92
  *
@@ -75,15 +102,12 @@ VALUE allocateResultSet(VALUE klass) {
75
102
  rb_raise(rb_eNoMemError,
76
103
  "Memory allocation failure allocating a result set.");
77
104
  }
78
- results->handle = 0;
79
- results->output = NULL;
80
- results->exhausted = 0;
81
105
  results->fetched = 0;
82
- results->dialect = 0;
83
- results->procedure_output_fetch_state = -1;
84
- results->transaction = Qnil;
106
+ results->active = 0;
107
+ results->manage_transaction = 0;
108
+ results->manage_statement = 0;
85
109
 
86
- return(Data_Wrap_Struct(klass, resultSetMark, resultSetFree, results));
110
+ return(Data_Wrap_Struct(klass, NULL, resultSetFree, results));
87
111
  }
88
112
 
89
113
 
@@ -91,137 +115,42 @@ VALUE allocateResultSet(VALUE klass) {
91
115
  * This function provides the initialize method for the ResultSet class.
92
116
  *
93
117
  * @param self A reference to the ResultSet object to be initialized.
94
- * @param connection A reference to a Connection object that will be used
95
- * in executing the statement.
96
- * @param transaction A reference to a Transaction object that will be used
97
- * in executing the statement.
98
- * @param sql A reference to a String containing the SQL statement to
99
- * be executed. Must be a query.
100
- * @param dialect A reference to an integer containing the SQL dialect to
101
- * be used in executing the query.
102
- * @param parameters A reference to an array containing the parameters to be
103
- * used in executing the query.
118
+ * @param statement A statement to iterate over
119
+ * @param transaction A reference to a privater transaction object
120
+ * taht should be managed by this ResultSet.
104
121
  *
105
122
  * @return A reference to the newly initialize ResultSet object.
106
123
  *
107
124
  */
108
- VALUE initializeResultSet(VALUE self, VALUE connection, VALUE transaction,
109
- VALUE sql, VALUE dialect, VALUE parameters) {
110
- short setting = 0;
111
- int type = 0,
112
- inputs = 0,
113
- outputs = 0;
114
- long affected = 0;
115
- ResultsHandle *results = NULL;
116
- VALUE value = Qnil;
117
- ConnectionHandle *cHandle = NULL;
118
- TransactionHandle *tHandle = NULL;
119
- XSQLDA *params = NULL;
120
-
121
- /* Validate the inputs. */
122
- if(TYPE(connection) == T_DATA &&
123
- RDATA(connection)->dfree == (RUBY_DATA_FUNC)connectionFree) {
124
- if(rb_funcall(connection, rb_intern("open?"), 0) == Qfalse) {
125
- rb_fireruby_raise(NULL, "Closed connection specified for result set.");
126
- }
127
- } else {
128
- rb_fireruby_raise(NULL, "Invalid connection specified for result set.");
129
- }
130
-
131
- if(TYPE(transaction) == T_DATA &&
132
- RDATA(transaction)->dfree == (RUBY_DATA_FUNC)transactionFree) {
133
- if(rb_funcall(transaction, rb_intern("active?"), 0) == Qfalse) {
134
- rb_fireruby_raise(NULL, "Inactive transaction specified for result set.");
135
- }
136
- } else {
137
- rb_fireruby_raise(NULL, "Invalid transaction specified for result set.");
138
- }
139
-
140
- value = rb_funcall(dialect, rb_intern("to_i"), 0);
141
- if(TYPE(value) == T_FIXNUM) {
142
- setting = FIX2INT(value);
143
- if(setting < 1 || setting > 3) {
144
- rb_fireruby_raise(NULL,
145
- "Invalid dialect value specified for result set. " \
146
- "The dialect value must be between 1 and 3.");
147
- }
148
- } else {
149
- rb_fireruby_raise(NULL,
150
- "Invalid dialect value specified for result set. The " \
151
- "dialect value must be between 1 and 3.");
152
- }
153
-
154
- /* Prepare the result set. */
155
- Data_Get_Struct(connection, ConnectionHandle, cHandle);
156
- Data_Get_Struct(transaction, TransactionHandle, tHandle);
157
- Data_Get_Struct(self, ResultsHandle, results);
158
- prepare(&cHandle->handle, &tHandle->handle, StringValuePtr(sql), &results->handle,
159
- setting, &type, &inputs, &outputs);
160
-
161
- if(type != isc_info_sql_stmt_select &&
162
- type != isc_info_sql_stmt_select_for_upd &&
163
- type != isc_info_sql_stmt_exec_procedure) {
164
- cleanupHandle(&results->handle);
165
- rb_fireruby_raise(NULL,
166
- "Non-query SQL statement specified for result set.");
167
- }
125
+ VALUE initializeResultSet(VALUE self, VALUE statement, VALUE transaction) {
126
+ ResultsHandle *hResults = NULL;
127
+ Data_Get_Struct(self, ResultsHandle, hResults);
168
128
 
169
- rb_iv_set(self, "@connection", connection);
129
+ rb_iv_set(self, "@statement", statement);
170
130
  rb_iv_set(self, "@transaction", transaction);
171
- rb_iv_set(self, "@sql", rb_funcall(sql, rb_intern("to_s"), 0));
172
- rb_iv_set(self, "@dialect", value);
173
- results->dialect = setting;
174
-
175
- /* UNCOMMENT FOR DEBUGGING PURPOSES! */
176
- /*strcpy(results->sql, StringValuePtr(sql));*/
177
-
178
- /* Check if input parameters are needed. */
179
- if(inputs > 0) {
180
- VALUE value = Qnil;
181
- int size = 0;
182
-
183
- if(parameters == Qnil) {
184
- cleanupHandle(&results->handle);
185
- rb_fireruby_raise(NULL,
186
- "Empty parameter list specified for result set.");
187
- }
188
-
189
- value = rb_funcall(parameters, rb_intern("size"), 0);
190
- size = TYPE(value) == T_FIXNUM ? FIX2INT(value) : NUM2INT(value);
191
- if(size < inputs) {
192
- cleanupHandle(&results->handle);
193
- rb_fireruby_raise(NULL,
194
- "Insufficient parameters specified for result set.");
195
- }
131
+ hResults->active = 1;
132
+
133
+ return(self);
134
+ }
196
135
 
197
- /* Allocate the XSQLDA and populate it. */
198
- params = allocateInXSQLDA(inputs, &results->handle, setting);
199
- prepareDataArea(params);
200
- setParameters(params, parameters, self);
201
- }
136
+ /**
137
+ * This function provides the row method for the ResultSet class.
138
+ *
139
+ * @param self A reference to the ResultSet object to make the call on.
140
+ *
141
+ * @return Either a reference to a Row object or nil.
142
+ *
143
+ */
144
+ VALUE getResultSetRow(VALUE self) {
145
+ VALUE row = Qnil;
146
+ ResultsHandle *hResults = NULL;
202
147
 
203
- /* Allocate output storage. */
204
- results->output = allocateOutXSQLDA(outputs, &results->handle, setting);
205
- prepareDataArea(results->output);
206
-
207
- /* Execute the statement and clean up. */
208
- if(type == isc_info_sql_stmt_exec_procedure) {
209
- /* Execute with output params */
210
- execute_2(&tHandle->handle, &results->handle, setting, params, type,
211
- &affected, results->output);
212
- /* Initialize procedure output fetch */
213
- results->procedure_output_fetch_state = 0;
214
- /* Early resolve transaction */
215
- resolveResultsTransaction (results, "commit");
216
- } else {
217
- execute(&tHandle->handle, &results->handle, setting, params, type,
218
- &affected);
219
- }
220
- if(params != NULL) {
221
- releaseDataArea(params);
148
+ Data_Get_Struct(self, ResultsHandle, hResults);
149
+ if(hResults->fetched) {
150
+ VALUE array = toArray(self);
151
+ row = rb_row_new(self, array, INT2FIX(hResults->fetched));
222
152
  }
223
-
224
- return(self);
153
+ return (row);
225
154
  }
226
155
 
227
156
 
@@ -234,43 +163,37 @@ VALUE initializeResultSet(VALUE self, VALUE connection, VALUE transaction,
234
163
  *
235
164
  */
236
165
  VALUE fetchResultSetEntry(VALUE self) {
237
- VALUE row = Qnil;
238
- ResultsHandle *results = NULL;
239
- ISC_STATUS status[ISC_STATUS_LENGTH],
240
- value;
241
-
242
- Data_Get_Struct(self, ResultsHandle, results);
243
- if(results->handle != 0 && !results->exhausted) {
244
- VALUE array,number;
245
- value = results->procedure_output_fetch_state;
246
- if(value < 0) {
247
- value = isc_dsql_fetch(status, &results->handle, results->dialect,
248
- results->output);
166
+ VALUE row = Qnil;
167
+ StatementHandle *hStatement = getStatementHandle(self);
168
+ ResultsHandle *hResults = NULL;
169
+ ISC_STATUS status[ISC_STATUS_LENGTH],
170
+ fetch_result;
171
+
172
+ Data_Get_Struct(self, ResultsHandle, hResults);
173
+ if(hResults->active) {
174
+ if (isCursorStatement(hStatement)) {
175
+ fetch_result = isc_dsql_fetch(status, &hStatement->handle, hStatement->dialect,
176
+ hStatement->output);
177
+ switch(fetch_result) {
178
+ case 0:
179
+ hResults->fetched += 1;
180
+ row = getResultSetRow(self);
181
+ break;
182
+ case 100:
183
+ hResults->active = 0;
184
+ break;
185
+ default:
186
+ rb_fireruby_raise(status, "Error fetching query row.");
187
+ }
249
188
  } else {
250
- /* move procedure_output_fetch_state ahead - fetch only one row */
251
- results->procedure_output_fetch_state = 100;
252
- }
253
- array = Qnil;
254
- number = Qnil;
255
- switch(value) {
256
- case 0:
257
- array = toArray(self);
258
- number = INT2NUM(++(results->fetched));
259
- row = rb_row_new(self, array, number);
260
- break;
261
- case 100:
262
- results->exhausted = 1;
263
- resolveResultsTransaction(results, "commit");
264
- break;
265
- default:
266
- rb_fireruby_raise(status, "Error fetching query row.");
189
+ hResults->active = 0;
190
+ hResults->fetched = 1;
191
+ row = getResultSetRow(self);
267
192
  }
268
193
  }
269
-
270
- return(row);
194
+ return (row);
271
195
  }
272
196
 
273
-
274
197
  /**
275
198
  * This function provides the close method for the ResultSet class, releasing
276
199
  * resources associated with the ResultSet.
@@ -281,24 +204,29 @@ VALUE fetchResultSetEntry(VALUE self) {
281
204
  *
282
205
  */
283
206
  VALUE closeResultSet(VALUE self) {
284
- ResultsHandle *results = NULL;
285
-
286
- Data_Get_Struct(self, ResultsHandle, results);
287
- if(results->handle != 0) {
288
- ISC_STATUS status[ISC_STATUS_LENGTH];
289
-
290
- if(isc_dsql_free_statement(status, &results->handle, DSQL_drop)) {
291
- rb_fireruby_raise(status, "Error closing result set.");
292
- }
293
- results->handle = 0;
207
+ StatementHandle *hStatement = getStatementHandle(self);
208
+ ResultsHandle *hResults = NULL;
209
+ Data_Get_Struct(self, ResultsHandle, hResults);
210
+ ISC_STATUS status[ISC_STATUS_LENGTH];
211
+
212
+ hResults->active = 0;
213
+ if(isc_dsql_free_statement(status, &hStatement->handle, DSQL_close)) {
214
+ rb_fireruby_raise(status, "Error closing cursor.");
294
215
  }
295
-
296
- if(results->output != NULL) {
297
- releaseDataArea(results->output);
298
- results->output = NULL;
216
+ if(hResults->manage_statement) {
217
+ VALUE statement = getResultSetStatement(self),
218
+ menagement_required = rb_funcall(statement, rb_intern("prepared?"), 0);
219
+ if(Qtrue == menagement_required) {
220
+ rb_funcall(statement, rb_intern("close"), 0);
221
+ }
222
+ }
223
+ if(hResults->manage_transaction) {
224
+ VALUE transaction = getResultSetTransaction(self),
225
+ menagement_required = rb_funcall(transaction, rb_intern("active?"), 0);
226
+ if(Qtrue == menagement_required) {
227
+ rb_funcall(transaction, rb_intern("commit"), 0);
228
+ }
299
229
  }
300
-
301
- resolveResultsTransaction(results, "commit");
302
230
 
303
231
  return(self);
304
232
  }
@@ -334,7 +262,7 @@ VALUE getResultSetCount(VALUE self) {
334
262
  *
335
263
  */
336
264
  VALUE getResultSetConnection(VALUE self) {
337
- return(rb_iv_get(self, "@connection"));
265
+ return(rb_funcall(getResultSetStatement(self), rb_intern("connection"), 0));
338
266
  }
339
267
 
340
268
 
@@ -349,7 +277,21 @@ VALUE getResultSetConnection(VALUE self) {
349
277
  *
350
278
  */
351
279
  VALUE getResultSetTransaction(VALUE self) {
352
- return(rb_iv_get(self, "@transaction"));
280
+ return rb_iv_get(self, "@transaction");
281
+ }
282
+
283
+ /**
284
+ * This method provides the accessor method for the transaction ResultSet
285
+ * statement.
286
+ *
287
+ * @param self A reference to the ResultSet object to fetch the attribute
288
+ * from.
289
+ *
290
+ * @return A reference to the requested attribute object.
291
+ *
292
+ */
293
+ VALUE getResultSetStatement(VALUE self) {
294
+ return rb_iv_get(self, "@statement");
353
295
  }
354
296
 
355
297
 
@@ -363,7 +305,7 @@ VALUE getResultSetTransaction(VALUE self) {
363
305
  *
364
306
  */
365
307
  VALUE getResultSetSQL(VALUE self) {
366
- return(rb_iv_get(self, "@sql"));
308
+ return(rb_funcall(getResultSetStatement(self), rb_intern("sql"), 0));
367
309
  }
368
310
 
369
311
 
@@ -377,7 +319,7 @@ VALUE getResultSetSQL(VALUE self) {
377
319
  *
378
320
  */
379
321
  VALUE getResultSetDialect(VALUE self) {
380
- return(rb_iv_get(self, "@dialect"));
322
+ return(rb_funcall(getResultSetStatement(self), rb_intern("dialect"), 0));
381
323
  }
382
324
 
383
325
 
@@ -391,15 +333,7 @@ VALUE getResultSetDialect(VALUE self) {
391
333
  *
392
334
  */
393
335
  VALUE getResultSetColumnCount(VALUE self) {
394
- VALUE count = Qnil;
395
- ResultsHandle *results = NULL;
396
-
397
- Data_Get_Struct(self, ResultsHandle, results);
398
- if(results != NULL) {
399
- count = INT2NUM(results->output->sqld);
400
- }
401
-
402
- return(count);
336
+ return(INT2NUM(getStatementHandle(self)->output->sqld));
403
337
  }
404
338
 
405
339
 
@@ -415,21 +349,17 @@ VALUE getResultSetColumnCount(VALUE self) {
415
349
  *
416
350
  */
417
351
  static VALUE getResultSetColumnName(VALUE self, VALUE column) {
352
+ int offset = 0;
418
353
  VALUE name = Qnil;
419
- ResultsHandle *results = NULL;
420
-
421
- Data_Get_Struct(self, ResultsHandle, results);
422
- if(results != NULL) {
423
- int offset = 0;
354
+ StatementHandle *hStatement = getStatementHandle(self);
424
355
 
425
- offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
426
- if(offset >= 0 && offset < results->output->sqld) {
427
- XSQLVAR *var = results->output->sqlvar;
428
- int index;
356
+ offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
357
+ if(offset >= 0 && offset < hStatement->output->sqld) {
358
+ XSQLVAR *var = hStatement->output->sqlvar;
359
+ int index;
429
360
 
430
- for(index = 0; index < offset; index++, var++) ;
431
- name = rb_str_new(var->sqlname, var->sqlname_length);
432
- }
361
+ for(index = 0; index < offset; index++, var++) ;
362
+ name = rb_str_new(var->sqlname, var->sqlname_length);
433
363
  }
434
364
 
435
365
  return(name);
@@ -448,21 +378,17 @@ static VALUE getResultSetColumnName(VALUE self, VALUE column) {
448
378
  *
449
379
  */
450
380
  static VALUE getResultSetColumnAlias(VALUE self, VALUE column) {
381
+ int offset = 0;
451
382
  VALUE alias = Qnil;
452
- ResultsHandle *results = NULL;
453
-
454
- Data_Get_Struct(self, ResultsHandle, results);
455
- if(results != NULL) {
456
- int offset = 0;
383
+ StatementHandle *hStatement = getStatementHandle(self);
457
384
 
458
- offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
459
- if(offset >= 0 && offset < results->output->sqld) {
460
- XSQLVAR *var = results->output->sqlvar;
461
- int index;
385
+ offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
386
+ if(offset >= 0 && offset < hStatement->output->sqld) {
387
+ XSQLVAR *var = hStatement->output->sqlvar;
388
+ int index;
462
389
 
463
- for(index = 0; index < offset; index++, var++) ;
464
- alias = rb_str_new(var->aliasname, var->aliasname_length);
465
- }
390
+ for(index = 0; index < offset; index++, var++) ;
391
+ alias = rb_str_new(var->aliasname, var->aliasname_length);
466
392
  }
467
393
 
468
394
  return(alias);
@@ -480,21 +406,17 @@ static VALUE getResultSetColumnAlias(VALUE self, VALUE column) {
480
406
  *
481
407
  */
482
408
  static VALUE getResultSetColumnScale(VALUE self, VALUE column) {
409
+ int offset = 0;
483
410
  VALUE scale = Qnil;
484
- ResultsHandle *results = NULL;
411
+ StatementHandle *hStatement = getStatementHandle(self);
485
412
 
486
- Data_Get_Struct(self, ResultsHandle, results);
487
- if(results != NULL) {
488
- int offset = 0;
413
+ offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
414
+ if(offset >= 0 && offset < hStatement->output->sqld) {
415
+ XSQLVAR *var = hStatement->output->sqlvar;
416
+ int index;
489
417
 
490
- offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
491
- if(offset >= 0 && offset < results->output->sqld) {
492
- XSQLVAR *var = results->output->sqlvar;
493
- int index;
494
-
495
- for(index = 0; index < offset; index++, var++) ;
496
- scale = INT2FIX(var->sqlscale);
497
- }
418
+ for(index = 0; index < offset; index++, var++) ;
419
+ scale = INT2FIX(var->sqlscale);
498
420
  }
499
421
 
500
422
  return(scale);
@@ -513,21 +435,17 @@ static VALUE getResultSetColumnScale(VALUE self, VALUE column) {
513
435
  *
514
436
  */
515
437
  static VALUE getResultSetColumnTable(VALUE self, VALUE column) {
438
+ int offset = 0;
516
439
  VALUE name = Qnil;
517
- ResultsHandle *results = NULL;
518
-
519
- Data_Get_Struct(self, ResultsHandle, results);
520
- if(results != NULL) {
521
- int offset = 0;
440
+ StatementHandle *hStatement = getStatementHandle(self);
522
441
 
523
- offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
524
- if(offset >= 0 && offset < results->output->sqld) {
525
- XSQLVAR *var = results->output->sqlvar;
526
- int index;
442
+ offset = (TYPE(column) == T_FIXNUM ? FIX2INT(column) : NUM2INT(column));
443
+ if(offset >= 0 && offset < hStatement->output->sqld) {
444
+ XSQLVAR *var = hStatement->output->sqlvar;
445
+ int index;
527
446
 
528
- for(index = 0; index < offset; index++, var++) ;
529
- name = rb_str_new(var->relname, var->relname_length);
530
- }
447
+ for(index = 0; index < offset; index++, var++) ;
448
+ name = rb_str_new(var->relname, var->relname_length);
531
449
  }
532
450
 
533
451
  return(name);
@@ -548,44 +466,28 @@ static VALUE getResultSetColumnType(VALUE self, VALUE column) {
548
466
  VALUE type = toSymbol("UNKNOWN");
549
467
 
550
468
  if(TYPE(column) == T_FIXNUM) {
551
- ResultsHandle *handle = NULL;
552
-
553
- Data_Get_Struct(self, ResultsHandle, handle);
554
- if(handle != NULL) {
555
- int index = FIX2INT(column);
469
+ StatementHandle *hStatement = getStatementHandle(self);
470
+ int index = FIX2INT(column);
556
471
 
557
- /* Fix negative index values. */
558
- if(index < 0) {
559
- index = handle->output->sqln + index;
560
- }
472
+ /* Fix negative index values. */
473
+ if(index < 0) {
474
+ index = hStatement->output->sqln + index;
475
+ }
561
476
 
562
- if(index >= 0 && index < handle->output->sqln) {
563
- type = getColumnType(&handle->output->sqlvar[index]);
564
- }
477
+ if(index >= 0 && index < hStatement->output->sqln) {
478
+ type = getColumnType(&hStatement->output->sqlvar[index]);
565
479
  }
566
480
  }
567
481
 
568
-
569
482
  return(type);
570
483
  }
571
484
 
572
-
573
- /**
574
- * This function provides the each method for the ResultSet class.
575
- *
576
- * @param self A reference to the ResultSet object to execute the method for.
577
- *
578
- * @return A reference to the last value returned by the associated block or
579
- * nil.
580
- *
581
- */
582
- VALUE eachResultSetRow(VALUE self) {
485
+ VALUE yieldRows(VALUE self) {
583
486
  VALUE result = Qnil;
584
487
 
585
488
  /* Check if a block was provided. */
586
489
  if(rb_block_given_p()) {
587
490
  VALUE row;
588
-
589
491
  while((row = fetchResultSetEntry(self)) != Qnil) {
590
492
  result = rb_yield(row);
591
493
  }
@@ -594,6 +496,22 @@ VALUE eachResultSetRow(VALUE self) {
594
496
  return(result);
595
497
  }
596
498
 
499
+ VALUE yieldResultsRows(VALUE self) {
500
+ return rb_ensure(yieldRows, self, closeResultSet, self);
501
+ }
502
+
503
+ /**
504
+ * This function provides the each method for the ResultSet class.
505
+ *
506
+ * @param self A reference to the ResultSet object to execute the method for.
507
+ *
508
+ * @return A reference to the last value returned by the associated block or
509
+ * nil.
510
+ *
511
+ */
512
+ VALUE eachResultSetRow(VALUE self) {
513
+ return yieldRows(self);
514
+ }
597
515
 
598
516
  /**
599
517
  * This function provides the exhausted? method of the ResultSet class.
@@ -605,84 +523,34 @@ VALUE eachResultSetRow(VALUE self) {
605
523
  *
606
524
  */
607
525
  VALUE isResultSetExhausted(VALUE self) {
608
- VALUE exhausted = Qfalse;
609
- ResultsHandle *results = NULL;
526
+ VALUE exhausted = Qtrue;
527
+ ResultsHandle *hResults = NULL;
610
528
 
611
- Data_Get_Struct(self, ResultsHandle, results);
612
- if(results->exhausted) {
613
- exhausted = Qtrue;
529
+ Data_Get_Struct(self, ResultsHandle, hResults);
530
+ if(hResults->active) {
531
+ exhausted = Qfalse;
614
532
  }
615
533
 
616
534
  return(exhausted);
617
535
  }
618
536
 
619
537
 
620
- /**
621
- * This method integrates with the Ruby garbage collector to insure that, if
622
- * a ResultSet contains a reference to a Transaction object, it doesn't get
623
- * collected by the garbage collector unnecessarily.
624
- *
625
- * @param handle A void pointer to the structure associated with the object
626
- * being scanned by the garbage collector.
627
- *
628
- */
629
- void resultSetMark(void *handle) {
630
- ResultsHandle *results = (ResultsHandle *)handle;
631
-
632
- if(results != NULL) {
633
- if(results->transaction != Qnil) {
634
- rb_gc_mark(results->transaction);
635
- }
636
- }
637
- }
638
-
639
-
640
538
  /**
641
539
  * This function provides a programmatic means of creating a ResultSet object.
642
540
  *
643
- * @param connection A reference to a Connection object that will be used
644
- * in executing the statement.
645
- * @param transaction A reference to a Transaction object that will be used
646
- * in executing the statement.
647
- * @param sql A reference to a String containing the SQL statement to
648
- * be executed. Must be a query.
649
- * @param dialect A reference to an integer containing the SQL dialect to
650
- * be used in executing the query.
651
- * @param parameters A reference to an array containing the parameters to be
652
- * used in executing the query.
541
+ * @param statement A statement to iterate over
542
+ * @param transaction A reference to a privater transaction object
543
+ * taht should be managed by this ResultSet.
544
+ * @param owns_transaction true if the result set should manage the transaction
653
545
  *
654
546
  * @return A reference to the newly created ResultSet object.
655
547
  *
656
548
  */
657
- VALUE rb_result_set_new(VALUE connection, VALUE transaction, VALUE sql,
658
- VALUE dialect, VALUE parameters) {
549
+ VALUE rb_result_set_new(VALUE statement, VALUE transaction) {
659
550
  VALUE instance = allocateResultSet(cResultSet);
660
-
661
- initializeResultSet(instance, connection, transaction, sql, dialect,
662
- parameters);
663
-
664
- return(instance);
551
+ return (initializeResultSet(instance, statement, transaction));
665
552
  }
666
553
 
667
-
668
- /**
669
- * This function assigns an anonymous transaction to a ResultSet, giving the
670
- * object responsibility for closing it.
671
- *
672
- * @param set A reference to the ResultSet object that will be taking
673
- * ownership of the Transaction.
674
- * @param transaction A reference to the Transaction object that the ResultSet
675
- * is assuming responsibility for.
676
- *
677
- */
678
- void rb_assign_transaction(VALUE set, VALUE transaction) {
679
- ResultsHandle *results = NULL;
680
-
681
- Data_Get_Struct(set, ResultsHandle, results);
682
- results->transaction = transaction;
683
- }
684
-
685
-
686
554
  /**
687
555
  * This function integrates with the Ruby garbage collector to free all of the
688
556
  * resources for a ResultSet object that is being collected.
@@ -692,60 +560,11 @@ void rb_assign_transaction(VALUE set, VALUE transaction) {
692
560
  *
693
561
  */
694
562
  void resultSetFree(void *handle) {
695
- if(handle != NULL) {
696
- ResultsHandle *results = (ResultsHandle *)handle;
697
-
698
- if(results->handle != 0) {
699
- ISC_STATUS status[ISC_STATUS_LENGTH];
700
-
701
- /* UNCOMMENT FOR DEBUG PURPOSES! */
702
- /*fprintf(stderr, "Releasing statement handle for...\n%s\n", results->sql);*/
703
- isc_dsql_free_statement(status, &results->handle, DSQL_drop);
704
- }
705
-
706
- if(results->output != NULL) {
707
- releaseDataArea(results->output);
708
- }
709
-
710
- resolveResultsTransaction(results, "rollback");
711
- free(results);
712
- }
713
- }
714
-
715
-
716
- /**
717
- * This is a simple function to aid in the clean up of statement handles.
718
- *
719
- * @param handle A pointer to the statement handle to be cleaned up.
720
- *
721
- */
722
- void cleanupHandle(isc_stmt_handle *handle) {
723
- if(*handle != 0) {
724
- ISC_STATUS status[ISC_STATUS_LENGTH];
725
-
726
- /* UNCOMMENT FOR DEBUG PURPOSES! */
727
- /*fprintf(stderr, "Cleaning up a statement handle.\n");*/
728
- isc_dsql_free_statement(status, handle, DSQL_drop);
563
+ if(handle) {
564
+ free(handle);
729
565
  }
730
566
  }
731
567
 
732
-
733
- /**
734
- * Simple helper function to resolve ResultsHandle associated transaction
735
- *
736
- * @param results - the ResultsHandle handle
737
- *
738
- * @param resolveMethod - transaction resolving method - eg. commit, rollback
739
- *
740
- */
741
- void resolveResultsTransaction(ResultsHandle *results, char *resolveMethod) {
742
- if(results->transaction != Qnil) {
743
- rb_funcall(results->transaction, rb_intern(resolveMethod), 0);
744
- results->transaction = Qnil;
745
- }
746
- }
747
-
748
-
749
568
  /**
750
569
  * This function initializes the ResultSet class within the Ruby environment.
751
570
  * The class is established under the module specified to the function.
@@ -757,13 +576,14 @@ void Init_ResultSet(VALUE module) {
757
576
  cResultSet = rb_define_class_under(module, "ResultSet", rb_cObject);
758
577
  rb_define_alloc_func(cResultSet, allocateResultSet);
759
578
  rb_include_module(cResultSet, rb_mEnumerable);
760
- rb_define_method(cResultSet, "initialize", initializeResultSet, 5);
579
+ rb_define_method(cResultSet, "initialize", initializeResultSet, 2);
761
580
  rb_define_method(cResultSet, "initialize_copy", forbidObjectCopy, 1);
762
581
  rb_define_method(cResultSet, "row_count", getResultSetCount, 0);
763
582
  rb_define_method(cResultSet, "fetch", fetchResultSetEntry, 0);
764
583
  rb_define_method(cResultSet, "close", closeResultSet, 0);
765
584
  rb_define_method(cResultSet, "connection", getResultSetConnection, 0);
766
585
  rb_define_method(cResultSet, "transaction", getResultSetTransaction, 0);
586
+ rb_define_method(cResultSet, "statement", getResultSetStatement, 0);
767
587
  rb_define_method(cResultSet, "sql", getResultSetSQL, 0);
768
588
  rb_define_method(cResultSet, "dialect", getResultSetDialect, 0);
769
589
  rb_define_method(cResultSet, "each", eachResultSetRow, 0);