1 /*
2 * Copyright (C) 2002 - 2003 Rodrigo Moya <rodrigo@gnome-db.org>
3 * Copyright (C) 2002 Tim Coleman <tim@timcoleman.com>
4 * Copyright (C) 2003 Akira TAGOH <tagoh@gnome-db.org>
5 * Copyright (C) 2003 Gonzalo Paniagua Javier <gonzalo@src.gnome.org>
6 * Copyright (C) 2003 Laurent Sansonetti <lrz@gnome.org>
7 * Copyright (C) 2003 Steve Fosdick <fozzy@src.gnome.org>
8 * Copyright (C) 2005 - 2011 Vivien Malerba <malerba@gnome-db.org>
9 * Copyright (C) 2005 Álvaro Peña <alvaropg@telefonica.net>
10 * Copyright (C) 2007 Murray Cumming <murrayc@murrayc-desktop>
11 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the
25 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
27 */
28
29 #include <stdarg.h>
30 #include <string.h>
31 #include <glib/gi18n-lib.h>
32 #include <libgda/gda-util.h>
33 #include <libgda/gda-connection-private.h>
34 #include "gda-oracle.h"
35 #include "gda-oracle-recordset.h"
36 #include "gda-oracle-provider.h"
37 #include "gda-oracle-util.h"
38
39 #define _GDA_PSTMT(x) ((GdaPStmt*)(x))
40 #define BUFFER_SIZE 4095 /* size of the buffer to fecth data from the server using the callback API (OCIDefineDynamic) */
41
42 static void gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass);
43 static void gda_oracle_recordset_init (GdaOracleRecordset *recset,
44 GdaOracleRecordsetClass *klass);
45 static void gda_oracle_recordset_dispose (GObject *object);
46
47 /* virtual methods */
48 static gint gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model);
49 static gboolean gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
50 static gboolean gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
51
52 static GdaRow *new_row (GdaDataSelect *imodel, GdaConnection *cnc, GdaOraclePStmt *ps);
53
54 struct _GdaOracleRecordsetPrivate {
55 gint next_row_num;
56 };
57 static GObjectClass *parent_class = NULL;
58
59 #ifdef GDA_DEBUG
60 #define TS_DIFF(a,b) (((b).tv_sec * 1000000 + (b).tv_usec) - ((a).tv_sec * 1000000 + (a).tv_usec))
61 #include <sys/time.h>
62 #endif
63
64 /*
65 * Object init and finalize
66 */
67 static void
gda_oracle_recordset_init(GdaOracleRecordset * recset,GdaOracleRecordsetClass * klass)68 gda_oracle_recordset_init (GdaOracleRecordset *recset,
69 GdaOracleRecordsetClass *klass)
70 {
71 g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
72 recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
73 recset->priv->next_row_num = 0;
74 }
75
76 static void
gda_oracle_recordset_class_init(GdaOracleRecordsetClass * klass)77 gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
78 {
79 GObjectClass *object_class = G_OBJECT_CLASS (klass);
80 GdaDataSelectClass *pmodel_class = GDA_DATA_SELECT_CLASS (klass);
81
82 parent_class = g_type_class_peek_parent (klass);
83
84 object_class->dispose = gda_oracle_recordset_dispose;
85 pmodel_class->fetch_nb_rows = gda_oracle_recordset_fetch_nb_rows;
86 pmodel_class->fetch_random = gda_oracle_recordset_fetch_random;
87
88 pmodel_class->fetch_next = gda_oracle_recordset_fetch_next;
89 pmodel_class->fetch_prev = NULL;
90 pmodel_class->fetch_at = NULL;
91 }
92
93 static void
gda_oracle_recordset_dispose(GObject * object)94 gda_oracle_recordset_dispose (GObject *object)
95 {
96 GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
97
98 g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
99
100 if (recset->priv) {
101 /* free specific information */
102 g_free (recset->priv);
103 recset->priv = NULL;
104 }
105
106 parent_class->dispose (object);
107 }
108
109 /*
110 * Public functions
111 */
112
113 GType
gda_oracle_recordset_get_type(void)114 gda_oracle_recordset_get_type (void)
115 {
116 static GType type = 0;
117
118 if (G_UNLIKELY (type == 0)) {
119 static GMutex registering;
120 static const GTypeInfo info = {
121 sizeof (GdaOracleRecordsetClass),
122 (GBaseInitFunc) NULL,
123 (GBaseFinalizeFunc) NULL,
124 (GClassInitFunc) gda_oracle_recordset_class_init,
125 NULL,
126 NULL,
127 sizeof (GdaOracleRecordset),
128 0,
129 (GInstanceInitFunc) gda_oracle_recordset_init,
130 NULL
131 };
132 g_mutex_lock (®istering);
133 if (type == 0)
134 type = g_type_register_static (GDA_TYPE_DATA_SELECT, "GdaOracleRecordset", &info, 0);
135 g_mutex_unlock (®istering);
136 }
137
138 return type;
139 }
140
141 static sb4
ora_def_callback(GdaOracleValue * ora_value,OCIDefine * def,ub4 iter,dvoid ** bufpp,ub4 ** alenpp,ub1 * piecep,dvoid ** indpp,ub2 ** rcodep)142 ora_def_callback (GdaOracleValue *ora_value,
143 OCIDefine *def,
144 ub4 iter,
145 dvoid **bufpp,
146 ub4 **alenpp,
147 ub1 *piecep,
148 dvoid **indpp,
149 ub2 **rcodep)
150 {
151 *piecep = OCI_ONE_PIECE;
152
153 if (!ora_value->value) {
154 /* 1st chunk */
155 ora_value->defined_size = 0;
156 ora_value->value = g_new0 (guchar, BUFFER_SIZE + 1);
157 *bufpp = ora_value->value;
158 }
159 else {
160 /* other chunks */
161 ora_value->defined_size += ora_value->xlen; /* previous's chunk's real size */
162 #ifdef GDA_DEBUG_NO
163 gint i;
164 g_print ("XLEN= %d\n", ora_value->xlen);
165 for (i = 0 ; i < ora_value->defined_size; i++)
166 g_print ("SO FAR[%d]=[%d]%c\n", i, ((gchar*) ora_value->value)[i],
167 g_unichar_isgraph (((gchar*) ora_value->value)[i]) ? ((gchar*) ora_value->value)[i] : '-');
168 #endif
169 ora_value->value = g_renew (guchar, ora_value->value, ora_value->defined_size + BUFFER_SIZE);
170 *bufpp = ora_value->value + ora_value->defined_size;
171 }
172
173 ora_value->xlen = BUFFER_SIZE;
174 *alenpp = &(ora_value->xlen);
175 *indpp = (dvoid *) &(ora_value->indicator);
176 *rcodep = (ub2 *) &(ora_value->rcode);
177
178 return OCI_CONTINUE;
179 }
180
181 /*
182 * the @ps struct is modified and transferred to the new data model created in
183 * this function
184 */
185 GdaDataModel *
gda_oracle_recordset_new(GdaConnection * cnc,GdaOraclePStmt * ps,GdaSet * exec_params,GdaDataModelAccessFlags flags,GType * col_types)186 gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
187 GdaDataModelAccessFlags flags, GType *col_types)
188 {
189 GdaOracleRecordset *model;
190 OracleConnectionData *cdata;
191 gint i;
192 GdaDataModelAccessFlags rflags;
193
194 gint nb_rows = -1;
195
196 g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
197 g_return_val_if_fail (ps != NULL, NULL);
198
199 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
200 if (!cdata)
201 return NULL;
202
203 /* make sure @ps reports the correct number of columns using the API */
204 if (_GDA_PSTMT (ps)->ncols < 0) {
205 ub4 ncolumns;
206 int result;
207
208 /* get the number of columns in the result set */
209 result = OCIAttrGet ((dvoid *) ps->hstmt,
210 (ub4) OCI_HTYPE_STMT,
211 (dvoid *) &ncolumns,
212 (ub4 *) 0,
213 (ub4) OCI_ATTR_PARAM_COUNT,
214 cdata->herr);
215 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
216 _("Could not get the number of columns in the result set")))
217 return NULL;
218
219 _GDA_PSTMT (ps)->ncols = ncolumns;
220 }
221
222 /* completing @ps if not yet done */
223 if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
224 /* create prepared statement's columns */
225 GSList *list;
226 GList *ora_values = NULL;
227
228 for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
229 _GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns,
230 gda_column_new ());
231 _GDA_PSTMT (ps)->tmpl_columns = g_slist_reverse (_GDA_PSTMT (ps)->tmpl_columns);
232
233 /* create prepared statement's types, all types are initialized to GDA_TYPE_NULL */
234 _GDA_PSTMT (ps)->types = g_new (GType, _GDA_PSTMT (ps)->ncols);
235 for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
236 _GDA_PSTMT (ps)->types [i] = GDA_TYPE_NULL;
237
238 if (col_types) {
239 for (i = 0; ; i++) {
240 if (col_types [i] > 0) {
241 if (col_types [i] == G_TYPE_NONE)
242 break;
243 if (i >= _GDA_PSTMT (ps)->ncols) {
244 g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
245 _GDA_PSTMT (ps)->ncols - 1);
246 break;
247 }
248 else
249 _GDA_PSTMT (ps)->types [i] = col_types [i];
250 }
251 }
252 }
253
254 /* fill GdaColumn's data and define the GdaOracleValue structures */
255 for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns;
256 i < GDA_PSTMT (ps)->ncols;
257 i++, list = list->next) {
258 GdaColumn *column;
259 int result;
260 GdaOracleValue *ora_value;
261 gboolean use_callback = FALSE;
262
263 ora_value = g_new0 (GdaOracleValue, 1);
264 ora_values = g_list_prepend (ora_values, ora_value);
265
266 /* parameter to get attributes */
267 result = OCIParamGet (ps->hstmt,
268 OCI_HTYPE_STMT,
269 cdata->herr,
270 (dvoid **) &(ora_value->pard),
271 (ub4) i+1);
272 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
273 _("Could not get the Oracle parameter descripter in the result set"))) {
274 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
275 return NULL;
276 }
277
278 /* data size */
279 result = OCIAttrGet ((dvoid *) (ora_value->pard),
280 OCI_DTYPE_PARAM,
281 &(ora_value->defined_size),
282 0,
283 (ub4) OCI_ATTR_DATA_SIZE,
284 cdata->herr);
285 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
286 _("Could not get the parameter defined size"))) {
287 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
288 return NULL;
289 }
290 ora_value->defined_size++;
291
292 /* data type */
293 result = OCIAttrGet ((dvoid *) (ora_value->pard),
294 OCI_DTYPE_PARAM,
295 &(ora_value->sql_type),
296 0,
297 OCI_ATTR_DATA_TYPE,
298 cdata->herr);
299 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
300 _("Could not get the parameter data type"))) {
301 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
302 return NULL;
303 }
304
305 result = OCIAttrGet ((dvoid *) (ora_value->pard),
306 OCI_DTYPE_PARAM,
307 &(ora_value->precision),
308 0,
309 OCI_ATTR_PRECISION,
310 cdata->herr);
311 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
312 _("Could not get the type's precision"))) {
313 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
314 return NULL;
315 }
316
317 result = OCIAttrGet ((dvoid *) (ora_value->pard),
318 OCI_DTYPE_PARAM,
319 &(ora_value->scale),
320 0,
321 OCI_ATTR_SCALE,
322 cdata->herr);
323 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
324 _("Could not get the type's scale"))) {
325 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
326 return NULL;
327 }
328
329 /* column's name */
330 text *name;
331 ub4 name_len;
332
333 column = GDA_COLUMN (list->data);
334 result = OCIAttrGet ((dvoid *) (ora_value->pard),
335 (ub4) OCI_DTYPE_PARAM,
336 (dvoid **) &name,
337 (ub4 *) &name_len,
338 (ub4) OCI_ATTR_NAME,
339 (OCIError *) cdata->herr);
340 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
341 _("Could not get column name in the result set"))) {
342 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
343 return NULL;
344 }
345
346 gchar *name_buffer;
347 name_buffer = g_new (gchar, name_len + 1);
348 memcpy (name_buffer, name, name_len);
349 name_buffer [name_len] = '\0';
350 gda_column_set_name (column, name_buffer);
351 gda_column_set_description (column, name_buffer);
352 g_free (name_buffer);
353
354 /* for data fetching */
355 if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
356 ora_value->sql_type = _g_type_to_oracle_sqltype (_GDA_PSTMT (ps)->types [i]);
357
358 switch (ora_value->sql_type) {
359 case SQLT_CHR: /* for G_TYPE_STRING => request SQLT_CHR */
360 case SQLT_STR:
361 case SQLT_VCS:
362 case SQLT_RID:
363 case SQLT_AVC:
364 case SQLT_AFC:
365 ora_value->sql_type = SQLT_CHR;
366 if (ora_value->defined_size == 1)
367 use_callback = TRUE;
368 break;
369
370 case SQLT_INT:
371 ora_value->defined_size = sizeof (gint);
372 break;
373
374 case SQLT_FLT:
375 case SQLT_BFLOAT:
376 ora_value->defined_size = sizeof (gfloat);
377 break;
378
379 case SQLT_BDOUBLE:
380 ora_value->defined_size = sizeof (gdouble);
381 break;
382
383 case SQLT_DAT: /* request OCIDate */
384 ora_value->sql_type = SQLT_ODT;
385 break;
386
387 case SQLT_NUM: /* for GDA_TYPE_NUMERIC => request SQLT_CHR */
388 case SQLT_VNU:
389 ora_value->sql_type = SQLT_CHR;
390 break;
391
392 case SQLT_LBI:
393 case SQLT_LVB:
394 case SQLT_LVC:
395 case SQLT_LNG:
396 case SQLT_VBI:
397 case SQLT_BIN:
398 use_callback = TRUE;
399 break;
400 default:
401 use_callback = TRUE;
402 break;
403 }
404
405 if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
406 ora_value->g_type = _GDA_PSTMT (ps)->types [i];
407 else
408 ora_value->g_type = _oracle_sqltype_to_g_type (ora_value->sql_type, ora_value->precision,
409 ora_value->scale);
410
411 if (ora_value->g_type == GDA_TYPE_BLOB) {
412 /* allocate a Lob locator */
413 OCILobLocator *lob;
414
415 result = OCIDescriptorAlloc ((dvoid *) cdata->henv, (dvoid **) &lob,
416 (ub4) gda_oracle_blob_type (ora_value->sql_type),
417 (size_t) 0, (dvoid **) 0);
418 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
419 _("Could not allocate Lob locator"))) {
420 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
421 return NULL;
422 }
423 ora_value->value = lob;
424 ora_value->defined_size = 0;
425 }
426 else if (use_callback) {
427 ora_value->value = NULL;
428 ora_value->defined_size = 33554432; /* 32M */
429 }
430 else
431 ora_value->value = g_malloc0 (ora_value->defined_size);
432
433 ora_value->s_type = gda_g_type_to_static_type (ora_value->g_type);
434 if (_GDA_PSTMT (ps)->types [i] == GDA_TYPE_NULL)
435 _GDA_PSTMT (ps)->types [i] = ora_value->g_type;
436 gda_column_set_g_type (column, ora_value->g_type);
437
438 #ifdef GDA_DEBUG_NO
439 g_print ("**COL type is %d, GType is %s, ORA defined size is %d%s\n",
440 ora_value->sql_type,
441 g_type_name (ora_value->g_type),
442 ora_value->defined_size - 1,
443 use_callback ? " using callback": "");
444 #endif
445
446 ora_value->hdef = (OCIDefine *) 0;
447 ora_value->indicator = 0;
448 result = OCIDefineByPos ((OCIStmt *) ps->hstmt,
449 (OCIDefine **) &(ora_value->hdef),
450 (OCIError *) cdata->herr,
451 (ub4) i + 1,
452 ora_value->value,
453 ora_value->defined_size,
454 ora_value->sql_type,
455 (dvoid *) &(ora_value->indicator),
456 &(ora_value->rlen),
457 &(ora_value->rcode),
458 (ub4) (use_callback ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
459 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
460 _("Could not define by position"))) {
461 OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
462 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
463 return NULL;
464 }
465
466 if (use_callback) {
467 result = OCIDefineDynamic ((OCIDefine *) (ora_value->hdef),
468 (OCIError *) (cdata->herr),
469 (dvoid*) (ora_value),
470 (OCICallbackDefine) ora_def_callback);
471 if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
472 _("Could not define by position"))) {
473 OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
474 g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
475 return NULL;
476 }
477 }
478
479 ora_value->use_callback = use_callback;
480 }
481
482 ps->ora_values = g_list_reverse (ora_values);
483 }
484
485 /* determine access mode: RANDOM or CURSOR FORWARD are the only supported; if CURSOR BACKWARD
486 * is requested, then we need RANDOM mode */
487 if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
488 rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
489 else if (flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD)
490 rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
491 else
492 rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
493
494 ub4 prefetch;
495 prefetch = (ub4) (100);
496 OCIAttrSet (ps->hstmt, OCI_HTYPE_STMT,
497 &prefetch, 0,
498 OCI_ATTR_PREFETCH_ROWS, cdata->herr);
499
500 /* create data model */
501 model = g_object_new (GDA_TYPE_ORACLE_RECORDSET,
502 "connection", cnc,
503 "prepared-stmt", ps,
504 "model-usage", rflags,
505 "exec-params", exec_params, NULL);
506 GDA_DATA_SELECT (model)->advertized_nrows = nb_rows;
507
508 return GDA_DATA_MODEL (model);
509 }
510
511 static GdaRow *
fetch_next_oracle_row(GdaOracleRecordset * model,G_GNUC_UNUSED gboolean do_store,GError ** error)512 fetch_next_oracle_row (GdaOracleRecordset *model, G_GNUC_UNUSED gboolean do_store, GError **error)
513 {
514 int result;
515 GdaRow *prow = NULL;
516 GdaOraclePStmt *ps = GDA_ORACLE_PSTMT (((GdaDataSelect*)model)->prep_stmt);
517 OracleConnectionData *cdata;
518 GdaConnection *cnc;
519
520 cnc = gda_data_select_get_connection ((GdaDataSelect*) model);
521 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
522 if (!cdata)
523 return NULL;
524
525 /* fetch row */
526 if (cdata->major_version > 9)
527 result = OCIStmtFetch2 (ps->hstmt,
528 cdata->herr,
529 (ub4) 1,
530 (ub2) OCI_FETCH_NEXT,
531 (sb4) 1,
532 (ub4) OCI_DEFAULT);
533 else
534 result = OCIStmtFetch (ps->hstmt,
535 cdata->herr,
536 (ub4) 1,
537 (ub2) OCI_FETCH_NEXT,
538 (ub4) OCI_DEFAULT);
539 if (result == OCI_NO_DATA) {
540 GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
541 return NULL;
542 }
543 else {
544 GdaConnectionEvent *event;
545 if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
546 _("Could not fetch next row")))) {
547 /* set @error */
548 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
549 "%s", gda_connection_event_get_description (event));
550
551 return NULL;
552 }
553 }
554
555 prow = new_row ((GdaDataSelect*) model, cnc, ps);
556 gda_data_select_take_row ((GdaDataSelect*) model, prow, model->priv->next_row_num);
557 model->priv->next_row_num ++;
558
559 return prow;
560 }
561
562
563 /*
564 * Get the number of rows in @model, if possible
565 */
566 static gint
gda_oracle_recordset_fetch_nb_rows(GdaDataSelect * model)567 gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
568 {
569 GdaOracleRecordset *imodel;
570 GdaRow *prow = NULL;
571
572 imodel = GDA_ORACLE_RECORDSET (model);
573 if (model->advertized_nrows >= 0)
574 return model->advertized_nrows;
575
576 struct timeval stm1, stm2;
577
578 gettimeofday (&stm1, NULL);
579
580 for (prow = fetch_next_oracle_row (imodel, TRUE, NULL);
581 prow;
582 prow = fetch_next_oracle_row (imodel, TRUE, NULL));
583
584 gettimeofday (&stm2, NULL);
585 /*g_print ("TOTAL time to get nb rows: %0.2f ms\n", (float) (TS_DIFF(stm1,stm2) / 1000.));*/
586
587 return model->advertized_nrows;
588 }
589
590 /*
591 * Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
592 *
593 * Each new #GdaRow created needs to be "given" to the #GdaDataSelect implementation using
594 * gda_data_select_take_row() because backward iterating is not supported.
595 */
596 static gboolean
gda_oracle_recordset_fetch_random(GdaDataSelect * model,GdaRow ** prow,gint rownum,GError ** error)597 gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
598 {
599 GdaOracleRecordset *imodel;
600 OracleConnectionData *cdata;
601 GdaConnection *cnc;
602
603 imodel = GDA_ORACLE_RECORDSET (model);
604 cnc = gda_data_select_get_connection (model);
605 cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
606 if (!cdata)
607 return TRUE;
608
609 if (imodel->priv->next_row_num >= rownum) {
610 g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
611 GDA_SERVER_PROVIDER_INTERNAL_ERROR,
612 "%s", _("Requested row could not be found"));
613 return TRUE;
614 }
615 for (*prow = fetch_next_oracle_row (imodel, TRUE, error);
616 *prow && (imodel->priv->next_row_num < rownum);
617 *prow = fetch_next_oracle_row (imodel, TRUE, error));
618
619 return TRUE;
620 }
621
622 /*
623 * Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
624 *
625 * Each new #GdaRow created needs to be "given" to the #GdaDataSelect implementation using
626 * gda_data_select_take_row() because backward iterating is not supported.
627 */
628 static gboolean
gda_oracle_recordset_fetch_next(GdaDataSelect * model,GdaRow ** prow,gint rownum,GError ** error)629 gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
630 {
631 GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
632
633 if (imodel->priv->next_row_num != rownum) {
634 GError *lerror = NULL;
635 *prow = NULL;
636 g_set_error (&lerror, GDA_DATA_MODEL_ERROR,
637 GDA_DATA_MODEL_ROW_NOT_FOUND_ERROR,
638 "%s", _("Can't set iterator on requested row"));
639 gda_data_select_add_exception (GDA_DATA_SELECT (model), lerror);
640 if (error)
641 g_propagate_error (error, g_error_copy (lerror));
642 return TRUE;
643 }
644 *prow = fetch_next_oracle_row ((GdaOracleRecordset*) model, TRUE, error);
645 return TRUE;
646 }
647
648
649 /* create a new GdaRow from the last read row */
650 static GdaRow *
new_row(GdaDataSelect * imodel,GdaConnection * cnc,GdaOraclePStmt * ps)651 new_row (GdaDataSelect *imodel, GdaConnection *cnc, GdaOraclePStmt *ps)
652 {
653 GdaRow *prow;
654 GList *nodes;
655 gint i;
656
657 prow = gda_row_new (((GdaDataSelect*) imodel)->prep_stmt->ncols);
658 for (i = 0, nodes = ps->ora_values;
659 nodes;
660 i++, nodes = nodes->next) {
661 GdaOracleValue *ora_value = (GdaOracleValue *) nodes->data;
662 GValue *value = gda_row_get_value (prow, i);
663 _gda_oracle_set_value (value, ora_value, cnc);
664 }
665
666 return prow;
667 }
668