CUBRID Engine  latest
cursor.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * esql_cursor.c - cursor manager
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "error_manager.h"
32 #include "storage_common.h"
33 #include "memory_alloc.h"
34 #include "object_primitive.h"
35 #include "object_representation.h"
36 #include "db.h"
37 #include "locator_cl.h"
38 #include "server_interface.h"
39 #include "work_space.h"
40 #include "set_object.h"
41 #include "cursor.h"
42 #include "parser_support.h"
43 #include "virtual_object.h"
44 #include "network_interface_cl.h"
45 #include "dbtype.h"
46 
47 #define CURSOR_BUFFER_SIZE DB_PAGESIZE
48 #define CURSOR_BUFFER_AREA_SIZE IO_MAX_PAGE_SIZE
49 
50 enum
51 {
52  FIRST_TPL = -1,
53  LAST_TPL = -2
54 };
55 
57 static bool cursor_has_set_vobjs (DB_SET * set);
58 static int cursor_fixup_set_vobjs (DB_VALUE * value);
59 static int cursor_fixup_vobjs (DB_VALUE * val);
61  DB_VALUE * db_value, bool copy);
62 static int cursor_get_tuple_value_from_list (CURSOR_ID * c_id, int index, DB_VALUE * value, char *tuple);
63 static int cursor_get_first_tuple_value (char *tuple, QFILE_TUPLE_VALUE_TYPE_LIST * type_list, DB_VALUE * value,
64  bool copy);
65 static char *cursor_peek_tuple (CURSOR_ID * cursor_id);
67 static OID *cursor_get_oid_from_vobj (OID * current_oid_p, int length);
68 static OID *cursor_get_oid_from_tuple (char *tuple_p, DB_TYPE type);
69 static int cursor_allocate_tuple_area (CURSOR_ID * cursor_id_p, int tuple_length);
70 static int cursor_construct_tuple_from_overflow_pages (CURSOR_ID * cursor_id_p, VPID * vpid_p);
71 static bool cursor_has_first_hidden_oid (CURSOR_ID * cursor_id_p);
72 static int cursor_fetch_oids (CURSOR_ID * cursor_id_p, int oid_index, DB_FETCH_MODE instant_fetch_mode,
73  DB_FETCH_MODE class_fetch_mode);
74 static int cursor_prefetch_first_hidden_oid (CURSOR_ID * cursor_id_p);
75 static int cursor_prefetch_column_oids (CURSOR_ID * cursor_id_p);
76 static int cursor_point_current_tuple (CURSOR_ID * cursor_id_p, int position, int offset);
77 static int cursor_buffer_last_page (CURSOR_ID * cursor_id_p, VPID * vpid_p);
78 static void cursor_allocate_oid_buffer (CURSOR_ID * cursor_id_p);
79 
80 /*
81  * List File routines
82  */
83 
84 static void
86 {
87  if (cursor_id_p == NULL)
88  {
89  assert (0);
90  return;
91  }
92 
93  cursor_id_p->current_tuple_value_index = -1;
94  cursor_id_p->current_tuple_value_p = NULL;
95 }
96 
97 /*
98  * cursor_copy_list_id () - Copy source list identifier into destination
99  * list identifier
100  * return: true on ok, false otherwise
101  * dest_list_id(out): Destination list identifier
102  * src_list_id(in): Source list identifier
103  */
104 int
105 cursor_copy_list_id (QFILE_LIST_ID * dest_list_id_p, const QFILE_LIST_ID * src_list_id_p)
106 {
107  size_t size;
108  QFILE_TUPLE_VALUE_TYPE_LIST *dest_type_list_p;
109  const QFILE_TUPLE_VALUE_TYPE_LIST *src_type_list_p;
110 
111  memcpy (dest_list_id_p, src_list_id_p, DB_SIZEOF (QFILE_LIST_ID));
112 
113  src_type_list_p = &(src_list_id_p->type_list);
114  dest_type_list_p = &(dest_list_id_p->type_list);
115 
116  dest_list_id_p->type_list.domp = NULL;
117  if (src_list_id_p->type_list.type_cnt)
118  {
119  size = src_type_list_p->type_cnt * sizeof (TP_DOMAIN *);
120  dest_type_list_p->domp = (TP_DOMAIN **) malloc (size);
121 
122  if (dest_type_list_p->domp == NULL)
123  {
124  return ER_FAILED;
125  }
126  memcpy (dest_type_list_p->domp, src_type_list_p->domp, size);
127  }
128 
129  dest_list_id_p->tpl_descr.f_valp = NULL;
130  dest_list_id_p->tpl_descr.clear_f_val_at_clone_decache = NULL;
131  dest_list_id_p->sort_list = NULL; /* never use sort_list in crs_ level */
132 
133  if (src_list_id_p->last_pgptr)
134  {
135  dest_list_id_p->last_pgptr = (PAGE_PTR) malloc (CURSOR_BUFFER_SIZE);
136  if (dest_list_id_p->last_pgptr == NULL)
137  {
138  return ER_FAILED;
139  }
140 
141  memcpy (dest_list_id_p->last_pgptr, src_list_id_p->last_pgptr, CURSOR_BUFFER_SIZE);
142  }
143 
144  return NO_ERROR;
145 }
146 
147 /*
148  * cursor_has_set_vobjs () -
149  * return: nonzero iff set has some vobjs, zero otherwise
150  * seq(in): set/sequence db_value
151  */
152 static bool
154 {
155  int i, size;
156  DB_VALUE element;
157 
158  size = db_set_size (set);
159 
160  for (i = 0; i < size; i++)
161  {
162  if (db_set_get (set, i, &element) != NO_ERROR)
163  {
164  return false;
165  }
166 
167  if (DB_VALUE_TYPE (&element) == DB_TYPE_VOBJ)
168  {
169  pr_clear_value (&element);
170  return true;
171  }
172 
173  pr_clear_value (&element);
174  }
175 
176  return false;
177 }
178 
179 /*
180  * cursor_fixup_set_vobjs() - if val is a set/seq of vobjs then
181  * turn it into a set/seq of vmops
182  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
183  * val(in/out): a db_value
184  */
185 static int
187 {
188  DB_TYPE type;
189  int rc, i, size;
190  DB_VALUE element;
191  DB_SET *set, *new_set;
192 
193  type = DB_VALUE_TYPE (value_p);
194  if (!pr_is_set_type (type))
195  {
196  return ER_FAILED;
197  }
198 
199  set = db_get_set (value_p);
200  size = db_set_size (set);
201 
202  if (cursor_has_set_vobjs (set) == false)
203  {
204  return set_convert_oids_to_objects (set);
205  }
206 
207  switch (type)
208  {
209  case DB_TYPE_SET:
210  new_set = db_set_create_basic (NULL, NULL);
211  break;
212  case DB_TYPE_MULTISET:
213  new_set = db_set_create_multi (NULL, NULL);
214  break;
215  case DB_TYPE_SEQUENCE:
216  new_set = db_seq_create (NULL, NULL, size);
217  break;
218  default:
219  return ER_FAILED;
220  }
221 
222  /* fixup element vobjs into vmops and add them to new */
223  for (i = 0; i < size; i++)
224  {
225  if (db_set_get (set, i, &element) != NO_ERROR)
226  {
227  db_set_free (new_set);
228  return ER_FAILED;
229  }
230 
231  if (cursor_fixup_vobjs (&element) != NO_ERROR)
232  {
233  db_set_free (new_set);
234  return ER_FAILED;
235  }
236 
237  if (type == DB_TYPE_SEQUENCE)
238  {
239  rc = db_seq_put (new_set, i, &element);
240  }
241  else
242  {
243  rc = db_set_add (new_set, &element);
244  }
245 
246  if (rc != NO_ERROR)
247  {
248  db_set_free (new_set);
249  return ER_FAILED;
250  }
251  }
252 
253  pr_clear_value (value_p);
254 
255  switch (type)
256  {
257  case DB_TYPE_SET:
258  db_make_set (value_p, new_set);
259  break;
260  case DB_TYPE_MULTISET:
261  db_make_multiset (value_p, new_set);
262  break;
263  case DB_TYPE_SEQUENCE:
264  db_make_sequence (value_p, new_set);
265  break;
266  default:
267  db_set_free (new_set);
268  return ER_FAILED;
269  }
270 
271  return NO_ERROR;
272 }
273 
274 /*
275  * cursor_fixup_vobjs () -
276  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
277  * value(in/out): a db_value
278  * Note: if value is an OID then turn it into an OBJECT type value
279  * if value is a VOBJ then turn it into a vmop
280  * if value is a set/seq then do same fixups on its elements
281  */
282 static int
284 {
285  DB_OBJECT *obj;
286  int rc;
287 
288  switch (DB_VALUE_DOMAIN_TYPE (value_p))
289  {
290  case DB_TYPE_OID:
291  rc = vid_oid_to_object (value_p, &obj);
292  db_make_object (value_p, obj);
293  break;
294 
295  case DB_TYPE_VOBJ:
296  if (DB_IS_NULL (value_p))
297  {
298  db_value_clear (value_p);
300  rc = NO_ERROR;
301  }
302  else
303  {
304  rc = vid_vobj_to_object (value_p, &obj);
305  pr_clear_value (value_p);
306  db_make_object (value_p, obj);
307  }
308  break;
309 
310  case DB_TYPE_SET:
311  case DB_TYPE_MULTISET:
312  case DB_TYPE_SEQUENCE:
313  /* fixup any set/seq of vobjs into a set/seq of vmops */
314  rc = cursor_fixup_set_vobjs (value_p);
315  value_p->need_clear = true;
316  break;
317 
318  default:
319  rc = NO_ERROR;
320  break;
321  }
322 
323  return rc;
324 }
325 
326 /*
327  * cursor_copy_vobj_to_dbvalue - The given tuple set value which is in disk
328  * representation form is copied to the db_value structure
329  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
330  * buf(in) : Pointer to set disk representation
331  * db_value(out) : Set to the set value
332  */
333 int
334 cursor_copy_vobj_to_dbvalue (struct or_buf *buffer_p, DB_VALUE * value_p)
335 {
336  int rc;
337  DB_VALUE vobj_dbval;
338  DB_OBJECT *object_p;
339  PR_TYPE *pr_type;
340 
341  pr_type = pr_type_from_id (DB_TYPE_VOBJ);
342  if (pr_type == NULL)
343  {
344  return ER_FAILED;
345  }
346 
347  if (db_value_domain_init (&vobj_dbval, pr_type->id, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE) != NO_ERROR)
348  {
349  return ER_FAILED;
350  }
351 
352  if (pr_type->data_readval (buffer_p, &vobj_dbval, NULL, -1, true, NULL, 0) != NO_ERROR)
353  {
354  return ER_FAILED;
355  }
356 
357  /* convert the vobj into a vmop */
358  rc = vid_vobj_to_object (&vobj_dbval, &object_p);
359  db_make_object (value_p, object_p);
360  pr_clear_value (&vobj_dbval);
361 
362  return rc;
363 }
364 
365 /*
366  * cursor_get_tuple_value_to_dbvalue () - The given tuple value which is in disk
367  * representation form is copied/peeked to the db_value structure
368  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
369  * buf(in) : Pointer to the tuple value
370  * dom(in) : Domain for the tpl column
371  * val_flag(in) : Flag to indicate if tuple value is bound
372  * db_value(out) : Set to the tuple value
373  * copy(in) : Indicator for copy/peek
374  */
375 static int
377  DB_VALUE * value_p, bool is_copy)
378 {
379  PR_TYPE *pr_type;
380  DB_TYPE type;
381 
382  pr_type = domain_p->type;
383  if (pr_type == NULL)
384  {
385  return ER_FAILED;
386  }
387 
388  type = pr_type->id;
389  if (value_flag == V_UNBOUND)
390  {
391  db_value_domain_init (value_p, type, domain_p->precision, domain_p->scale);
392  return NO_ERROR;
393  }
394 
395  /* VOBJs must be handled separately */
396  if (type == DB_TYPE_VOBJ)
397  {
398  return cursor_copy_vobj_to_dbvalue (buffer_p, value_p);
399  }
400 
401  /* for all other types, we can use the prim routines */
402  if (pr_type->data_readval (buffer_p, value_p, domain_p, -1, is_copy, NULL, 0) != NO_ERROR)
403  {
404  return ER_FAILED;
405  }
406 
407  /*
408  * OIDs must be turned into objects.
409  * VOBJs must be turned into vmops.
410  */
411  return cursor_fixup_vobjs (value_p);
412 
413 }
414 
415 /*
416  * cursor_get_tuple_value_from_list () - The tuple value at the indicated position is
417  * extracted and mapped to given db_value
418  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
419  * c_id(in) : Cursor Identifier
420  * index(in) : Tuple Value index
421  * value(out) : Set to the fetched tuple value
422  * tuple(in) : List file tuple
423  */
424 static int
425 cursor_get_tuple_value_from_list (CURSOR_ID * cursor_id_p, int index, DB_VALUE * value_p, char *tuple_p)
426 {
427  QFILE_TUPLE_VALUE_TYPE_LIST *type_list_p;
429  OR_BUF buffer;
430  int i;
431 
432  if (cursor_id_p == NULL)
433  {
434  assert (0);
435  return ER_FAILED;
436  }
437 
438  type_list_p = &cursor_id_p->list_id.type_list;
439 
440  assert (index >= 0 && index < type_list_p->type_cnt);
441 
442  or_init (&buffer, tuple_p, QFILE_GET_TUPLE_LENGTH (tuple_p));
443 
444  /* check for saved tplvalue position info */
445  if (cursor_id_p->current_tuple_value_index >= 0 && cursor_id_p->current_tuple_value_index <= index
446  && cursor_id_p->current_tuple_value_p != NULL)
447  {
448  i = cursor_id_p->current_tuple_value_index;
449  tuple_p = cursor_id_p->current_tuple_value_p;
450  }
451  else
452  {
453  i = 0;
454  tuple_p += QFILE_TUPLE_LENGTH_SIZE;
455  }
456 
457  for (; i < index; i++)
458  {
460  }
461 
462  /* save index-th tplvalue position info */
463  cursor_id_p->current_tuple_value_index = i;
464  cursor_id_p->current_tuple_value_p = tuple_p;
465 
466  flag = QFILE_GET_TUPLE_VALUE_FLAG (tuple_p);
468  buffer.ptr = tuple_p;
469 
470  return cursor_get_tuple_value_to_dbvalue (&buffer, type_list_p->domp[i], flag, value_p,
471  cursor_id_p->is_copy_tuple_value);
472 }
473 
474 /*
475  * cursor_get_first_tuple_value () - First tuple value is extracted and mapped to
476  * given db_value
477  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
478  * tuple(in): List file tuple
479  * type_list(in): Type List
480  * value(out): Set to the first tuple value
481  * copy(in): Indicator for copy/peek
482  */
483 static int
484 cursor_get_first_tuple_value (char *tuple_p, QFILE_TUPLE_VALUE_TYPE_LIST * type_list_p, DB_VALUE * value_p,
485  bool is_copy)
486 {
488  OR_BUF buffer;
489 
490  or_init (&buffer, tuple_p, QFILE_GET_TUPLE_LENGTH (tuple_p));
491 
492  tuple_p = (char *) tuple_p + QFILE_TUPLE_LENGTH_SIZE;
493  flag = QFILE_GET_TUPLE_VALUE_FLAG (tuple_p);
495  buffer.ptr = tuple_p;
496 
497  return cursor_get_tuple_value_to_dbvalue (&buffer, type_list_p->domp[0], flag, value_p, is_copy);
498 }
499 
500 /*
501  * cursor_get_list_file_page () -
502  * return:
503  * cursor_id(in/out): Cursor identifier
504  * vpid(in):
505  */
506 static int
507 cursor_get_list_file_page (CURSOR_ID * cursor_id_p, VPID * vpid_p)
508 {
509  VPID in_vpid;
510  int page_size;
511  char *page_p;
512 
513  if (cursor_id_p == NULL || vpid_p == NULL)
514  {
515  assert (0);
516  return ER_FAILED;
517  }
518 
519  /* find page at buffer area */
520  if (VPID_EQ (vpid_p, &cursor_id_p->current_vpid))
521  {
522  /*
523  * current_vpid can indicate one of pages in buffer area,
524  * so do not assign buffer as head of buffer area
525  */
526  ;
527  }
528  else
529  {
530  cursor_id_p->buffer = NULL;
531  if (cursor_id_p->buffer_filled_size > 0)
532  {
533  /* it received a page from server */
534  if (VPID_EQ (vpid_p, &cursor_id_p->header_vpid))
535  {
536  /* in case of header vpid in buffer area */
537  cursor_id_p->buffer = cursor_id_p->buffer_area;
538  }
539  else
540  {
541  page_p = cursor_id_p->buffer_area;
542  page_size = 0;
543 
544  while (page_size < (cursor_id_p->buffer_filled_size - CURSOR_BUFFER_SIZE))
545  {
546  if (QFILE_GET_OVERFLOW_PAGE_ID (page_p) == NULL_PAGEID)
547  {
548  QFILE_GET_NEXT_VPID (&in_vpid, page_p);
549  }
550  else
551  {
552  QFILE_GET_OVERFLOW_VPID (&in_vpid, page_p);
553  }
554 
555  if (VPID_ISNULL (&in_vpid))
556  {
557  break;
558  }
559  else if (VPID_EQ (vpid_p, &in_vpid))
560  {
561  cursor_id_p->buffer = page_p + CURSOR_BUFFER_SIZE;
562  break;
563  }
564 
565  page_p += CURSOR_BUFFER_SIZE;
566  page_size += CURSOR_BUFFER_SIZE;
567  }
568  }
569  }
570  }
571 
572  /* if not found, get the page from server */
573  if (cursor_id_p->buffer == NULL)
574  {
575  int ret_val;
576 
577  ret_val = qfile_get_list_file_page (cursor_id_p->query_id, vpid_p->volid, vpid_p->pageid,
578  cursor_id_p->buffer_area, &cursor_id_p->buffer_filled_size);
579  if (ret_val != NO_ERROR)
580  {
581  return ret_val;
582  }
583 
584  cursor_id_p->buffer = cursor_id_p->buffer_area;
585  QFILE_COPY_VPID (&cursor_id_p->header_vpid, vpid_p);
586  }
587 
588  return NO_ERROR;
589 }
590 
591 static OID *
592 cursor_get_oid_from_vobj (OID * current_oid_p, int length)
593 {
594  char *vobject_p;
595  OR_BUF buffer;
596  DB_VALUE value;
597  DB_OBJECT *object_p, *tmp_object_p;
598 
599  vobject_p = (char *) current_oid_p;
600  current_oid_p = NULL;
601  or_init (&buffer, vobject_p, length);
602  db_make_null (&value);
603 
604  if (cursor_copy_vobj_to_dbvalue (&buffer, &value) == NO_ERROR)
605  {
606  tmp_object_p = db_get_object (&value);
607 
608  if (vid_is_updatable (tmp_object_p) == true)
609  {
610  object_p = vid_base_instance (tmp_object_p);
611 
612  if (object_p && !WS_ISVID (object_p))
613  {
614  current_oid_p = WS_OID (object_p);
615  }
616  }
617  }
618 
619  return current_oid_p;
620 }
621 
622 static OID *
623 cursor_get_oid_from_tuple (char *tuple_p, DB_TYPE type)
624 {
625  OID *current_oid_p;
626  int length;
627 
628  length = QFILE_GET_TUPLE_VALUE_LENGTH (tuple_p);
629  current_oid_p = (OID *) ((char *) tuple_p + QFILE_TUPLE_VALUE_HEADER_SIZE);
630 
631  if (type == DB_TYPE_VOBJ)
632  {
633  return cursor_get_oid_from_vobj (current_oid_p, length);
634  }
635 
636  return current_oid_p;
637 }
638 
639 static int
640 cursor_allocate_tuple_area (CURSOR_ID * cursor_id_p, int tuple_length)
641 {
642  if (cursor_id_p == NULL)
643  {
644  assert (0);
645  return ER_FAILED;
646  }
647 
648  if (cursor_id_p->tuple_record.size == 0)
649  {
650  cursor_id_p->tuple_record.tpl = (char *) malloc (tuple_length);
651  }
652  else
653  {
654  cursor_id_p->tuple_record.tpl = (char *) realloc (cursor_id_p->tuple_record.tpl, tuple_length);
655  }
656 
657  if (cursor_id_p->tuple_record.tpl == NULL)
658  {
659  return ER_FAILED;
660  }
661 
662  cursor_id_p->tuple_record.size = tuple_length;
663  return NO_ERROR;
664 }
665 
666 static int
668 {
669  VPID overflow_vpid;
670  char *buffer_p;
671  char *tmp_tuple_p, *tuple_p;
672  int tuple_length, offset, tuple_page_size;
673 
674  if (cursor_id_p == NULL || vpid_p == NULL)
675  {
676  assert (0);
677  return ER_FAILED;
678  }
679 
680  /* get tuple length and allocate space for the tuple */
681  tmp_tuple_p = cursor_id_p->buffer + QFILE_PAGE_HEADER_SIZE;
682  tuple_length = QFILE_GET_TUPLE_LENGTH (tmp_tuple_p);
683 
684  if (cursor_id_p->tuple_record.size < tuple_length)
685  {
686  if (cursor_allocate_tuple_area (cursor_id_p, tuple_length) != NO_ERROR)
687  {
688  return ER_FAILED;
689  }
690  }
691 
692  tuple_p = cursor_id_p->tuple_record.tpl;
693  offset = 0;
694 
695  do
696  {
697  buffer_p = cursor_id_p->buffer;
698 
699  QFILE_GET_OVERFLOW_VPID (&overflow_vpid, buffer_p);
700  tuple_page_size = MIN (tuple_length - offset, QFILE_MAX_TUPLE_SIZE_IN_PAGE);
701  memcpy (tuple_p, buffer_p + QFILE_PAGE_HEADER_SIZE, tuple_page_size);
702  tuple_p += tuple_page_size;
703  offset += tuple_page_size;
704 
705  if (overflow_vpid.pageid != NULL_PAGEID)
706  {
707  if (cursor_get_list_file_page (cursor_id_p, &overflow_vpid) != NO_ERROR)
708  {
709  return ER_FAILED;
710  }
711  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &overflow_vpid);
712  }
713  }
714  while (overflow_vpid.pageid != NULL_PAGEID);
715 
716  /* reset buffer as a head page of overflow page */
717  if (!VPID_EQ (vpid_p, &overflow_vpid) && cursor_get_list_file_page (cursor_id_p, vpid_p) != NO_ERROR)
718  {
719  return ER_FAILED;
720  }
721 
722  cursor_id_p->current_tuple_p = cursor_id_p->tuple_record.tpl;
723 
724  return NO_ERROR;
725 }
726 
727 static bool
729 {
730  if (cursor_id_p == NULL)
731  {
732  assert (0);
733  return false;
734  }
735 
736  return (cursor_id_p->is_oid_included && cursor_id_p->oid_ent_count > 0 && cursor_id_p->list_id.type_list.domp
737  && (TP_DOMAIN_TYPE (cursor_id_p->list_id.type_list.domp[0]) == DB_TYPE_OBJECT));
738 }
739 
740 static int
741 cursor_fetch_oids (CURSOR_ID * cursor_id_p, int oid_index, DB_FETCH_MODE instant_fetch_mode,
742  DB_FETCH_MODE class_fetch_mode)
743 {
744  int i;
745  OID tmp_oid;
746  MOBJ mobj;
747 
748  if (cursor_id_p == NULL)
749  {
750  assert (0);
751  return ER_FAILED;
752  }
753 
754  if (oid_index == 0)
755  {
756  /* nothing to fetch */
757  return NO_ERROR;
758  }
759 
760  /* form the MOP set from the existing oid_set */
761  for (i = 0; i < oid_index; i++)
762  {
763  OR_GET_OID (&cursor_id_p->oid_set[i], &tmp_oid);
764  cursor_id_p->mop_set[i] = ws_mop (&tmp_oid, (MOP) NULL);
765  }
766 
767 
768  if (oid_index == 1)
769  {
770  /* use mvcc fetch type to get the visible object again (accessible only using mvcc snapshot) */
771  mobj = locator_fetch_object (cursor_id_p->mop_set[0], instant_fetch_mode, LC_FETCH_MVCC_VERSION);
772  }
773  else
774  {
775  mobj = locator_fetch_set (oid_index, cursor_id_p->mop_set, instant_fetch_mode, class_fetch_mode, false);
776  }
777 
778  if (mobj == NULL && er_errid () != ER_HEAP_UNKNOWN_OBJECT)
779  {
780  return ER_FAILED;
781  }
782 
783  return NO_ERROR;
784 }
785 
786 static int
788 {
789  char *tuple_p;
790  OID *current_oid_p;
791  QFILE_TUPLE current_tuple;
792  int tupel_count, oid_index = 0, current_tuple_length, i;
793  DB_TYPE type;
794 
795  if (cursor_id_p == NULL)
796  {
797  assert (0);
798  return ER_FAILED;
799  }
800 
801  /* set tuple count and point to the first tuple */
802  tupel_count = QFILE_GET_TUPLE_COUNT (cursor_id_p->buffer);
803  current_tuple = cursor_id_p->buffer + QFILE_PAGE_HEADER_SIZE;
804  oid_index = 0;
805 
806  /*
807  * search through the current buffer to store interesting OIDs
808  * in the oid_set area, eliminating duplicates.
809  */
810  for (i = 0; i < tupel_count; i++)
811  {
812  current_tuple_length = QFILE_GET_TUPLE_LENGTH (current_tuple);
813 
814  /* fetch first OID */
815  type = TP_DOMAIN_TYPE (cursor_id_p->list_id.type_list.domp[0]);
816  tuple_p = (char *) current_tuple + QFILE_TUPLE_LENGTH_SIZE;
817 
818  if (QFILE_GET_TUPLE_VALUE_FLAG (tuple_p) != V_BOUND)
819  {
820  continue;
821  }
822 
823  current_oid_p = cursor_get_oid_from_tuple (tuple_p, type);
824 
825  if (current_oid_p && oid_index < cursor_id_p->oid_ent_count)
826  {
827  COPY_OID (&cursor_id_p->oid_set[oid_index], current_oid_p);
828  oid_index++;
829  }
830 
831  /* move to next tuple */
832  current_tuple = (char *) current_tuple + current_tuple_length;
833  }
834 
835  return cursor_fetch_oids (cursor_id_p, oid_index, cursor_id_p->prefetch_lock_mode,
836  ((cursor_id_p->prefetch_lock_mode == DB_FETCH_WRITE)
838 }
839 
840 static int
842 {
843  char *tuple_p;
844  OID *current_oid_p;
845  QFILE_TUPLE current_tuple;
846  int tuple_count, oid_index = 0, current_tuple_length;
847  int j, tuple_index, col_index, col_num;
848  DB_TYPE type;
849 
850  if (cursor_id_p == NULL)
851  {
852  assert (0);
853  return ER_FAILED;
854  }
855 
856  /* set tuple count and point to the first tuple */
857  tuple_count = QFILE_GET_TUPLE_COUNT (cursor_id_p->buffer);
858  current_tuple = cursor_id_p->buffer + QFILE_PAGE_HEADER_SIZE;
859  oid_index = 0;
860 
861  for (tuple_index = 0; tuple_index < tuple_count; tuple_index++)
862  {
863  current_tuple_length = QFILE_GET_TUPLE_LENGTH (current_tuple);
864 
865  for (col_index = 0; col_index < cursor_id_p->oid_col_no_cnt; col_index++)
866  {
867  col_num = cursor_id_p->oid_col_no[col_index];
868  type = TP_DOMAIN_TYPE (cursor_id_p->list_id.type_list.domp[col_num]);
869 
870  tuple_p = (char *) current_tuple + QFILE_TUPLE_LENGTH_SIZE;
871  for (j = col_num - 1; j >= 0; --j)
872  {
874  }
875 
876  if (QFILE_GET_TUPLE_VALUE_FLAG (tuple_p) != V_BOUND)
877  {
878  continue;
879  }
880 
881  if (type != DB_TYPE_OBJECT && type != DB_TYPE_VOBJ)
882  {
883  continue;
884  }
885 
886  current_oid_p = cursor_get_oid_from_tuple (tuple_p, type);
887 
888  if (current_oid_p && oid_index < cursor_id_p->oid_ent_count)
889  {
890  /* for little endian */
891  if (type == DB_TYPE_VOBJ)
892  {
893  OR_PUT_OID (&cursor_id_p->oid_set[oid_index], current_oid_p);
894  }
895  else
896  {
897  COPY_OID (&cursor_id_p->oid_set[oid_index], current_oid_p);
898  }
899 
900  oid_index++;
901  }
902  }
903 
904  current_tuple = (char *) current_tuple + current_tuple_length;
905  }
906 
907  return cursor_fetch_oids (cursor_id_p, oid_index, DB_FETCH_READ, DB_FETCH_QUERY_READ);
908 }
909 
910 static int
911 cursor_point_current_tuple (CURSOR_ID * cursor_id_p, int position, int offset)
912 {
913  if (cursor_id_p == NULL || cursor_id_p->buffer == NULL)
914  {
915  assert (0);
916  return ER_FAILED;
917  }
918 
919  cursor_id_p->buffer_tuple_count = QFILE_GET_TUPLE_COUNT (cursor_id_p->buffer);
921 
922  if (position == LAST_TPL)
923  {
924  cursor_id_p->current_tuple_no = cursor_id_p->buffer_tuple_count - 1;
925  cursor_id_p->current_tuple_offset = QFILE_GET_LAST_TUPLE_OFFSET (cursor_id_p->buffer);
926  }
927  else if (position == FIRST_TPL)
928  {
929  cursor_id_p->current_tuple_no = 0;
931  }
932  else if (position < cursor_id_p->buffer_tuple_count)
933  {
934  cursor_id_p->current_tuple_no = position;
935  cursor_id_p->current_tuple_offset = offset;
936  }
937  else
938  {
939  return ER_FAILED;
940  }
941 
942  return NO_ERROR;
943 }
944 
945 static int
946 cursor_buffer_last_page (CURSOR_ID * cursor_id_p, VPID * vpid_p)
947 {
948  if (cursor_id_p == NULL || vpid_p == NULL)
949  {
950  assert (0);
951  return ER_FAILED;
952  }
953 
954  if (cursor_id_p->list_id.last_pgptr && VPID_EQ (&(cursor_id_p->list_id.first_vpid), vpid_p))
955  {
956  cursor_id_p->buffer = cursor_id_p->list_id.last_pgptr;
957  }
958  else
959  {
960  if (cursor_get_list_file_page (cursor_id_p, vpid_p) != NO_ERROR)
961  {
962  return ER_FAILED;
963  }
964  }
965 
966  return NO_ERROR;
967 }
968 
969 /*
970  * cursor_fetch_page_having_tuple () - A request is made to the server side to
971  * bring the specified list file page and copy the page to the cursor buffer
972  * area
973  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
974  * cursor_id(in): Cursor identifier
975  * vpid(in): List File Real Page Identifier
976  * position(in):
977  * offset(in):
978  * Note: For performance reasons, this routine checks the cursor identifier
979  * and if the cursor LIST FILE has a hidden OID column (for update)
980  * or has preceding hidden OID columns, vector fetches those referred
981  * objects from the server.
982  *
983  * It also positions the tuple pointer to the desired tuple position.
984  * If position = LAST_TPL, then the cursor is positioned to the LAST
985  * tuple on the page. If position = FIRST_TPL, then the cursor is
986  * positioned to the FIRST tuple on the page. Otherwise, position is
987  * the tuple position in the fetched page and offset is used as the
988  * byte offset to the tuple. If positioning to the first or last tuple
989  * on the page, the offset is ignored.
990  */
991 int
992 cursor_fetch_page_having_tuple (CURSOR_ID * cursor_id_p, VPID * vpid_p, int position, int offset)
993 {
994  if (cursor_id_p == NULL || vpid_p == NULL)
995  {
996  assert (0);
997  return ER_FAILED;
998  }
999 
1001 
1002  if (!VPID_EQ (&(cursor_id_p->current_vpid), vpid_p))
1003  {
1004  if (cursor_buffer_last_page (cursor_id_p, vpid_p) != NO_ERROR)
1005  {
1006  return ER_FAILED;
1007  }
1008  }
1009 
1010  if (cursor_id_p->buffer == NULL)
1011  {
1012  return ER_FAILED;
1013  }
1014 
1015  if (cursor_point_current_tuple (cursor_id_p, position, offset) != NO_ERROR)
1016  {
1017  return ER_FAILED;
1018  }
1019 
1020  if (QFILE_GET_OVERFLOW_PAGE_ID (cursor_id_p->buffer) != NULL_PAGEID)
1021  {
1022  if (cursor_construct_tuple_from_overflow_pages (cursor_id_p, vpid_p) != NO_ERROR)
1023  {
1024  return ER_FAILED;
1025  }
1026  }
1027  else
1028  {
1029  cursor_id_p->current_tuple_p = cursor_id_p->buffer + cursor_id_p->current_tuple_offset;
1030  }
1031 
1032  /* If there is only one tuple, don't prefetch objects because prefetching a small set of objects is slower than
1033  * fetching them individually. */
1034  if (cursor_id_p->buffer_tuple_count < 2)
1035  {
1036  return NO_ERROR;
1037  }
1038 
1039  /* vector fetched involved OIDs for performance reasons, if the fetched LIST FILE page contains a hidden OID column
1040  * or a set of hidden preceding OID columns. NOTE1: this process for oid-cols-included queries are disabled. NOTE2:
1041  * this process is done only for DB_TYPE_OBJECT colums not for any other colum types such as DB_TYPE_VOBJ. */
1042  if (cursor_has_first_hidden_oid (cursor_id_p))
1043  {
1044  return cursor_prefetch_first_hidden_oid (cursor_id_p);
1045  }
1046  else if (cursor_id_p->oid_col_no && cursor_id_p->oid_col_no_cnt)
1047  {
1048  return cursor_prefetch_column_oids (cursor_id_p);
1049  }
1050 
1051  return NO_ERROR;
1052 }
1053 
1054 #if defined(WINDOWS) || defined (CUBRID_DEBUG)
1055 /*
1056  * cursor_print_list () - Dump the content of the list file to the standard output
1057  * return:
1058  * query_id(in):
1059  * list_id(in): List File Identifier
1060  */
1061 void
1062 cursor_print_list (QUERY_ID query_id, QFILE_LIST_ID * list_id_p)
1063 {
1065  DB_VALUE *value_list_p, *value_p;
1066  int count, i, status;
1067 
1068  if (list_id_p == NULL)
1069  {
1070  assert (0);
1071  return;
1072  }
1073 
1074  count = list_id_p->type_list.type_cnt;
1075  value_list_p = (DB_VALUE *) malloc (count * sizeof (DB_VALUE));
1076  if (value_list_p == NULL)
1077  {
1078  return;
1079  }
1080 
1081  fprintf (stdout, "\n================= Q U E R Y R E S U L T S =================\n\n");
1082 
1083  if (cursor_open (&cursor_id, list_id_p, false, false) == false)
1084  {
1085  free_and_init (value_list_p);
1086  return;
1087  }
1088 
1089  cursor_id.query_id = query_id;
1090 
1091  while (true)
1092  {
1093  status = cursor_next_tuple (&cursor_id);
1094  if (status != DB_CURSOR_SUCCESS)
1095  {
1096  break;
1097  }
1098 
1099  if (cursor_get_tuple_value_list (&cursor_id, count, value_list_p) != NO_ERROR)
1100  {
1101  goto cleanup;
1102  }
1103 
1104  fprintf (stdout, "\n ");
1105 
1106  for (i = 0, value_p = value_list_p; i < count; i++, value_p++)
1107  {
1108  fprintf (stdout, " ");
1109 
1110  if (TP_IS_SET_TYPE (DB_VALUE_TYPE (value_p)) || DB_VALUE_TYPE (value_p) == DB_TYPE_VOBJ)
1111  {
1112  db_set_print (db_get_set (value_p));
1113  }
1114  else
1115  {
1116  db_value_print (value_p);
1117  }
1118 
1119  db_value_clear (value_p);
1120  fprintf (stdout, " ");
1121  }
1122  }
1123 
1124  fprintf (stdout, "\n");
1125 
1126 cleanup:
1127 
1128  cursor_close (&cursor_id);
1129 
1130  free_and_init (value_list_p);
1131  return;
1132 }
1133 #endif
1134 
1135 /*
1136  * Cursor Management routines
1137  */
1138 
1139 static void
1141 {
1142  size_t oids_size, mops_size;
1143 
1144  if (cursor_id_p == NULL)
1145  {
1146  assert (0);
1147  return;
1148  }
1149 
1150  /*
1151  * NOTE: Currently assume a PAGESIZE. In fact, since we can
1152  * find average tuple count per page from the LIST FILE
1153  * identifier we can make a good estimate of oid entry count.
1154  */
1155  cursor_id_p->oid_ent_count = CEIL_PTVDIV (DB_PAGESIZE, sizeof (OID)) - 1;
1156 
1157  oids_size = cursor_id_p->oid_ent_count * sizeof (OID);
1158  cursor_id_p->oid_set = (OID *) malloc (oids_size);
1159 
1160  if (cursor_id_p->oid_set == NULL)
1161  {
1162  /* Ignore the failure, this is an optimization */
1163  cursor_id_p->oid_ent_count = 0;
1164  }
1165 
1166  mops_size = cursor_id_p->oid_ent_count * sizeof (MOP);
1167  cursor_id_p->mop_set = (MOP *) malloc (mops_size);
1168 
1169  if (cursor_id_p->mop_set == NULL)
1170  {
1171  /* Ignore the failure, this is an optimization */
1172  free_and_init (cursor_id_p->oid_set);
1173  cursor_id_p->oid_ent_count = 0;
1174  }
1175 }
1176 
1177 /*
1178  * cursor_open () -
1179  * return: true on all ok, false otherwise
1180  * cursor_id(out): Cursor identifier
1181  * list_id: List file identifier
1182  * updatable: Flag which indicates if cursor is updatable
1183  * is_oid_included: Flag which indicates if first column of the list file
1184  * contains hidden object identifiers
1185  *
1186  * Note: A cursor is opened to scan through the tuples of the given
1187  * list file. The cursor identifier is initialized and memory
1188  * buffer for the cursor identifier is allocated. If is_oid_included
1189  * flag is set to true, this indicates that the first column
1190  * of list file tuples contains the object identifier to be used
1191  * for cursor update/delete operations.
1192  */
1193 bool
1194 cursor_open (CURSOR_ID * cursor_id_p, QFILE_LIST_ID * list_id_p, bool updatable, bool is_oid_included)
1195 {
1196  static QFILE_LIST_ID empty_list_id; /* TODO: remove static empty_list_id */
1197 
1198  if (cursor_id_p == NULL)
1199  {
1200  assert (0);
1201  return false;
1202  }
1203 
1204  QFILE_CLEAR_LIST_ID (&empty_list_id);
1205 
1206  cursor_id_p->is_updatable = updatable;
1207  cursor_id_p->is_oid_included = is_oid_included;
1208  cursor_id_p->oid_ent_count = 0;
1209  cursor_id_p->oid_set = NULL;
1210  cursor_id_p->mop_set = NULL;
1211  cursor_id_p->position = C_BEFORE;
1212  cursor_id_p->tuple_no = -1;
1213  VPID_SET_NULL (&cursor_id_p->current_vpid);
1214  VPID_SET_NULL (&cursor_id_p->next_vpid);
1215  VPID_SET_NULL (&cursor_id_p->header_vpid);
1216  cursor_id_p->tuple_record.size = 0;
1217  cursor_id_p->tuple_record.tpl = NULL;
1218  cursor_id_p->on_overflow = false;
1219  cursor_id_p->buffer_tuple_count = 0;
1220  cursor_id_p->current_tuple_no = -1;
1221  cursor_id_p->current_tuple_offset = -1;
1222  cursor_id_p->current_tuple_p = NULL;
1223  cursor_id_p->current_tuple_length = -1;
1224  cursor_id_p->oid_col_no = NULL;
1225  cursor_id_p->oid_col_no_cnt = 0;
1226  cursor_id_p->buffer = NULL;
1227  cursor_id_p->buffer_area = NULL;
1228  cursor_id_p->buffer_filled_size = 0;
1229  cursor_id_p->list_id = empty_list_id;
1230  cursor_id_p->prefetch_lock_mode = DB_FETCH_READ;
1231  cursor_id_p->is_copy_tuple_value = true; /* copy */
1233 
1234  if (cursor_copy_list_id (&cursor_id_p->list_id, list_id_p) != NO_ERROR)
1235  {
1236  return false;
1237  }
1238 
1239  cursor_id_p->query_id = list_id_p->query_id;
1240 
1241  if (cursor_id_p->list_id.type_list.type_cnt)
1242  {
1243  cursor_id_p->buffer_area = (char *) malloc (CURSOR_BUFFER_AREA_SIZE);
1244  cursor_id_p->buffer = cursor_id_p->buffer_area;
1245 
1246  if (cursor_id_p->buffer == NULL)
1247  {
1248  return false;
1249  }
1250 
1251  if (is_oid_included)
1252  {
1253  cursor_allocate_oid_buffer (cursor_id_p);
1254  }
1255  }
1256 
1257  return true;
1258 }
1259 
1260 /*
1261  * cursor_set_prefetch_lock_mode () - Record the lock mode for prefetched objects.
1262  * return: It returns the previous lock mode.
1263  * cursor_id(in/out): Cursor identifier
1264  * mode(in):
1265  */
1268 {
1269  DB_FETCH_MODE old;
1270 
1271  if (cursor_id_p == NULL)
1272  {
1273  assert (0);
1274  return mode;
1275  }
1276 
1277  old = cursor_id_p->prefetch_lock_mode;
1278 
1279  cursor_id_p->prefetch_lock_mode = mode;
1280 
1281  return old;
1282 }
1283 
1284 /*
1285  * cursor_set_copy_tuple_value () - Record the indicator for copy/peek tplvalue.
1286  * return: It returns the previous indicator.
1287  * cursor_id(in/out): Cursor identifier
1288  * copy(in):
1289  */
1290 bool
1291 cursor_set_copy_tuple_value (CURSOR_ID * cursor_id_p, bool is_copy)
1292 {
1293  bool old;
1294 
1295  if (cursor_id_p == NULL)
1296  {
1297  assert (0);
1298  return false;
1299  }
1300 
1301  old = cursor_id_p->is_copy_tuple_value;
1302 
1303  cursor_id_p->is_copy_tuple_value = is_copy;
1304 
1305  return old;
1306 }
1307 
1308 /*
1309  * cursor_set_oid_columns () -
1310  * return:
1311  * cursor_id(in/out): Cursor identifier
1312  * oid_col_no(in): Array of int
1313  * oid_col_no_cnt(in): Size of oid_col_no
1314  *
1315  * returns/side-effects: int (true on success, false on failure)
1316  *
1317  * description: The caller indicates which columns of the list file
1318  * contain OID's which are to be pre-fetched when a list file
1319  * page is fetched.
1320  */
1321 int
1322 cursor_set_oid_columns (CURSOR_ID * cursor_id_p, int *oid_col_no_p, int oid_col_no_cnt)
1323 {
1324  if (cursor_id_p == NULL || cursor_id_p->is_oid_included || cursor_id_p->is_updatable)
1325  {
1326  return ER_FAILED;
1327  }
1328 
1329  cursor_id_p->oid_col_no = oid_col_no_p;
1330  cursor_id_p->oid_col_no_cnt = oid_col_no_cnt;
1331 
1332  cursor_allocate_oid_buffer (cursor_id_p);
1333  return NO_ERROR;
1334 }
1335 
1336 /*
1337  * cursor_free () - Free the area allocated for the cursor identifier.
1338  * return:
1339  * cursor_id(in/out): Cursor Identifier
1340  */
1341 void
1342 cursor_free (CURSOR_ID * cursor_id_p)
1343 {
1344  int i;
1345 
1346  if (cursor_id_p == NULL)
1347  {
1348  assert (0);
1349  return;
1350  }
1351 
1352  cursor_free_list_id (&(cursor_id_p->list_id));
1353 
1354  if (cursor_id_p->buffer_area != NULL)
1355  {
1356  free_and_init (cursor_id_p->buffer_area);
1357  cursor_id_p->buffer_filled_size = 0;
1358  cursor_id_p->buffer = NULL;
1359  }
1360 
1361  free_and_init (cursor_id_p->tuple_record.tpl);
1362  free_and_init (cursor_id_p->oid_set);
1363 
1364  if (cursor_id_p->mop_set != NULL)
1365  {
1366  for (i = 0; i < cursor_id_p->oid_ent_count; i++)
1367  {
1368  cursor_id_p->mop_set[i] = NULL;
1369  }
1370  free_and_init (cursor_id_p->mop_set);
1371  }
1372 }
1373 
1374 /*
1375  * cursor_close () - Free the area allocated for the cursor identifier and
1376  * invalidate the cursor identifier.
1377  * return:
1378  * cursor_id(in/out): Cursor Identifier
1379  */
1380 void
1381 cursor_close (CURSOR_ID * cursor_id_p)
1382 {
1383  if (cursor_id_p == NULL)
1384  {
1385  assert (0);
1386  return;
1387  }
1388 
1389  /* free the cursor allocated area */
1390  cursor_free (cursor_id_p);
1391 
1392  /* invalidate the cursor_id */
1393  cursor_id_p->position = C_BEFORE;
1394  cursor_id_p->tuple_no = -1;
1395  cursor_id_p->is_updatable = false;
1396  cursor_id_p->oid_ent_count = 0;
1397  cursor_id_p->current_vpid.pageid = NULL_PAGEID;
1398  cursor_id_p->next_vpid.pageid = NULL_PAGEID;
1399  cursor_id_p->header_vpid.pageid = NULL_PAGEID;
1400  cursor_id_p->buffer_tuple_count = 0;
1401  cursor_id_p->current_tuple_no = -1;
1402  cursor_id_p->current_tuple_offset = -1;
1403  cursor_id_p->current_tuple_p = NULL;
1404  cursor_id_p->current_tuple_length = -1;
1405  cursor_id_p->oid_col_no = NULL;
1406  cursor_id_p->oid_col_no_cnt = 0;
1407  cursor_id_p->query_id = NULL_QUERY_ID;
1409 }
1410 
1411 /*
1412  * crs_peek_tuple () - peek the current cursor tuple
1413  * return: NULL on error
1414  * cursor_id(in): Cursor Identifier
1415  * Note: A pointer to the beginning of the current cursor tuple is
1416  * returned. The pointer directly points to inside the cursor memory
1417  * buffer.
1418  */
1419 static char *
1421 {
1422  if (cursor_id_p == NULL)
1423  {
1424  assert (0);
1425  return NULL;
1426  }
1427 
1428  if (cursor_id_p->position != C_ON)
1429  {
1431  return NULL;
1432  }
1433 
1434  /* tuple is contained in the cursor buffer */
1435  return cursor_id_p->current_tuple_p;
1436 }
1437 
1438 /*
1439  * cursor_get_current_oid () -
1440  * return: DB_CURSOR_SUCCESS, DB_CURSOR_END, error_code
1441  * cursor_id(in): Cursor Identifier
1442  * db_value(out): Set to the object identifier
1443  * Note: The object identifier stored in the first column of the
1444  * current cursor tuple is extracted and stored in the db_value
1445  * parameter. If cursor list file does not have an object
1446  * identifier column, an error code is set.
1447  */
1448 int
1449 cursor_get_current_oid (CURSOR_ID * cursor_id_p, DB_VALUE * value_p)
1450 {
1451  char *tuple_p;
1452 
1453  if (cursor_id_p == NULL)
1454  {
1455  assert (0);
1456  return ER_FAILED;
1457  }
1458 
1459  assert (cursor_id_p->is_oid_included == true);
1460 
1461  tuple_p = cursor_peek_tuple (cursor_id_p);
1462  if (tuple_p == NULL)
1463  {
1464  return ER_FAILED;
1465  }
1466 
1467  return cursor_get_first_tuple_value (tuple_p, &cursor_id_p->list_id.type_list, value_p,
1468  cursor_id_p->is_copy_tuple_value);
1469 }
1470 
1471 /*
1472  * cursor_next_tuple () -
1473  * return: DB_CURSOR_SUCCESS, DB_CURSOR_END, error_code
1474  * cursor_id(in/out): Cursor Identifier
1475  * Note: Makes the next tuple in the LIST FILE referred by the cursor
1476  * identifier the current active tuple of the cursor and returns
1477  * DB_CURSOR_SUCCESS.
1478  *
1479  * Note: if end_of_scan: DB_CURSOR_END, otherwise an error code is returned.
1480  */
1481 int
1483 {
1484  if (cursor_id_p == NULL || cursor_id_p->query_id == NULL_QUERY_ID)
1485  {
1486  assert (0);
1487  return DB_CURSOR_ERROR;
1488  }
1489 
1491 
1492  if (cursor_id_p->position == C_BEFORE)
1493  {
1494  if (VPID_ISNULL (&(cursor_id_p->list_id.first_vpid)))
1495  {
1496  return DB_CURSOR_END;
1497  }
1498 
1499  if (cursor_fetch_page_having_tuple (cursor_id_p, &cursor_id_p->list_id.first_vpid, FIRST_TPL, 0) != NO_ERROR)
1500  {
1501  return DB_CURSOR_ERROR;
1502  }
1503 
1504  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &cursor_id_p->list_id.first_vpid);
1505  /*
1506  * Setup the cursor so that we can proceed through the next "if"
1507  * statement w/o code duplication.
1508  */
1509  cursor_id_p->position = C_ON;
1510  cursor_id_p->tuple_no = -1;
1511  cursor_id_p->current_tuple_no = -1;
1512  cursor_id_p->current_tuple_length = 0;
1513  }
1514 
1515  if (cursor_id_p->position == C_ON)
1516  {
1517  VPID next_vpid;
1518 
1519  if (cursor_id_p->current_tuple_no < cursor_id_p->buffer_tuple_count - 1)
1520  {
1521  cursor_id_p->tuple_no++;
1522  cursor_id_p->current_tuple_no++;
1523  cursor_id_p->current_tuple_offset += cursor_id_p->current_tuple_length;
1524  cursor_id_p->current_tuple_p += cursor_id_p->current_tuple_length;
1525  cursor_id_p->current_tuple_length = QFILE_GET_TUPLE_LENGTH (cursor_id_p->current_tuple_p);
1526  }
1527  else if (QFILE_GET_NEXT_PAGE_ID (cursor_id_p->buffer) != NULL_PAGEID)
1528  {
1529  QFILE_GET_NEXT_VPID (&next_vpid, cursor_id_p->buffer);
1530  if (cursor_fetch_page_having_tuple (cursor_id_p, &next_vpid, FIRST_TPL, 0) != NO_ERROR)
1531  {
1532  return DB_CURSOR_ERROR;
1533  }
1534  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &next_vpid);
1535  cursor_id_p->tuple_no++;
1536  }
1537  else
1538  {
1539  cursor_id_p->position = C_AFTER;
1540  cursor_id_p->tuple_no = cursor_id_p->list_id.tuple_cnt;
1541  return DB_CURSOR_END;
1542  }
1543  }
1544  else if (cursor_id_p->position == C_AFTER)
1545  {
1546  return DB_CURSOR_END;
1547  }
1548  else
1549  {
1551  return ER_QPROC_UNKNOWN_CRSPOS;
1552  }
1553 
1554  return DB_CURSOR_SUCCESS;
1555 }
1556 
1557 /*
1558  * cursor_prev_tuple () -
1559  * return: DB_CURSOR_SUCCESS, DB_CURSOR_END, error_code
1560  * cursor_id(in/out): Cursor Identifier
1561  * Note: Makes the previous tuple in the LIST FILE referred by cursor
1562  * identifier the current active tuple of the cursor and returns
1563  * DB_CURSOR_SUCCESS.
1564  *
1565  * Note: if end_of_scan: DB_CURSOR_END, otherwise an error code is returned.
1566  */
1567 int
1569 {
1570  if (cursor_id_p == NULL)
1571  {
1572  assert (0);
1573  return DB_CURSOR_ERROR;
1574  }
1575 
1577 
1578  if (cursor_id_p->position == C_BEFORE)
1579  {
1580  return DB_CURSOR_END;
1581  }
1582  else if (cursor_id_p->position == C_ON)
1583  {
1584  VPID prev_vpid;
1585 
1586  if (cursor_id_p->current_tuple_no > 0)
1587  {
1588  cursor_id_p->tuple_no--;
1589  cursor_id_p->current_tuple_no--;
1590  cursor_id_p->current_tuple_offset -= QFILE_GET_PREV_TUPLE_LENGTH (cursor_id_p->current_tuple_p);
1591  cursor_id_p->current_tuple_p -= QFILE_GET_PREV_TUPLE_LENGTH (cursor_id_p->current_tuple_p);
1592  cursor_id_p->current_tuple_length = QFILE_GET_TUPLE_LENGTH (cursor_id_p->current_tuple_p);
1593  }
1594  else if (QFILE_GET_PREV_PAGE_ID (cursor_id_p->buffer) != NULL_PAGEID)
1595  {
1596  QFILE_GET_PREV_VPID (&prev_vpid, cursor_id_p->buffer);
1597 
1598  if (cursor_fetch_page_having_tuple (cursor_id_p, &prev_vpid, LAST_TPL, 0) != NO_ERROR)
1599  {
1600  return DB_CURSOR_ERROR;
1601  }
1602 
1603  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &prev_vpid);
1604  cursor_id_p->tuple_no--;
1605  }
1606  else
1607  {
1608  cursor_id_p->position = C_BEFORE;
1609  cursor_id_p->tuple_no = -1;
1610  return DB_CURSOR_END;
1611  }
1612  }
1613  else if (cursor_id_p->position == C_AFTER)
1614  {
1615  if (VPID_ISNULL (&(cursor_id_p->list_id.first_vpid)))
1616  {
1617  return DB_CURSOR_END;
1618  }
1619 
1620  if (cursor_fetch_page_having_tuple (cursor_id_p, &cursor_id_p->list_id.last_vpid, LAST_TPL, 0) != NO_ERROR)
1621  {
1622  return DB_CURSOR_ERROR;
1623  }
1624 
1625  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &cursor_id_p->list_id.last_vpid);
1626  cursor_id_p->position = C_ON;
1627  cursor_id_p->tuple_no--;
1628  }
1629  else
1630  {
1632  return ER_QPROC_UNKNOWN_CRSPOS;
1633  }
1634 
1635  return DB_CURSOR_SUCCESS;
1636 }
1637 
1638 /*
1639  * cursor_first_tuple () -
1640  *
1641  * arguments:
1642  * return: DB_CURSOR_SUCCESS, DB_CURSOR_END, error_code
1643  * cursor_id(in/out): Cursor Identifier
1644  * Note: Makes the first tuple in the LIST FILE referred by the cursor
1645  * identifier the current active tuple of the cursor and returns
1646  * DB_CURSOR_SUCCESS. If there are no tuples in the list file,
1647  * end_of_scan condition is reached.
1648  *
1649  * Note: if end_of_scan: DB_CURSOR_END, otherwise an error code is returned.
1650  */
1651 int
1653 {
1654  if (cursor_id_p == NULL)
1655  {
1656  assert (0);
1657  return DB_CURSOR_ERROR;
1658  }
1659 
1660  if (VPID_ISNULL (&(cursor_id_p->list_id.first_vpid)))
1661  {
1662  return DB_CURSOR_END;
1663  }
1664 
1665  if (cursor_fetch_page_having_tuple (cursor_id_p, &cursor_id_p->list_id.first_vpid, FIRST_TPL, 0) != NO_ERROR)
1666  {
1667  return DB_CURSOR_ERROR;
1668  }
1669 
1670  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &cursor_id_p->list_id.first_vpid);
1671  cursor_id_p->position = C_ON;
1672  cursor_id_p->tuple_no = 0;
1673 
1674  if (cursor_id_p->buffer_tuple_count == 0)
1675  {
1676  cursor_id_p->position = C_AFTER;
1677  cursor_id_p->tuple_no = cursor_id_p->list_id.tuple_cnt;
1678  return DB_CURSOR_END;
1679  }
1680 
1681  return DB_CURSOR_SUCCESS;
1682 }
1683 
1684 /*
1685  * cursor_last_tuple () -
1686  * return: DB_CURSOR_SUCCESS, DB_CURSOR_END, error_code
1687  * cursor_id(in/out): Cursor Identifier
1688  * Note: Makes the last tuple in the LIST FILE referred by the cursor
1689  * identifier the current active tuple of the cursor and returns
1690  * DB_CURSOR_SUCCESS. If there are no tuples in the list file,
1691  * end_of_scan condition is reached.
1692  *
1693  * Note: if end_of_scan: DB_CURSOR_END, otherwise an error code is returned.
1694  */
1695 int
1697 {
1698  if (cursor_id_p == NULL)
1699  {
1700  assert (0);
1701  return DB_CURSOR_ERROR;
1702  }
1703 
1704  if (VPID_ISNULL (&(cursor_id_p->list_id.first_vpid)))
1705  {
1706  return DB_CURSOR_END;
1707  }
1708 
1709  if (cursor_fetch_page_having_tuple (cursor_id_p, &cursor_id_p->list_id.last_vpid, LAST_TPL, 0) != NO_ERROR)
1710  {
1711  return DB_CURSOR_ERROR;
1712  }
1713 
1714  QFILE_COPY_VPID (&cursor_id_p->current_vpid, &cursor_id_p->list_id.last_vpid);
1715  cursor_id_p->position = C_ON;
1716  cursor_id_p->tuple_no = cursor_id_p->list_id.tuple_cnt - 1;
1717 
1718  return DB_CURSOR_SUCCESS;
1719 }
1720 
1721 /*
1722  * cursor_get_tuple_value () -
1723  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
1724  * c_id(in): Cursor Identifier
1725  * index(in):
1726  * value(in/out):
1727  * Note: The data value of the current cursor tuple at the position
1728  * pecified is fetched. If the position specified by index is
1729  * not a valid position number, or if the cursor is not
1730  * currently pointing to a tuple, then necessary error codes are
1731  * returned.
1732  */
1733 int
1734 cursor_get_tuple_value (CURSOR_ID * cursor_id_p, int index, DB_VALUE * value_p)
1735 {
1736  char *tuple_p;
1737 
1738  if (cursor_id_p == NULL)
1739  {
1740  assert (0);
1741  return ER_FAILED;
1742  }
1743 
1744  if (cursor_id_p->is_oid_included == true)
1745  {
1746  index++;
1747  }
1748 
1749  if (index < 0 || index >= cursor_id_p->list_id.type_list.type_cnt)
1750  {
1752  return ER_FAILED;
1753  }
1754 
1755  tuple_p = cursor_peek_tuple (cursor_id_p);
1756  if (tuple_p == NULL)
1757  {
1758  return ER_FAILED;
1759  }
1760 
1761  return cursor_get_tuple_value_from_list (cursor_id_p, index, value_p, tuple_p);
1762 }
1763 
1764 /*
1765  * cursor_get_tuple_value_list () -
1766  * return: NO_ERROR on all ok, ER status( or ER_FAILED) otherwise
1767  * cursor_id(in): Cursor Identifier
1768  * size(in): Number of values in the value list
1769  * value_list(in/out): Set to the values fetched from the current tuple
1770  * Note: The data values of the current cursor tuple are fetched
1771  * and put the value_list in their originial order. The size
1772  * parameter must be equal to the number of values in the tuple
1773  * and the caller should allocate necessary space for the value
1774  * list. If the cursor is not currently pointing to tuple, an
1775  * error code is returned.
1776  */
1777 int
1778 cursor_get_tuple_value_list (CURSOR_ID * cursor_id_p, int size, DB_VALUE * value_list_p)
1779 {
1780  DB_VALUE *value_p;
1781  int index;
1782 
1783  if (cursor_id_p == NULL)
1784  {
1785  assert (0);
1786  return ER_FAILED;
1787  }
1788 
1789  index = 0;
1790  value_p = value_list_p;
1791 
1792  while (index < size)
1793  {
1794  if (cursor_get_tuple_value (cursor_id_p, index, value_p) != NO_ERROR)
1795  {
1796  return ER_FAILED;
1797  }
1798 
1799  index++;
1800  value_p++;
1801  }
1802 
1803  return NO_ERROR;
1804 }
#define QFILE_TUPLE_VALUE_HEADER_SIZE
Definition: query_list.h:229
VPID next_vpid
Definition: cursor.h:61
char * PAGE_PTR
static int cursor_prefetch_column_oids(CURSOR_ID *cursor_id_p)
Definition: cursor.c:841
#define QFILE_CLEAR_LIST_ID(list_id)
Definition: query_list.h:445
int data_readval(struct or_buf *buf, DB_VALUE *value, const tp_domain *domain, int size, bool copy, char *copy_buf, int copy_buf_len) const
#define OR_PUT_OID(ptr, oid)
int page_size
Definition: unloaddb.c:52
static int cursor_buffer_last_page(CURSOR_ID *cursor_id_p, VPID *vpid_p)
Definition: cursor.c:946
#define CURSOR_BUFFER_SIZE
Definition: cursor.c:47
#define NO_ERROR
Definition: error_code.h:46
int cursor_copy_vobj_to_dbvalue(struct or_buf *buffer_p, DB_VALUE *value_p)
Definition: cursor.c:334
#define ER_QPROC_INVALID_TPLVAL_INDEX
Definition: error_code.h:523
DB_COLLECTION * db_get_set(const DB_VALUE *value)
int cursor_get_tuple_value(CURSOR_ID *cursor_id_p, int index, DB_VALUE *value_p)
Definition: cursor.c:1734
int oid_col_no_cnt
Definition: cursor.h:75
QFILE_TUPLE_VALUE_TYPE_LIST type_list
Definition: query_list.h:428
QUERY_ID query_id
Definition: query_list.h:438
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
PAGE_PTR last_pgptr
Definition: query_list.h:434
char * MOBJ
Definition: work_space.h:174
DB_SET * db_seq_create(MOP classop, const char *name, int size)
Definition: db_set.c:252
MOBJ locator_fetch_set(int num_mops, MOP *mop_set, DB_FETCH_MODE inst_purpose, DB_FETCH_MODE class_purpose, int quit_on_errors)
Definition: locator_cl.c:2464
#define TP_IS_SET_TYPE(typenum)
static char * cursor_peek_tuple(CURSOR_ID *cursor_id)
Definition: cursor.c:1420
static int cursor_fixup_vobjs(DB_VALUE *val)
Definition: cursor.c:283
DB_TYPE
Definition: dbtype_def.h:670
#define ER_FAILED
Definition: error_code.h:47
int db_seq_put(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:745
static void cursor_initialize_current_tuple_value_position(CURSOR_ID *cursor_id_p)
Definition: cursor.c:85
#define QFILE_GET_NEXT_PAGE_ID(ptr)
Definition: query_list.h:73
DB_FETCH_MODE cursor_set_prefetch_lock_mode(CURSOR_ID *cursor_id_p, DB_FETCH_MODE mode)
Definition: cursor.c:1267
int cursor_next_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1482
char * current_tuple_p
Definition: cursor.h:72
#define QFILE_GET_PREV_TUPLE_LENGTH(tpl)
Definition: query_list.h:241
static int cursor_point_current_tuple(CURSOR_ID *cursor_id_p, int position, int offset)
Definition: cursor.c:911
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
VPID header_vpid
Definition: cursor.h:62
int vid_oid_to_object(const DB_VALUE *value, DB_OBJECT **mop)
Definition: cursor.h:47
char * buffer_area
Definition: cursor.h:67
#define WS_ISVID(mop)
Definition: work_space.h:288
DB_FETCH_MODE prefetch_lock_mode
Definition: cursor.h:76
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
#define DB_CURSOR_ERROR
Definition: dbtype_def.h:168
int32_t pageid
Definition: dbtype_def.h:879
int er_errid(void)
DB_SET * db_set_create_multi(MOP classop, const char *name)
Definition: db_set.c:192
bool * clear_f_val_at_clone_decache
Definition: query_list.h:373
QFILE_TUPLE_DESCRIPTOR tpl_descr
Definition: query_list.h:441
int db_set_print(DB_SET *set)
Definition: db_set.c:664
int on_overflow
Definition: cursor.h:63
int cursor_fetch_page_having_tuple(CURSOR_ID *cursor_id_p, VPID *vpid_p, int position, int offset)
Definition: cursor.c:992
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
#define cursor_free_list_id(list_id)
Definition: cursor.h:86
static int cursor_get_list_file_page(CURSOR_ID *cursor_id, VPID *vpid)
Definition: cursor.c:507
VPID current_vpid
Definition: cursor.h:60
#define NULL_PAGEID
#define ER_QPROC_INVALID_CRSPOS
Definition: error_code.h:520
MOBJ locator_fetch_object(MOP mop, DB_FETCH_MODE purpose, LC_FETCH_VERSION_TYPE fetch_version_type)
Definition: locator_cl.c:2235
int cursor_last_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1696
#define QFILE_GET_TUPLE_VALUE_FLAG(ptr)
Definition: query_list.h:250
bool pr_is_set_type(DB_TYPE type)
#define QFILE_MAX_TUPLE_SIZE_IN_PAGE
Definition: query_list.h:217
static int cursor_allocate_tuple_area(CURSOR_ID *cursor_id_p, int tuple_length)
Definition: cursor.c:640
PR_TYPE * pr_type_from_id(DB_TYPE id)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
int db_set_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:508
bool is_updatable
Definition: cursor.h:79
#define assert(x)
int cursor_get_current_oid(CURSOR_ID *cursor_id_p, DB_VALUE *value_p)
Definition: cursor.c:1449
char * current_tuple_value_p
Definition: cursor.h:78
int db_make_set(DB_VALUE *value, DB_C_SET *set)
int db_make_multiset(DB_VALUE *value, DB_C_SET *set)
static bool cursor_has_first_hidden_oid(CURSOR_ID *cursor_id_p)
Definition: cursor.c:728
static int cursor_construct_tuple_from_overflow_pages(CURSOR_ID *cursor_id_p, VPID *vpid_p)
Definition: cursor.c:667
DB_IDENTIFIER OID
Definition: dbtype_def.h:967
#define QFILE_PAGE_HEADER_SIZE
Definition: query_list.h:47
#define OR_GET_OID(ptr, oid)
#define QFILE_GET_PREV_PAGE_ID(ptr)
Definition: query_list.h:70
int buffer_tuple_count
Definition: cursor.h:69
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
#define QFILE_GET_PREV_VPID(des, ptr)
Definition: query_list.h:96
static int cursor_get_tuple_value_from_list(CURSOR_ID *c_id, int index, DB_VALUE *value, char *tuple)
Definition: cursor.c:425
static enum scanner_mode mode
#define VPID_EQ(vpid_ptr1, vpid_ptr2)
Definition: dbtype_def.h:915
short volid
Definition: dbtype_def.h:880
int cursor_set_oid_columns(CURSOR_ID *cursor_id_p, int *oid_col_no_p, int oid_col_no_cnt)
Definition: cursor.c:1322
DB_OBJECT * db_get_object(const DB_VALUE *value)
int buffer_filled_size
Definition: cursor.h:68
QUERY_ID query_id
Definition: cursor.h:54
#define TP_DOMAIN_TYPE(dom)
#define DB_SIZEOF(val)
Definition: memory_alloc.h:54
static void cleanup(int signo)
Definition: broker.c:717
#define QFILE_GET_TUPLE_VALUE_LENGTH(ptr)
Definition: query_list.h:253
SORT_LIST * sort_list
Definition: query_list.h:429
#define NULL
Definition: freelistheap.h:34
static int cursor_prefetch_first_hidden_oid(CURSOR_ID *cursor_id_p)
Definition: cursor.c:787
#define QFILE_TUPLE_LENGTH_SIZE
Definition: query_list.h:224
void db_value_print(const DB_VALUE *value)
Definition: db_macro.c:1663
#define ER_QPROC_UNKNOWN_CRSPOS
Definition: error_code.h:522
struct pr_type * type
Definition: object_domain.h:76
int current_tuple_offset
Definition: cursor.h:71
#define QFILE_COPY_VPID(ptr1, ptr2)
Definition: query_list.h:197
#define QFILE_GET_TUPLE_LENGTH(tpl)
Definition: query_list.h:238
bool is_copy_tuple_value
Definition: cursor.h:81
static int cursor_fetch_oids(CURSOR_ID *cursor_id_p, int oid_index, DB_FETCH_MODE instant_fetch_mode, DB_FETCH_MODE class_fetch_mode)
Definition: cursor.c:741
int db_set_add(DB_SET *set, DB_VALUE *value)
Definition: db_set.c:465
bool is_oid_included
Definition: cursor.h:80
#define CURSOR_BUFFER_AREA_SIZE
Definition: cursor.c:48
DB_SET * db_set_create_basic(MOP classop, const char *name)
Definition: db_set.c:134
int db_set_free(DB_SET *set)
Definition: db_set.c:306
bool cursor_set_copy_tuple_value(CURSOR_ID *cursor_id_p, bool is_copy)
Definition: cursor.c:1291
void or_init(OR_BUF *buf, char *data, int length)
need_clear_type need_clear
Definition: dbtype_def.h:1084
#define CEIL_PTVDIV(dividend, divisor)
Definition: memory_alloc.h:50
int db_set_size(DB_SET *set)
Definition: db_set.c:557
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
static int cursor_fixup_set_vobjs(DB_VALUE *value)
Definition: cursor.c:186
int pr_clear_value(DB_VALUE *value)
int vid_vobj_to_object(const DB_VALUE *vobj, DB_OBJECT **mop)
#define DB_DEFAULT_SCALE
Definition: dbtype_def.h:561
int tuple_no
Definition: cursor.h:64
static void cursor_allocate_oid_buffer(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1140
#define VPID_ISNULL(vpid_ptr)
Definition: dbtype_def.h:925
static int rc
Definition: serial.c:50
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
static OID * cursor_get_oid_from_vobj(OID *current_oid_p, int length)
Definition: cursor.c:592
bool vid_is_updatable(MOP mop)
int cursor_copy_list_id(QFILE_LIST_ID *dest_list_id_p, const QFILE_LIST_ID *src_list_id_p)
Definition: cursor.c:105
#define ARG_FILE_LINE
Definition: error_manager.h:44
char * buffer
Definition: cursor.h:66
QFILE_TUPLE_VALUE_FLAG
Definition: query_list.h:291
#define WS_OID(mop)
Definition: work_space.h:293
QFILE_TUPLE_RECORD tuple_record
Definition: cursor.h:65
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define DB_PAGESIZE
#define QFILE_GET_OVERFLOW_VPID(des, ptr)
Definition: query_list.h:112
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
char * QFILE_TUPLE
Definition: query_list.h:281
MOP * mop_set
Definition: cursor.h:57
static bool cursor_has_set_vobjs(DB_SET *set)
Definition: cursor.c:153
void cursor_free(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1342
int current_tuple_value_index
Definition: cursor.h:77
int cursor_prev_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1568
void cursor_close(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1381
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
struct db_object * MOP
Definition: dbtype_def.h:409
DB_TYPE id
MOP vid_base_instance(MOP mop)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
QFILE_LIST_ID list_id
Definition: cursor.h:55
static OID * cursor_get_oid_from_tuple(char *tuple_p, DB_TYPE type)
Definition: cursor.c:623
int oid_ent_count
Definition: cursor.h:58
#define QFILE_GET_LAST_TUPLE_OFFSET(ptr)
Definition: query_list.h:76
int current_tuple_no
Definition: cursor.h:70
DB_FETCH_MODE
Definition: dbtype_def.h:215
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
#define QFILE_GET_TUPLE_COUNT(ptr)
Definition: query_list.h:67
CURSOR_POSITION position
Definition: cursor.h:59
#define QFILE_GET_NEXT_VPID(des, ptr)
Definition: query_list.h:104
static int cursor_get_first_tuple_value(char *tuple, QFILE_TUPLE_VALUE_TYPE_LIST *type_list, DB_VALUE *value, bool copy)
Definition: cursor.c:484
static int cursor_get_tuple_value_to_dbvalue(OR_BUF *buf, TP_DOMAIN *dom, QFILE_TUPLE_VALUE_FLAG val_flag, DB_VALUE *db_value, bool copy)
Definition: cursor.c:376
#define DB_CURSOR_END
Definition: dbtype_def.h:167
bool cursor_open(CURSOR_ID *cursor_id_p, QFILE_LIST_ID *list_id_p, bool updatable, bool is_oid_included)
Definition: cursor.c:1194
#define VPID_SET_NULL(vpid_ptr)
Definition: dbtype_def.h:906
Definition: cursor.h:48
OID * oid_set
Definition: cursor.h:56
int set_convert_oids_to_objects(DB_COLLECTION *set)
Definition: set_object.c:3273
int current_tuple_length
Definition: cursor.h:74
int cursor_get_tuple_value_list(CURSOR_ID *cursor_id_p, int size, DB_VALUE *value_list_p)
Definition: cursor.c:1778
int qfile_get_list_file_page(QUERY_ID query_id, VOLID volid, PAGEID pageid, char *buffer, int *buffer_size)
#define QFILE_GET_OVERFLOW_PAGE_ID(ptr)
Definition: query_list.h:79
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
int * oid_col_no
Definition: cursor.h:73
int cursor_first_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1652