CUBRID Engine  latest
query_manager.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  * query_manager.c - Query manager module
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 "query_manager.h"
32 
33 #include "file_manager.h"
34 #include "compile_context.h"
35 #include "log_append.hpp"
36 #include "object_primitive.h"
37 #include "object_representation.h"
38 #include "xserver_interface.h"
39 #include "query_executor.h"
40 #include "stream_to_xasl.h"
41 #include "session.h"
42 #include "filter_pred_cache.h"
43 #include "crypt_opfunc.h"
44 #if defined(ENABLE_SYSTEMTAP)
45 #include "probes.h"
46 #endif /* ENABLE_SYSTEMTAP */
47 #include "thread_entry.hpp"
48 #include "xasl_cache.h"
49 #include "xasl_unpack_info.hpp"
50 
51 #if !defined (SERVER_MODE)
52 
53 #define pthread_mutex_init(a, b)
54 #define pthread_mutex_destroy(a)
55 #define pthread_mutex_lock(a) 0
56 #define pthread_mutex_unlock(a)
58 #define IS_IN_METHOD_OR_JSP_CALL() (method_Num_method_jsp_calls > 0)
59 
60 #endif
61 
62 #define QMGR_MAX_QUERY_ENTRY_PER_TRAN 100
63 
64 #define QMGR_TEMP_FILE_FREE_LIST_SIZE 100
65 
66 #define QMGR_NUM_TEMP_FILE_LISTS (TEMP_FILE_MEMBUF_NUM_TYPES)
67 
68 #define QMGR_SQL_ID_LENGTH 13
69 
70 /* We have two valid types of membuf used by temporary file. */
71 #define QMGR_IS_VALID_MEMBUF_TYPE(m) ((m) == TEMP_FILE_MEMBUF_NORMAL || (m) == TEMP_FILE_MEMBUF_KEY_BUFFER)
72 
74 {
78 };
80 
81 /*
82  * ALLOCATION STRUCTURES
83  *
84  * A resource mechanism used to effectively handle memory allocation for the
85  * query entry structures.
86  */
87 
88 #define OID_BLOCK_ARRAY_SIZE 10
89 typedef struct oid_block_list
90 {
95 
98 {
99  QMGR_TRAN_STATUS trans_stat; /* transaction status */
100  int query_id_generator; /* global query identifier count */
101 
102  int num_query_entries; /* number of allocated query entries */
103 
104  QMGR_QUERY_ENTRY *query_entry_list_p; /* linked list of query entries */
105  QMGR_QUERY_ENTRY *free_query_entry_list_p; /* free query entry list */
106 
107  OID_BLOCK_LIST *modified_classes_p; /* array of class OIDs */
108 };
109 
112 {
113  pthread_mutex_t mutex;
115  int count;
116 };
117 
118 /*
119  * Global query table variable used to keep track of query entries and
120  * the anchor for the out of space in the temp vol WFG.
121  */
124 {
125  QMGR_TRAN_ENTRY *tran_entries_p; /* list of transaction entries */
126  int num_trans; /* size of trans_ind[] */
127 
128  /* allocation structure resource */
129  OID_BLOCK_LIST *free_oid_block_list_p; /* free OID block list */
130 
131  /* temp file free list info */
133 };
134 
136  {{PTHREAD_MUTEX_INITIALIZER, NULL, 0}, {PTHREAD_MUTEX_INITIALIZER, NULL, 0}}
137 };
138 
139 #if !defined(SERVER_MODE)
140 static struct drand48_data qmgr_rand_buf;
141 #endif
142 
143 static QMGR_PAGE_TYPE qmgr_get_page_type (PAGE_PTR page_p, QMGR_TEMP_FILE * temp_file_p);
147 static void qmgr_put_page_header (PAGE_PTR page_p, QFILE_PAGE_HEADER * header_p);
148 
149 static QMGR_QUERY_ENTRY *qmgr_allocate_query_entry (THREAD_ENTRY * thread_p, QMGR_TRAN_ENTRY * tran_entry_p);
150 static void qmgr_free_query_entry (THREAD_ENTRY * thread_p, QMGR_TRAN_ENTRY * tran_entry_p, QMGR_QUERY_ENTRY * q_ptr);
151 static void qmgr_deallocate_query_entries (QMGR_QUERY_ENTRY * q_ptr);
152 static void qmgr_deallocate_oid_blocks (OID_BLOCK_LIST * oid_block);
153 static void qmgr_add_query_entry (THREAD_ENTRY * thread_p, QMGR_QUERY_ENTRY * q_ptr, int trans_ind);
154 static QMGR_QUERY_ENTRY *qmgr_find_query_entry (QMGR_QUERY_ENTRY * query_list_p, QUERY_ID query_id);
155 static void qmgr_delete_query_entry (THREAD_ENTRY * thread_p, QUERY_ID query_id, int trans_ind);
156 static void qmgr_free_tran_entries (void);
157 
158 static void qmgr_clear_relative_cache_entries (THREAD_ENTRY * thread_p, QMGR_TRAN_ENTRY * tran_entry_p);
159 static bool qmgr_is_related_class_modified (THREAD_ENTRY * thread_p, XASL_CACHE_ENTRY * xasl_cache, int tran_index);
161 static void qmgr_free_oid_block (THREAD_ENTRY * thread_p, OID_BLOCK_LIST * oid_block);
162 static int qmgr_init_external_file_page (THREAD_ENTRY * thread_p, PAGE_PTR page, void *args);
164 static int qmgr_free_query_temp_file_helper (THREAD_ENTRY * thread_p, QMGR_QUERY_ENTRY * query_p);
165 static int qmgr_free_query_temp_file (THREAD_ENTRY * thread_p, QMGR_QUERY_ENTRY * qptr, int tran_idx);
166 static QMGR_TEMP_FILE *qmgr_allocate_tempfile_with_buffer (int num_buffer_pages);
167 
168 #if defined (SERVER_MODE)
169 static XASL_NODE *qmgr_find_leaf (XASL_NODE * xasl);
170 static QFILE_LIST_ID *qmgr_process_query (THREAD_ENTRY * thread_p, XASL_NODE * xasl_tree, char *xasl_stream,
171  int xasl_stream_size, int dbval_count, const DB_VALUE * dbvals_p,
172  QUERY_FLAG flag, QMGR_QUERY_ENTRY * query_p, QMGR_TRAN_ENTRY * tran_entry_p);
173 static void qmgr_reset_query_exec_info (int tran_index);
174 static void qmgr_set_query_exec_info_to_tdes (int tran_index, int query_timeout, const XASL_ID * xasl_id);
175 #endif
176 
177 static void qmgr_initialize_temp_file_list (QMGR_TEMP_FILE_LIST * temp_file_list_p,
178  QMGR_TEMP_FILE_MEMBUF_TYPE membuf_type);
179 static void qmgr_finalize_temp_file_list (QMGR_TEMP_FILE_LIST * temp_file_list_p);
181 static void qmgr_put_temp_file_into_list (QMGR_TEMP_FILE * temp_file_p);
182 
183 static int copy_bind_value_to_tdes (THREAD_ENTRY * thread_p, int num_bind_vals, DB_VALUE * bind_vals);
184 
185 /*
186  * qmgr_get_page_type () -
187  *
188  * return: QMGR_PAGE_TYPE
189  *
190  * page_p(in):
191  * temp_file_p(in):
192  */
193 static QMGR_PAGE_TYPE
195 {
196  PAGE_PTR begin_page = NULL, end_page = NULL;
197 
198  if (temp_file_p != NULL && temp_file_p->membuf_last >= 0 && temp_file_p->membuf && page_p >= temp_file_p->membuf[0]
199  && page_p <= temp_file_p->membuf[temp_file_p->membuf_last])
200  {
201  return QMGR_MEMBUF_PAGE;
202  }
203 
204  begin_page = (PAGE_PTR) ((PAGE_PTR) temp_file_p->membuf
205  + DB_ALIGN (sizeof (PAGE_PTR) * temp_file_p->membuf_npages, MAX_ALIGNMENT));
206  end_page = begin_page + temp_file_p->membuf_npages * DB_PAGESIZE;
207  if (begin_page <= page_p && page_p <= end_page)
208  {
209  /* defense code */
210  assert (false);
211  return QMGR_UNKNOWN_PAGE;
212  }
213 
214  return QMGR_TEMP_FILE_PAGE;
215 }
216 
217 static bool
219 {
220  static int query_cache_mode = prm_get_integer_value (PRM_ID_LIST_QUERY_CACHE_MODE);
221 
223  {
224  return false;
225  }
226 
227  if (query_cache_mode == QFILE_LIST_QUERY_CACHE_MODE_OFF
228  || query_cache_mode == QFILE_LIST_QUERY_CACHE_MODE_SELECTIVELY_OFF
229  || (query_cache_mode == QFILE_LIST_QUERY_CACHE_MODE_SELECTIVELY_ON && !(flag & RESULT_CACHE_REQUIRED)))
230  {
231  return false;
232  }
233 
234  return true;
235 }
236 
237 static void
239 {
240  OR_PUT_INT ((page_p) + QFILE_TUPLE_COUNT_OFFSET, (header_p)->pg_tplcnt);
241  OR_PUT_INT ((page_p) + QFILE_PREV_PAGE_ID_OFFSET, (header_p)->prev_pgid);
242  OR_PUT_INT ((page_p) + QFILE_NEXT_PAGE_ID_OFFSET, (header_p)->next_pgid);
243  OR_PUT_INT ((page_p) + QFILE_LAST_TUPLE_OFFSET, (header_p)->lasttpl_off);
244  OR_PUT_INT ((page_p) + QFILE_OVERFLOW_PAGE_ID_OFFSET, (header_p)->ovfl_pgid);
245  OR_PUT_SHORT ((page_p) + QFILE_PREV_VOL_ID_OFFSET, (header_p)->prev_volid);
246  OR_PUT_SHORT ((page_p) + QFILE_NEXT_VOL_ID_OFFSET, (header_p)->next_volid);
247  OR_PUT_SHORT ((page_p) + QFILE_OVERFLOW_VOL_ID_OFFSET, (header_p)->ovfl_volid);
248 #if !defined(NDEBUG)
249  /* suppress valgrind UMW error */
251 #endif
252 }
253 
254 static void
256 {
257  query_p->query_status = QUERY_COMPLETED;
258 }
259 
260 /*
261  * qmgr_allocate_query_entry () -
262  * return: QMGR_QUERY_ENTRY * or NULL
263  *
264  * Note: Allocate a query_entry structure from the free
265  * list of query_entry structures if any, or by malloc to allocate a new
266  * a structure.
267  */
268 static QMGR_QUERY_ENTRY *
270 {
271  QMGR_QUERY_ENTRY *query_p;
272  QUERY_ID hint_query_id;
273  int i;
274  bool usable = false;
275 
276  static_assert (QMGR_MAX_QUERY_ENTRY_PER_TRAN < SHRT_MAX, "Bad query entry count");
277 
278  query_p = tran_entry_p->free_query_entry_list_p;
279 
280  if (query_p)
281  {
282  tran_entry_p->free_query_entry_list_p = query_p->next;
283  }
284  else if (QMGR_MAX_QUERY_ENTRY_PER_TRAN < tran_entry_p->num_query_entries)
285  {
287  return NULL;
288  }
289  else
290  {
291  query_p = (QMGR_QUERY_ENTRY *) malloc (sizeof (QMGR_QUERY_ENTRY));
292  if (query_p == NULL)
293  {
295  return NULL;
296  }
297 
298  query_p->list_id = NULL;
299 
300  tran_entry_p->num_query_entries++;
301  }
302 
303  /* assign query id */
304  hint_query_id = 0;
305  for (i = 0; i < QMGR_MAX_QUERY_ENTRY_PER_TRAN; i++)
306  {
307  if (tran_entry_p->query_id_generator >= SHRT_MAX - 2) /* overflow happened */
308  {
309  tran_entry_p->query_id_generator = 0;
310  }
311  query_p->query_id = ++tran_entry_p->query_id_generator;
312 
313  usable = session_is_queryid_idle (thread_p, query_p->query_id, &hint_query_id);
314  if (usable == true)
315  {
316  /* it is usable */
317  break;
318  }
319 
320  if (i == 0)
321  {
322  /* optimization: The second try uses the current max query_id as hint.
323  * This may help us to quickly locate an available id.
324  */
325  assert (hint_query_id != 0);
326  tran_entry_p->query_id_generator = (int) hint_query_id;
327  }
328  }
329  assert (usable == true);
330 
331  /* initialize per query temp file VFID structure */
332  query_p->next = NULL;
333  query_p->temp_vfid = NULL;
334  query_p->num_tmp = 0;
335  query_p->total_count = 0;
336  XASL_ID_SET_NULL (&query_p->xasl_id);
337  query_p->xasl_ent = NULL;
338  query_p->list_id = NULL;
339  query_p->list_ent = NULL;
340  query_p->errid = NO_ERROR;
341  query_p->er_msg = NULL;
342  query_p->query_flag = 0;
343  query_p->is_holdable = false;
344  query_p->includes_tde_class = false;
345 
346 #if defined (NDEBUG)
347  /* just a safe guard for a release build. I don't expect it will be hit. */
348  if (usable == false)
349  {
350  qmgr_free_query_entry (thread_p, tran_entry_p, query_p);
351  return NULL;
352  }
353 #endif /* NDEBUG */
354 
355  return query_p;
356 }
357 
358 /*
359  * qmgr_free_query_entry () -
360  * return:
361  * q_ptr(in) : Query entry structure to be freed
362  *
363  * Note: Free the query_entry structure by putting it to the free
364  * query_entry structure list if there are not many in the list,
365  * or by calling db_free.
366  */
367 static void
369 {
370 #if defined (SERVER_MODE)
371  if (query_p->er_msg)
372  {
373  free_and_init (query_p->er_msg);
374  }
375 #endif
376 
377  if (query_p->list_id)
378  {
380  }
381 
382  query_p->next = NULL;
383 
384  query_p->next = tran_entry_p->free_query_entry_list_p;
385  tran_entry_p->free_query_entry_list_p = query_p;
386 }
387 
388 /*
389  * qmgr_deallocate_oid_blocks () -
390  * return:
391  * oid_blocks(in) : oid_block pointer
392  *
393  * Note: Free the area allocated for the oid_blocks
394  */
395 static void
397 {
398  OID_BLOCK_LIST *oid;
399 
400  while (oid_block)
401  {
402  oid = oid_block;
403  oid_block = oid_block->next;
404 
405  free (oid);
406  }
407 }
408 
409 /*
410  * qmgr_deallocate_query_entries () -
411  * return:
412  * q_ptr(in) : Query Entry Pointer
413  *
414  * Note: Free the area allocated for the query entry list
415  */
416 static void
418 {
420 
421  while (query_p)
422  {
423  p = query_p;
424  query_p = query_p->next;
425 
426 #if defined (SERVER_MODE)
427  if (p->er_msg)
428  {
429  free_and_init (p->er_msg);
430  }
431 #endif
432 
433  if (p->list_id)
434  {
436  }
437 
438  free_and_init (p);
439  }
440 }
441 
442 /*
443  * qmgr_add_query_entry () -
444  * return:
445  * q_ptr(in) : Query Entry Pointer
446  * trans_ind(in) : this transaction index
447  *
448  * Note: Add the given query entry to the list of query entries for the
449  * current transaction.
450  */
451 static void
452 qmgr_add_query_entry (THREAD_ENTRY * thread_p, QMGR_QUERY_ENTRY * query_p, int tran_index)
453 {
454  QMGR_TRAN_ENTRY *tran_entry_p;
455 
456  if (tran_index == NULL_TRAN_INDEX)
457  {
458  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
459  }
460  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
461 
462  if (tran_entry_p->trans_stat == QMGR_TRAN_NULL || tran_entry_p->trans_stat == QMGR_TRAN_TERMINATED)
463  {
464  tran_entry_p->trans_stat = QMGR_TRAN_RUNNING;
465  tran_entry_p->query_entry_list_p = query_p;
466  }
467  else
468  {
469  query_p->next = tran_entry_p->query_entry_list_p;
470  tran_entry_p->query_entry_list_p = query_p;
471  }
472 }
473 
474 static QMGR_QUERY_ENTRY *
475 qmgr_find_query_entry (QMGR_QUERY_ENTRY * query_list_p, QUERY_ID query_id)
476 {
477  QMGR_QUERY_ENTRY *query_p;
478 
479  query_p = query_list_p;
480  while (query_p && query_p->query_id != query_id)
481  {
482  query_p = query_p->next;
483  }
484 
485  return query_p;
486 }
487 
488 /*
489  * qmgr_get_query_entry () -
490  * return: QMGR_QUERY_ENTRY *
491  * query_id(in) : query identifier
492  * trans_ind(in) : this transaction index(NULL_TRAN_INDEX for unknown)
493  *
494  * Note: Return the query entry pointer for the given query identifier
495  * or NULL if the query entry is not found.
496  */
498 qmgr_get_query_entry (THREAD_ENTRY * thread_p, QUERY_ID query_id, int tran_index)
499 {
500  QMGR_QUERY_ENTRY *query_p = NULL;
501  QMGR_TRAN_ENTRY *tran_entry_p;
502 
503  /*
504  * The code for finding the query_entry pointer is in-lined in
505  * xqmgr_end_query and qmgr_is_query_interrupted to avoid calling this function.
506  */
507 
508  if (qmgr_Query_table.tran_entries_p == NULL)
509  {
510  return query_p;
511  }
512 
513  if (tran_index == NULL_TRAN_INDEX)
514  {
515  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
516  }
517 
518  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
519 
520  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
521  if (query_p != NULL)
522  {
523  return query_p;
524  }
525 
526  /* Maybe it is a holdable result and we'll find it in the session state object. In order to be able to use this
527  * result, we need to create a new entry for this query in the transaction query entries and copy result information
528  * from the session. */
529  query_p = qmgr_allocate_query_entry (thread_p, tran_entry_p);
530  if (query_p == NULL)
531  {
532  return NULL;
533  }
534 
535  query_p->query_id = query_id;
536  if (xsession_load_query_entry_info (thread_p, query_p) != NO_ERROR)
537  {
538  qmgr_free_query_entry (thread_p, tran_entry_p, query_p);
539  query_p = NULL;
540 
541  return NULL;
542  }
543 
544  /* add it to this transaction also */
545  qmgr_add_query_entry (thread_p, query_p, tran_index);
546 
547  return query_p;
548 }
549 
550 /*
551  * qmgr_delete_query_entry () -
552  * return:
553  * query_id(in) : query identifier
554  * trans_ind(in) : this transaction index(NULL_TRAN_INDEX for unknown)
555  *
556  * Note: Delete the query entry for the given query identifier from the
557  * query entry list for the current transaction.
558  */
559 static void
560 qmgr_delete_query_entry (THREAD_ENTRY * thread_p, QUERY_ID query_id, int tran_index)
561 {
562  QMGR_QUERY_ENTRY *query_p = NULL, *prev_query_p = NULL;
563  QMGR_TRAN_ENTRY *tran_entry_p;
564 
565  if (qmgr_Query_table.tran_entries_p == NULL)
566  {
567  return;
568  }
569 
570  if (tran_index == NULL_TRAN_INDEX)
571  {
572  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
573  }
574 
575  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
576 
577  prev_query_p = NULL;
578  query_p = tran_entry_p->query_entry_list_p;
579 
580  while (query_p && query_p->query_id != query_id)
581  {
582  prev_query_p = query_p;
583  query_p = query_p->next;
584  }
585 
586  if (query_p == NULL)
587  {
588  return;
589  }
590 
591  if (prev_query_p == NULL)
592  {
593  /* entry is the first entry */
594  tran_entry_p->query_entry_list_p = query_p->next;
595 
596  if (tran_entry_p->query_entry_list_p == NULL)
597  {
598  tran_entry_p->trans_stat = QMGR_TRAN_TERMINATED;
599  }
600  }
601  else
602  {
603  prev_query_p->next = query_p->next;
604  }
605 
606  qmgr_free_query_entry (thread_p, tran_entry_p, query_p);
607 }
608 
609 static void
611 {
612  tran_entry_p->trans_stat = QMGR_TRAN_NULL;
613  tran_entry_p->query_id_generator = 0;
614  tran_entry_p->num_query_entries = 0;
615  tran_entry_p->query_entry_list_p = NULL;
616  tran_entry_p->free_query_entry_list_p = NULL;
617  tran_entry_p->modified_classes_p = NULL;
618 }
619 
620 /*
621  * qmgr_allocate_tran_entries () -
622  * return: int (NO_ERROR or ER_FAILED)
623  * num_new_entries(in) : Number of transactions
624  *
625  * Note: Allocates(Reallocates) the area pointed by the query manager
626  * transaction index pointer
627  */
628 int
629 qmgr_allocate_tran_entries (THREAD_ENTRY * thread_p, int num_new_entries)
630 {
631  QMGR_TRAN_ENTRY *tran_entry_p;
632  int i, num_current_entries;
633  size_t tran_entry_size;
634 
635 #if defined (SERVER_MODE)
636  num_new_entries = MAX (num_new_entries, MAX_NTRANS);
637 #endif
638 
639  /* enter critical section, this prevents another to perform malloc/init */
641  {
642  return ER_FAILED;
643  }
644 
645  num_current_entries = qmgr_Query_table.num_trans;
646 
647  if (num_new_entries <= num_current_entries)
648  {
649  /* enough */
651  return NO_ERROR;
652  }
653 
654  tran_entry_size = num_new_entries * sizeof (QMGR_TRAN_ENTRY);
655  if (qmgr_Query_table.tran_entries_p == NULL)
656  {
657  qmgr_Query_table.tran_entries_p = (QMGR_TRAN_ENTRY *) malloc (tran_entry_size);
658  }
659  else
660  {
661  qmgr_Query_table.tran_entries_p = (QMGR_TRAN_ENTRY *) realloc (qmgr_Query_table.tran_entries_p, tran_entry_size);
662  }
663 
664  if (qmgr_Query_table.tran_entries_p == NULL)
665  {
667 
669  return ER_FAILED;
670  }
671 
672  /* initialize newly allocated areas */
673  tran_entry_p = (QMGR_TRAN_ENTRY *) qmgr_Query_table.tran_entries_p + num_current_entries;
674  for (i = qmgr_Query_table.num_trans; i < num_new_entries; i++, tran_entry_p++)
675  {
676  qmgr_initialize_tran_entry (tran_entry_p);
677  }
678 
679  qmgr_Query_table.num_trans = num_new_entries;
680 
682 
683  return NO_ERROR;
684 }
685 
686 /*
687  * qmgr_free_tran_entries () -
688  * return:
689  *
690  * Note: frees the area pointed by the query manager transaction index pointer.
691  */
692 static void
694 {
695  QMGR_TRAN_ENTRY *tran_entry_p;
696  int i;
697 
698  if (qmgr_Query_table.tran_entries_p == NULL)
699  {
700  return;
701  }
702 
703  tran_entry_p = qmgr_Query_table.tran_entries_p;
704  for (i = 0; i < qmgr_Query_table.num_trans; i++)
705  {
709 
710  tran_entry_p++;
711  }
712 
713  free_and_init (qmgr_Query_table.tran_entries_p);
714  qmgr_Query_table.num_trans = 0;
715 }
716 
717 #if defined (CUBRID_DEBUG)
718 static const char *
719 qmgr_get_tran_status_string (QMGR_TRAN_STATUS stat)
720 {
721  switch (stat)
722  {
723  case QMGR_TRAN_NULL:
724  return "QMGR_TRAN_NULL";
725  case QMGR_TRAN_RUNNING:
726  return "QMGR_TRAN_NULL";
728  return "QMGR_TRAN_DELAYED_START";
729  case QMGR_TRAN_WAITING:
730  return "QMGR_TRAN_WAITING";
732  return "QMGR_TRAN_RESUME_TO_DEALLOCATE";
734  return "QMGR_TRAN_RESUME_DUE_DEADLOCK";
736  return "QMGR_TRAN_TERMINATED";
737  default:
738  return "QMGR_UNKNOWN";
739  }
740 }
741 
742 static void
743 qmgr_dump_query_entry (QMGR_QUERY_ENTRY * query_p)
744 {
745  QMGR_TEMP_FILE *temp_vfid_p;
746  QFILE_LIST_ID *list_id_p;
747  int i;
748 
749  fprintf (stdout, "\t\tQuery Entry Structures:\n");
750  fprintf (stdout, "\t\tquery_id: %lld\n", (long long) query_p->query_id);
751  fprintf (stdout, "\t\txasl_id: {{%08x | %08x | %08x | %08x | %08x}, {%d sec %d usec}}\n",
753  fprintf (stdout, "\t\tlist_id: %p\n", (void *) query_p->list_id);
754 
755  if (query_p->list_id)
756  {
757  list_id_p = query_p->list_id;
758  fprintf (stdout,
759  "\t\t{type_list: {%d, %p}, tuple_cnt: %d, page_cnt: %d,\n"
760  "\t first_vpid: {%d, %d}, last_vpid: {%d, %d},\n"
761  "\t last_pgptr: %p, last_offset: %d, lasttpl_len: %d}\n", list_id_p->type_list.type_cnt,
762  (void *) list_id_p->type_list.domp, list_id_p->tuple_cnt, list_id_p->page_cnt,
763  list_id_p->first_vpid.pageid, list_id_p->first_vpid.volid, list_id_p->last_vpid.pageid,
764  list_id_p->last_vpid.volid, list_id_p->last_pgptr, list_id_p->last_offset, list_id_p->lasttpl_len);
765  }
766 
767  if (query_p->temp_vfid)
768  {
769  temp_vfid_p = query_p->temp_vfid;
770 
771  do
772  {
773  fprintf (stdout, "\t\tfile_vfid: %p\n", (void *) &temp_vfid_p);
774 
775  temp_vfid_p = temp_vfid_p->next;
776  }
777  while (temp_vfid_p != query_p->temp_vfid);
778  }
779 
780  fprintf (stdout, "\t\tnext: %p\n\n", (void *) query_p->next);
781 }
782 
783 /*
784  * qmgr_dump () -
785  * return:
786  *
787  * Note: Dump query manager table for debugging purposes.
788  */
789 void
790 qmgr_dump (void)
791 {
792  QMGR_TRAN_ENTRY *tran_entry_p;
793  QMGR_QUERY_ENTRY *query_p;
794  int waiting_count, running_count;
795  int i;
796 
797  /* Get statistics from query manager table */
798  waiting_count = running_count = 0;
799 
800  tran_entry_p = qmgr_Query_table.tran_entries_p;
801  for (i = 0; i < qmgr_Query_table.num_trans; i++)
802  {
803  if (tran_entry_p->trans_stat == QMGR_TRAN_WAITING)
804  {
805  waiting_count++;
806  }
807  else if (tran_entry_p->trans_stat == QMGR_TRAN_RUNNING)
808  {
809  running_count++;
810  }
811 
812  tran_entry_p++;
813  }
814 
815  fprintf (stdout, "\n\tQUERY MANAGER TRANSACTION STRUCTURES: \n");
816  fprintf (stdout, "\t===================================== \n");
817  fprintf (stdout, "\tTrans_cnt: %d\n", qmgr_Query_table.num_trans);
818  fprintf (stdout, "\tWait_trans_cnt: %d\n", waiting_count);
819  fprintf (stdout, "\tRun_trans_cnt: %d\n", running_count);
820  fprintf (stdout, "\n\tTransaction index array: \n");
821  fprintf (stdout, "\t------------------------ \n");
822 
823  tran_entry_p = qmgr_Query_table.tran_entries_p;
824  for (i = 0; i < qmgr_Query_table.num_trans; i++)
825  {
826  fprintf (stdout, "\tTrans_ind: %d\n", i);
827  fprintf (stdout, "\tTrans_stat: %s\n", qmgr_get_tran_status_string (tran_entry_p->trans_stat));
828 
829  fprintf (stdout, "\tTrans_query_entries:\n");
830 
831  for (query_p = tran_entry_p->query_entry_list_p; query_p; query_p = query_p->next)
832  {
833  qmgr_dump_query_entry (query_p);
834  }
835 
836  fprintf (stdout, "\t------------------------ \n");
837  tran_entry_p++;
838  }
839 }
840 #endif
841 
842 /*
843  * qmgr_initialize () -
844  * return: int (NO_ERROR or ER_FAILED)
845  *
846  * Note: Initializes the query manager and the query file manager
847  * global variables.
848  */
849 int
851 {
852  int total_tran_indices;
853 #if !defined(SERVER_MODE)
854  struct timeval t;
855 #endif
856 
858  {
859  return ER_FAILED;
860  }
861 
862  if (qmgr_Query_table.tran_entries_p == NULL)
863  {
864  total_tran_indices = logtb_get_number_of_total_tran_indices ();
865  if (qmgr_allocate_tran_entries (thread_p, total_tran_indices) != NO_ERROR)
866  {
868  return ER_FAILED;
869  }
870  }
871 
872  if (qmgr_Query_table.temp_file_list[TEMP_FILE_MEMBUF_NORMAL].list != NULL)
873  {
875  }
877 
878  if (qmgr_Query_table.temp_file_list[TEMP_FILE_MEMBUF_KEY_BUFFER].list != NULL)
879  {
881  }
884 
886 
887  qfile_initialize ();
888 
889 #if defined (SERVER_MODE)
890  numeric_init_power_value_string ();
891 #endif
892 
893  srand48 ((long) time (NULL));
894 
895 #if !defined(SERVER_MODE)
896  gettimeofday (&t, NULL);
897  srand48_r ((long) t.tv_usec, &qmgr_rand_buf);
898 #endif
899 
900  return scan_initialize ();
901 }
902 
903 /*
904  * qmgr_finalize () -
905  * return:
906  *
907  * Note: Finalizes the query manager functioning by deallocating the
908  * memory area pointed by transaction index list pointer.
909  */
910 void
912 {
913  int i;
914 
915  scan_finalize ();
916  qfile_finalize ();
917 
919  {
920  return;
921  }
922 
924 
925  assert (qmgr_Query_table.tran_entries_p == NULL && qmgr_Query_table.num_trans == 0);
926 
927  for (i = 0; i < QMGR_NUM_TEMP_FILE_LISTS; i++)
928  {
929  qmgr_finalize_temp_file_list (&qmgr_Query_table.temp_file_list[i]);
930  }
931 
933 }
934 
935 /*
936  * xqmgr_prepare_query () - Prepares a query for later (and repetitive) execution
937  * return : Error code.
938  * thread_p (in) : thread entry.
939  * context (in) : query string; used for hash key of the XASL cache
940  * stream (in/out) : XASL stream, size, xasl_id & xasl_header info; set to NULL if you want to look up the XASL cache
941  *
942  * Note: Store the given XASL stream into the XASL file and return its file id.
943  * The XASL file is a temporay file, ..
944  * If NULL is given as the input argument xasl_stream, this function will look up the XASL cache,
945  * and return the cached XASL file id if found. If not found, NULL will be returned.
946  */
947 int
949 {
950  XASL_CACHE_ENTRY *cache_entry_p = NULL;
951  char *p;
952  int header_size;
953  int i;
954  OID creator_oid, *class_oid_list_p = NULL;
955  int n_oid_list, *tcard_list_p = NULL;
956  int *class_locks = NULL;
957  int dbval_cnt;
958  int error_code = NO_ERROR;
959  xasl_cache_rt_check_result recompile_due_to_threshold = XASL_CACHE_RECOMPILE_NOT_NEEDED;
960 
961  /* If xasl_stream is NULL, it means that the client requested looking up the XASL cache to know there's a reusable
962  * execution plan (XASL) for this query. The XASL is stored as a file so that the XASL file id (XASL_ID) will be
963  * returned if found in the cache.
964  */
965 
966  if (stream->buffer == NULL && context->recompile_xasl)
967  {
968  /* Recompile requested by no xasl_stream is provided. */
969  assert_release (false);
970  return ER_FAILED;
971  }
972 
973  XASL_ID_SET_NULL (stream->xasl_id);
974  if (!context->recompile_xasl)
975  {
976  error_code =
977  xcache_find_sha1 (thread_p, &context->sha1, XASL_CACHE_SEARCH_FOR_PREPARE, &cache_entry_p,
978  &recompile_due_to_threshold);
979  if (error_code != NO_ERROR)
980  {
981  assert (false);
982  return error_code;
983  }
984  if (cache_entry_p != NULL)
985  {
986  if (recompile_due_to_threshold != XASL_CACHE_RECOMPILE_NOT_NEEDED)
987  {
988  assert (recompile_due_to_threshold == XASL_CACHE_RECOMPILE_PREPARE);
989  XASL_ID_COPY (stream->xasl_id, &cache_entry_p->xasl_id);
990  xcache_unfix (thread_p, cache_entry_p);
991  context->recompile_xasl = true;
992  return NO_ERROR;
993  }
994  else
995  {
996  /* Found entry. */
997  XASL_ID_COPY (stream->xasl_id, &cache_entry_p->xasl_id);
998  if (stream->buffer == NULL && stream->xasl_header != NULL)
999  {
1000  /* also header was requested. */
1001  qfile_load_xasl_node_header (thread_p, stream->buffer, stream->xasl_header);
1002  }
1003  xcache_unfix (thread_p, cache_entry_p);
1004  goto exit_on_end;
1005  }
1006  }
1007  if (stream->buffer == NULL)
1008  {
1009  /* No entry found. */
1010  if (recompile_due_to_threshold != XASL_CACHE_RECOMPILE_NOT_NEEDED)
1011  {
1012  /* We need to force recompile. */
1013  assert (recompile_due_to_threshold == XASL_CACHE_RECOMPILE_PREPARE);
1014  context->recompile_xasl = true;
1015  }
1016  return NO_ERROR;
1017  }
1018  }
1019  /* Add new entry to xasl cache. */
1020  assert (cache_entry_p == NULL);
1021  assert (stream->buffer != NULL);
1022 
1023  /* get some information from the XASL stream */
1024  p = or_unpack_int ((char *) stream->buffer, &header_size);
1025  p = or_unpack_int (p, &dbval_cnt);
1026  p = or_unpack_oid (p, &creator_oid);
1027  p = or_unpack_int (p, &n_oid_list);
1028 
1029  if (n_oid_list > 0)
1030  {
1031  class_oid_list_p = (OID *) db_private_alloc (thread_p, sizeof (OID) * n_oid_list);
1032  class_locks = (int *) db_private_alloc (thread_p, sizeof (LOCK) * n_oid_list);
1033  tcard_list_p = (int *) db_private_alloc (thread_p, sizeof (int) * n_oid_list);
1034  if (class_oid_list_p == NULL || class_locks == NULL || tcard_list_p == NULL)
1035  {
1036  ASSERT_ERROR_AND_SET (error_code);
1037  goto exit_on_error;
1038  }
1039 
1040  for (i = 0; i < n_oid_list; i++)
1041  {
1042  p = or_unpack_oid (p, &class_oid_list_p[i]);
1043  }
1044  for (i = 0; i < n_oid_list; i++)
1045  {
1046  p = or_unpack_int (p, &class_locks[i]);
1047  }
1048  for (i = 0; i < n_oid_list; i++)
1049  {
1050  p = or_unpack_int (p, &tcard_list_p[i]);
1051  }
1052  }
1053  else
1054  {
1055  class_oid_list_p = NULL;
1056  class_locks = NULL;
1057  tcard_list_p = NULL;
1058  }
1059 
1060  error_code =
1061  xcache_insert (thread_p, context, stream, n_oid_list, class_oid_list_p, class_locks, tcard_list_p, &cache_entry_p);
1062  if (error_code != NO_ERROR)
1063  {
1064  ASSERT_ERROR ();
1065  goto exit_on_error;
1066  }
1067  if (cache_entry_p == NULL)
1068  {
1069  assert (false);
1071  error_code = ER_FAILED;
1072  goto exit_on_error;
1073  }
1074  XASL_ID_COPY (stream->xasl_id, &cache_entry_p->xasl_id);
1075  xcache_unfix (thread_p, cache_entry_p);
1076 
1077 exit_on_end:
1078 
1079  if (class_oid_list_p)
1080  {
1081  db_private_free_and_init (thread_p, class_oid_list_p);
1082  }
1083  if (class_locks)
1084  {
1085  db_private_free_and_init (thread_p, class_locks);
1086  }
1087  if (tcard_list_p)
1088  {
1089  db_private_free_and_init (thread_p, tcard_list_p);
1090  }
1091 
1092  return error_code;
1093 
1094 exit_on_error:
1095 
1096  assert (error_code != NO_ERROR);
1097  ASSERT_ERROR ();
1098  goto exit_on_end;
1099 }
1100 
1101 /*
1102  * qmgr_process_query () - Execute a prepared query as sync mode
1103  * return : query result file id
1104  * thread_p (in) : Thread entry.
1105  * xasl_tree (in) : XASL tree already unpacked or NULL.
1106  * xasl_stream (in) : XASL stream.
1107  * xasl_stream_size (in) : XASL stream size.
1108  * dbval_count (in) : number of host variables
1109  * dbvals_p (in) : array of host variables (query input parameters)
1110  * flag (in) : flag
1111  * query_p (in) : QMGR_QUERY_ENTRY *
1112  * tran_entry_p (in) : QMGR_TRAN_ENTRY *
1113  *
1114  * Note1: The query result is returned through a list id (actually the list
1115  * file). Query id is put for further reference to this query entry.
1116  * If there's an error, NULL will be returned.
1117  *
1118  * Note2: It is the caller's responsibility to free output QFILE_LIST_ID
1119  * by calling QFILE_FREE_AND_INIT_LIST_ID().
1120  */
1121 static QFILE_LIST_ID *
1122 qmgr_process_query (THREAD_ENTRY * thread_p, XASL_NODE * xasl_tree, char *xasl_stream, int xasl_stream_size,
1123  int dbval_count, const DB_VALUE * dbvals_p, QUERY_FLAG flag, QMGR_QUERY_ENTRY * query_p,
1124  QMGR_TRAN_ENTRY * tran_entry_p)
1125 {
1126  XASL_NODE *xasl_p;
1127  XASL_UNPACK_INFO *xasl_buf_info;
1128  QFILE_LIST_ID *list_id;
1129 
1130  assert (query_p != NULL);
1131  assert (tran_entry_p != NULL);
1132 
1133  xasl_p = NULL;
1134  xasl_buf_info = NULL;
1135  list_id = NULL;
1136 
1137  if (xasl_tree != NULL)
1138  {
1139  /* check the number of the host variables for this XASL */
1140  if (xasl_tree->dbval_cnt > dbval_count)
1141  {
1142  er_log_debug (ARG_FILE_LINE, "qmgr_process_query: dbval_cnt mismatch %d vs %d\n", xasl_tree->dbval_cnt,
1143  dbval_count);
1145  goto exit_on_error;
1146  }
1147 
1148  /* Adjust XASL flag for query result cache. For the last list file(QFILE_LIST_ID) as the query result, the
1149  * permanent query result file(FILE_QUERY_AREA) rather than temporary file(FILE_TEMP) will be created if and only
1150  * if XASL_TO_BE_CACHED flag is set. */
1151  if (qmgr_is_allowed_result_cache (flag))
1152  {
1153  XASL_SET_FLAG (xasl_tree, XASL_TO_BE_CACHED);
1154  }
1155  xasl_p = xasl_tree;
1156  }
1157  else
1158  {
1159  if (stx_map_stream_to_xasl (thread_p, &xasl_p, false, xasl_stream, xasl_stream_size, &xasl_buf_info) != NO_ERROR)
1160  {
1161  goto exit_on_error;
1162  }
1163  }
1164 
1166 #if !defined(NDEBUG)
1167  er_log_debug (ARG_FILE_LINE, "TDE: qmgr_process_query(): includes_tde_class = %d\n", query_p->includes_tde_class);
1168 #endif /* !NDEBUG */
1169 
1170 
1171  if (flag & RETURN_GENERATED_KEYS)
1172  {
1174  }
1175 
1176  /* execute the query with the value list, if any */
1177  query_p->list_id = qexec_execute_query (thread_p, xasl_p, dbval_count, dbvals_p, query_p->query_id);
1178  thread_p->no_logging = false;
1179 
1180  /* Note: qexec_execute_query() returns listid (NOT NULL) even if an error was occurred. We should check the error
1181  * condition and free listid. */
1182  if (query_p->errid < 0)
1183  { /* error has occurred */
1184  if (query_p->list_id)
1185  {
1187  }
1188  /* error occurred during executing the query */
1189  goto exit_on_error;
1190  }
1191 
1192  assert (query_p->list_id != NULL);
1193 
1194  /* allocate new QFILE_LIST_ID to be returned as the result and copy from the query result; the caller is responsible
1195  * to free this */
1196  list_id = qfile_clone_list_id (query_p->list_id, false);
1197  if (list_id == NULL)
1198  {
1199  goto exit_on_error;
1200  }
1201  assert (list_id->sort_list == NULL);
1202 
1203  list_id->last_pgptr = NULL;
1204 
1205 end:
1206 
1207  if (xasl_buf_info)
1208  {
1209  /* free the XASL tree */
1210  free_xasl_unpack_info (thread_p, xasl_buf_info);
1211  }
1212 
1213  return list_id;
1214 
1215 exit_on_error:
1216 
1217  assert (list_id == NULL);
1218  goto end;
1219 }
1220 
1221 /*
1222  * xqmgr_execute_query () - Execute a prepared query
1223  * return: query result file id
1224  * thrd(in) :
1225  * xasl_id(in) : XASL file id that was a result of prepare_query()
1226  * query_idp(out) : query id to be used for getting results
1227  * dbval_count(in) : number of host variables
1228  * dbval_p(in) : array of host variables (query input parameters)
1229  * flagp(in) : flag
1230  * clt_cache_time(in) :
1231  * srv_cache_time(in) :
1232  * query_timeout(in) : query_timeout in millisec.
1233  * info(out) : execution info from server
1234  *
1235  * Note1: The query result is returned through a list id (actually the list
1236  * file). Query id is put for further refernece to this query entry.
1237  * If there's an error, NULL will be returned.
1238  *
1239  * Note2: It is the caller's responsibility to free output QFILE_LIST_ID
1240  * by calling QFILE_FREE_AND_INIT_LIST_ID().
1241  */
1242 QFILE_LIST_ID *
1243 xqmgr_execute_query (THREAD_ENTRY * thread_p, const XASL_ID * xasl_id_p, QUERY_ID * query_id_p, int dbval_count,
1244  void *dbval_p, QUERY_FLAG * flag_p, CACHE_TIME * client_cache_time_p,
1245  CACHE_TIME * server_cache_time_p, int query_timeout, xasl_cache_ent ** ret_cache_entry_p)
1246 {
1247  XASL_CACHE_ENTRY *xasl_cache_entry_p = NULL;
1249  QFILE_LIST_CACHE_ENTRY *list_cache_entry_p;
1250  DB_VALUE *dbvals_p;
1251 #if defined (SERVER_MODE)
1252  DB_VALUE *dbval;
1253  HL_HEAPID old_pri_heap_id;
1254  char *data;
1255  int i;
1256 #endif
1257  DB_VALUE_ARRAY params;
1258  QMGR_QUERY_ENTRY *query_p;
1259  int tran_index = -1;
1260  QMGR_TRAN_ENTRY *tran_entry_p;
1261  QFILE_LIST_ID *list_id_p, *tmp_list_id_p;
1262  bool cached_result;
1263  bool saved_is_stats_on;
1264  bool xasl_trace;
1265  bool is_xasl_pinned_reference;
1266  bool do_not_cache = false;
1267 
1268  cached_result = false;
1269  query_p = NULL;
1270  *query_id_p = -1;
1271  list_id_p = NULL;
1272  xasl_cache_entry_p = NULL;
1273  list_cache_entry_p = NULL;
1274 
1275  dbvals_p = NULL;
1276 #if defined (SERVER_MODE)
1277  data = (char *) dbval_p;
1278  old_pri_heap_id = 0;
1279 #endif
1280 
1281 #if defined (SERVER_MODE)
1282  assert (thread_get_recursion_depth (thread_p) == 0);
1283 #elif defined (SA_MODE)
1285 #endif
1286 
1287  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1288 
1289  saved_is_stats_on = perfmon_server_is_stats_on (thread_p);
1290 
1291  xasl_trace = IS_XASL_TRACE_TEXT (*flag_p) || IS_XASL_TRACE_JSON (*flag_p);
1292 
1293  is_xasl_pinned_reference = IS_XASL_CACHE_PINNED_REFERENCE (*flag_p);
1294 
1295  if (DO_NOT_COLLECT_EXEC_STATS (*flag_p))
1296  {
1297  if (saved_is_stats_on == true)
1298  {
1299  perfmon_stop_watch (thread_p);
1300  }
1301  }
1302  else if (xasl_trace == true)
1303  {
1304  thread_trace_on (thread_p);
1305  perfmon_start_watch (thread_p);
1306 
1307  if (IS_XASL_TRACE_TEXT (*flag_p))
1308  {
1310  }
1311  else if (IS_XASL_TRACE_JSON (*flag_p))
1312  {
1314  }
1315  }
1316 
1317  xasl_cache_entry_p = NULL;
1318  if (xcache_find_xasl_id_for_execute (thread_p, xasl_id_p, &xasl_cache_entry_p, &xclone) != NO_ERROR)
1319  {
1320  ASSERT_ERROR ();
1321  return NULL;
1322  }
1323  if (xasl_cache_entry_p == NULL)
1324  {
1325  /* XASL cache entry not found. */
1328  return NULL;
1329  }
1330  if (xclone.xasl == NULL || xclone.xasl_buf == NULL)
1331  {
1332  assert (false);
1335  return NULL;
1336  }
1337 
1338  if (ret_cache_entry_p)
1339  {
1340  *ret_cache_entry_p = xasl_cache_entry_p;
1341  }
1342 
1343  if (IS_TRIGGER_INVOLVED (*flag_p))
1344  {
1345  session_set_trigger_state (thread_p, true);
1346  }
1347 
1348 #if defined (SERVER_MODE)
1349  if (dbval_count)
1350  {
1351  char *ptr;
1352 
1353  assert (data != NULL);
1354 
1355  dbvals_p = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE) * dbval_count);
1356  if (dbvals_p == NULL)
1357  {
1358  goto exit_on_error;
1359  }
1360 
1361  /* unpack DB_VALUEs from the received data */
1362  ptr = data;
1363  for (i = 0, dbval = dbvals_p; i < dbval_count; i++, dbval++)
1364  {
1365  ptr = or_unpack_db_value (ptr, dbval);
1366  }
1367  }
1368 #else
1369  dbvals_p = (DB_VALUE *) dbval_p;
1370 #endif
1371 
1372  /* If it is not inhibited from getting the cached result, inspect the list cache (query result cache) and get the
1373  * list file id(QFILE_LIST_ID) to be returned to the client if it is in there. The list cache will be searched with
1374  * the XASL cache entry of the target query that is obtained from the XASL_ID, because all results of the query with
1375  * different parameters (host variables - DB_VALUES) are linked at the XASL cache entry.
1376  */
1377  params.size = dbval_count;
1378  params.vals = dbvals_p;
1379 
1380  if (copy_bind_value_to_tdes (thread_p, dbval_count, dbvals_p) != NO_ERROR)
1381  {
1382  goto exit_on_error;
1383  }
1384 
1385  if (qmgr_is_allowed_result_cache (*flag_p))
1386  {
1387  if (qmgr_is_related_class_modified (thread_p, xasl_cache_entry_p, tran_index))
1388  {
1389  do_not_cache = true;
1390  }
1391 
1392  if (do_not_cache == false)
1393  {
1394  /* lookup the list cache with the parameter values (DB_VALUE array) */
1395  list_cache_entry_p =
1396  qfile_lookup_list_cache_entry (thread_p, xasl_cache_entry_p->list_ht_no, &params, &cached_result);
1397  /* If we've got the cached result, return it. */
1398  if (cached_result)
1399  {
1400  /* found the cached result */
1401  CACHE_TIME_MAKE (server_cache_time_p, &list_cache_entry_p->time_created);
1402  }
1403  }
1404  }
1405 
1406  if (client_cache_time_p)
1407  {
1408  CACHE_TIME_RESET (client_cache_time_p);
1409  }
1410 
1411  /* Make an query entry */
1412  /* mark that this transaction is running a query */
1413  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
1414 
1415 #if defined(ENABLE_SYSTEMTAP)
1416  if (tran_entry_p->trans_stat == QMGR_TRAN_NULL || tran_entry_p->trans_stat == QMGR_TRAN_TERMINATED)
1417  {
1418  CUBRID_TRAN_START (tran_index);
1419  }
1420 #endif /* ENABLE_SYSTEMTAP */
1421 
1422 #if defined (SERVER_MODE)
1423  tran_entry_p->trans_stat = QMGR_TRAN_RUNNING;
1424 
1425  /* allocate a new query entry */
1426  query_p = qmgr_allocate_query_entry (thread_p, tran_entry_p);
1427 
1428  /* set a timeout if necessary */
1429  qmgr_set_query_exec_info_to_tdes (tran_index, query_timeout, xasl_id_p);
1430 #else
1431  /* allocate a new query entry */
1432  query_p = qmgr_allocate_query_entry (thread_p, tran_entry_p);
1433 #endif
1434 
1435  if (query_p == NULL)
1436  {
1438  goto exit_on_error;
1439  }
1440 
1441  /* initialize query entry */
1442  XASL_ID_COPY (&query_p->xasl_id, xasl_id_p);
1443  query_p->xasl_ent = xasl_cache_entry_p;
1444  if (cached_result)
1445  {
1446  query_p->list_ent = list_cache_entry_p; /* for qfile_end_use_of_list_cache_entry() */
1447  }
1448  query_p->query_status = QUERY_IN_PROGRESS;
1449  query_p->query_flag = *flag_p;
1450  if (*flag_p & RESULT_HOLDABLE)
1451  {
1452  query_p->is_holdable = true;
1453  }
1454  else
1455  {
1456  query_p->is_holdable = false;
1457  }
1458 
1459  /* add the entry to the query table */
1460  qmgr_add_query_entry (thread_p, query_p, tran_index);
1461 
1462  /* to return query id */
1463  *query_id_p = query_p->query_id;
1464 
1465  /* If we've got the cached result, return it. Else, process the query */
1466  if (cached_result)
1467  {
1468  /* allocate new QFILE_LIST_ID to be stored in the query entry cloning from the QFILE_LIST_ID of the found list
1469  * cache entry */
1470  query_p->list_id = qfile_clone_list_id (&list_cache_entry_p->list_id, false);
1471  if (query_p->list_id == NULL)
1472  {
1473  goto exit_on_error;
1474  }
1475  query_p->list_id->query_id = query_p->query_id;
1476 
1477  /* allocate new QFILE_LIST_ID to be returned as the result and copy from the query result; the caller is
1478  * responsible to free this */
1479  list_id_p = qfile_clone_list_id (query_p->list_id, false);
1480  if (list_id_p == NULL)
1481  {
1482  goto exit_on_error; /* maybe, memory allocation error */
1483  }
1484  list_id_p->last_pgptr = NULL;
1485 
1486  /* mark that the query is completed */
1487  qmgr_mark_query_as_completed (query_p);
1488 
1489  goto end; /* OK */
1490  }
1491 
1492  /* If the result didn't come from the cache, build the execution plan (XASL tree) from the cached(stored) XASL
1493  * stream. */
1494 
1495  assert (cached_result == false);
1496 
1497  list_id_p =
1498  qmgr_process_query (thread_p, xclone.xasl, NULL, 0, dbval_count, dbvals_p, *flag_p, query_p, tran_entry_p);
1499  if (list_id_p == NULL)
1500  {
1501  goto exit_on_error;
1502  }
1503 
1504  /* everything is ok, mark that the query is completed */
1505  qmgr_mark_query_as_completed (query_p);
1506 
1507  /* If it is allowed to cache the query result or if it is required to cache, put the list file id(QFILE_LIST_ID) into
1508  * the list cache. Provided are the corresponding XASL cache entry to be linked, and the parameters (host variables -
1509  * DB_VALUES). */
1510  if (qmgr_is_allowed_result_cache (*flag_p) && do_not_cache == false)
1511  {
1512  /* check once more to ensure that the related XASL entry is still valid */
1513  if (xcache_can_entry_cache_list (xasl_cache_entry_p))
1514  {
1515  if (list_id_p == NULL)
1516  {
1517  goto end;
1518  }
1519 
1520  if (list_cache_entry_p && !cached_result)
1521  {
1522  goto end;
1523  }
1524 
1525  /* the type of the result file should be FILE_QUERY_AREA in order not to deleted at the time of query_end */
1526  if (list_id_p->tfile_vfid != NULL && list_id_p->tfile_vfid->temp_file_type != FILE_QUERY_AREA)
1527  {
1528  /* duplicate the list file */
1529  tmp_list_id_p = qfile_duplicate_list (thread_p, list_id_p, QFILE_FLAG_RESULT_FILE);
1530  if (tmp_list_id_p)
1531  {
1532  qfile_destroy_list (thread_p, list_id_p);
1533  QFILE_FREE_AND_INIT_LIST_ID (list_id_p);
1534  list_id_p = tmp_list_id_p;
1535  }
1536  }
1537  else
1538  {
1539  tmp_list_id_p = list_id_p; /* just for next if condition */
1540  }
1541 
1542  if (tmp_list_id_p == NULL)
1543  {
1544  goto end; /* return without inserting into the cache */
1545  }
1546 
1547  /* update the cache entry for the result associated with the used parameter values (DB_VALUE array) if there
1548  * is, or make new one
1549  * in case list_ht_no is less than 0,
1550  * the cache is not found and should be newly added (surely list_cache_entry_p is null)
1551  * in case list_ht_no is not less than 0 and list_cache_entry_p is null
1552  * the cache entry is found but the entry is used by other transaction
1553  */
1554  if (list_cache_entry_p && xasl_cache_entry_p->list_ht_no < 0)
1555  {
1556  assert (false);
1557  }
1558 
1559  list_cache_entry_p =
1560  qfile_update_list_cache_entry (thread_p, xasl_cache_entry_p->list_ht_no, &params, list_id_p,
1561  xasl_cache_entry_p);
1562 
1563  if (list_cache_entry_p == NULL)
1564  {
1565  char *s;
1566 
1567  s = (params.size > 0) ? pr_valstring (&params.vals[0]) : NULL;
1569  "xqmgr_execute_query: ls_update_xasl failed "
1570  "xasl_id { sha1 { %08x | %08x | %08x | %08x | %08x } time_stored { %d sec %d usec } } "
1571  "params { %d %s ... }\n",
1572  SHA1_AS_ARGS (&xasl_id_p->sha1), CACHE_TIME_AS_ARGS (&xasl_id_p->time_stored),
1573  params.size, s ? s : "(null)");
1574  if (s)
1575  {
1576  db_private_free (thread_p, s);
1577  }
1578 
1579  goto end;
1580  }
1581 
1582  /* record list cache entry into the query entry for qfile_end_use_of_list_cache_entry() */
1583  query_p->list_ent = list_cache_entry_p;
1584 
1585  CACHE_TIME_MAKE (server_cache_time_p, &list_cache_entry_p->time_created);
1586  }
1587  }
1588 
1589 end:
1590 
1591  xcache_retire_clone (thread_p, xasl_cache_entry_p, &xclone);
1592  if (ret_cache_entry_p != NULL && *ret_cache_entry_p != NULL)
1593  {
1594  /* The XASL cache entry is output. */
1595  assert (*ret_cache_entry_p == xasl_cache_entry_p);
1596  }
1597  else if (xasl_cache_entry_p != NULL)
1598  {
1599  xcache_unfix (thread_p, xasl_cache_entry_p);
1600  }
1601 
1602  if (IS_TRIGGER_INVOLVED (*flag_p))
1603  {
1604  session_set_trigger_state (thread_p, false);
1605  }
1606 
1607 #if defined (SERVER_MODE)
1608  if (dbvals_p)
1609  {
1610  for (i = 0, dbval = dbvals_p; i < dbval_count; i++, dbval++)
1611  {
1612  pr_clear_value (dbval);
1613  }
1614  db_private_free_and_init (thread_p, dbvals_p);
1615  }
1616 #endif
1617 
1618  if (DO_NOT_COLLECT_EXEC_STATS (*flag_p) && saved_is_stats_on == true)
1619  {
1620  perfmon_start_watch (thread_p);
1621  }
1622 
1623 #if defined (SERVER_MODE)
1624  qmgr_reset_query_exec_info (tran_index);
1625 #endif
1626 
1627  return list_id_p;
1628 
1629 exit_on_error:
1630 
1631  /* end the use of the cached result if any when an error occurred */
1632  if (cached_result)
1633  {
1634  (void) qfile_end_use_of_list_cache_entry (thread_p, list_cache_entry_p, false);
1635  }
1636 
1637  if (query_p)
1638  {
1639  /* mark that the query is completed and then delete this query entry */
1640  qmgr_mark_query_as_completed (query_p);
1641 
1642  if (qmgr_free_query_temp_file (thread_p, query_p, tran_index) != NO_ERROR)
1643  {
1644  er_log_debug (ARG_FILE_LINE, "xqmgr_execute_query: qmgr_free_query_temp_file");
1645  }
1646 
1647  qmgr_delete_query_entry (thread_p, query_p->query_id, tran_index);
1648  }
1649 
1650  *query_id_p = 0;
1651 
1652  /* free QFILE_LIST_ID */
1653  if (list_id_p)
1654  {
1655  QFILE_FREE_AND_INIT_LIST_ID (list_id_p);
1656  }
1657 
1658  if (xasl_trace == true && saved_is_stats_on == false)
1659  {
1660  perfmon_stop_watch (thread_p);
1661  }
1662 
1663  goto end;
1664 }
1665 
1666 /*
1667  * copy_bind_value_to_tdes - copy bind values to transaction descriptor
1668  * return:
1669  * thread_p(in):
1670  * num_bind_vals(in):
1671  * bind_vals(in):
1672  */
1673 static int
1674 copy_bind_value_to_tdes (THREAD_ENTRY * thread_p, int num_bind_vals, DB_VALUE * bind_vals)
1675 {
1676  LOG_TDES *tdes;
1677  DB_VALUE *vals;
1678  int i;
1679  HL_HEAPID save_heap_id;
1680 
1681  tdes = LOG_FIND_CURRENT_TDES (thread_p);
1682  if (tdes == NULL)
1683  {
1684  return ER_FAILED;
1685  }
1686 
1687  if (tdes != NULL && tdes->num_exec_queries < MAX_NUM_EXEC_QUERY_HISTORY)
1688  {
1689  tdes->bind_history[tdes->num_exec_queries].vals = NULL;
1690  tdes->bind_history[tdes->num_exec_queries].size = num_bind_vals;
1691 
1692  if (num_bind_vals > 0)
1693  {
1694  save_heap_id = db_change_private_heap (thread_p, 0);
1695 
1696  vals = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE) * num_bind_vals);
1697  if (vals == NULL)
1698  {
1699  (void) db_change_private_heap (thread_p, save_heap_id);
1700  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (DB_VALUE) * num_bind_vals);
1701 
1702  return ER_OUT_OF_VIRTUAL_MEMORY;
1703  }
1704 
1705  for (i = 0; i < num_bind_vals; i++)
1706  {
1707  pr_clone_value (&bind_vals[i], &vals[i]);
1708  }
1709 
1710  tdes->bind_history[tdes->num_exec_queries].vals = vals;
1711  (void) db_change_private_heap (thread_p, save_heap_id);
1712  }
1713  }
1714 
1715  tdes->num_exec_queries++;
1716  return NO_ERROR;
1717 }
1718 
1719 /*
1720  * xqmgr_prepare_and_execute_query () -
1721  * return: Query result file identifier, or NULL
1722  * thrd(in) :
1723  * xasl_stream(in) : XASL tree pointer in unprepared form
1724  * xasl_stream_size(in) : memory area size pointed by the xasl_stream
1725  * query_id(in) :
1726  * dbval_count(in) : Number of positional values
1727  * dbval_p(in) : List of positional values
1728  * flag(in) :
1729  * query_timeout(in): set a timeout only if it is positive
1730  *
1731  * Note: The specified query is executed and the query result structure
1732  * which will be basically used for client side cursor operations
1733  * is returned. If val_cnt > 0, the list of given positional
1734  * values are used during query execution.
1735  * The query plan is dropped after the execution.
1736  * If there is an error, NULL is returned.
1737  */
1738 QFILE_LIST_ID *
1739 xqmgr_prepare_and_execute_query (THREAD_ENTRY * thread_p, char *xasl_stream, int xasl_stream_size,
1740  QUERY_ID * query_id_p, int dbval_count, void *dbval_p, QUERY_FLAG * flag_p,
1741  int query_timeout)
1742 {
1743 #if defined (SERVER_MODE)
1744  DB_VALUE *dbval;
1745  HL_HEAPID old_pri_heap_id;
1746  char *data;
1747  int i;
1748 #endif
1749  DB_VALUE *dbvals_p;
1750  QMGR_QUERY_ENTRY *query_p;
1751  QFILE_LIST_ID *list_id_p;
1752  int tran_index;
1753  QMGR_TRAN_ENTRY *tran_entry_p;
1754  bool saved_is_stats_on;
1755  bool xasl_trace;
1756 
1757  query_p = NULL;
1758  *query_id_p = -1;
1759  list_id_p = NULL;
1760 
1761  dbvals_p = NULL;
1762  assert (thread_get_recursion_depth (thread_p) == 0);
1763 
1764 #if defined (SERVER_MODE)
1765  data = (char *) dbval_p;
1766  old_pri_heap_id = 0;
1767 #endif
1768 
1769  saved_is_stats_on = perfmon_server_is_stats_on (thread_p);
1770  xasl_trace = IS_XASL_TRACE_TEXT (*flag_p) || IS_XASL_TRACE_JSON (*flag_p);
1771 
1772  if (DO_NOT_COLLECT_EXEC_STATS (*flag_p))
1773  {
1774  if (saved_is_stats_on == true)
1775  {
1776  perfmon_stop_watch (thread_p);
1777  }
1778  }
1779  else if (xasl_trace == true)
1780  {
1781  thread_trace_on (thread_p);
1782  perfmon_start_watch (thread_p);
1783 
1784  if (IS_XASL_TRACE_TEXT (*flag_p))
1785  {
1787  }
1788  else if (IS_XASL_TRACE_JSON (*flag_p))
1789  {
1791  }
1792  }
1793 
1794  if (IS_TRIGGER_INVOLVED (*flag_p))
1795  {
1796  session_set_trigger_state (thread_p, true);
1797  }
1798 
1799  /* Make an query entry */
1800  /* mark that this transaction is running a query */
1801  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1802  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
1803 
1804 #if defined(ENABLE_SYSTEMTAP)
1805  if (tran_entry_p->trans_stat == QMGR_TRAN_NULL || tran_entry_p->trans_stat == QMGR_TRAN_TERMINATED)
1806  {
1807  CUBRID_TRAN_START (tran_index);
1808  }
1809 #endif /* ENABLE_SYSTEMTAP */
1810 
1811 #if defined (SERVER_MODE)
1812  tran_entry_p->trans_stat = QMGR_TRAN_RUNNING;
1813 
1814  /* allocate a new query entry */
1815  query_p = qmgr_allocate_query_entry (thread_p, tran_entry_p);
1816 
1817  /* set a timeout if necessary */
1818  qmgr_set_query_exec_info_to_tdes (tran_index, query_timeout, NULL);
1819 
1820  if (dbval_count)
1821  {
1822  char *ptr;
1823 
1824  assert (data != NULL);
1825 
1826  dbvals_p = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE) * dbval_count);
1827  if (dbvals_p == NULL)
1828  {
1829  goto exit_on_error;
1830  }
1831 
1832  /* unpack DB_VALUEs from the received data */
1833  ptr = data;
1834  for (i = 0, dbval = dbvals_p; i < dbval_count; i++, dbval++)
1835  {
1836  ptr = or_unpack_db_value (ptr, dbval);
1837  }
1838  }
1839 #else
1840  dbvals_p = (DB_VALUE *) dbval_p;
1841 
1842  /* allocate a new query entry */
1843  query_p = qmgr_allocate_query_entry (thread_p, tran_entry_p);
1844 #endif
1845 
1846  if (query_p == NULL)
1847  {
1849  goto exit_on_error;
1850  }
1851 
1852  /* initialize query entry */
1853  XASL_ID_SET_NULL (&query_p->xasl_id);
1854  query_p->xasl_ent = NULL;
1855  query_p->list_ent = NULL;
1856  query_p->query_status = QUERY_IN_PROGRESS;
1857  query_p->query_flag = *flag_p;
1858 
1859  assert (!(*flag_p & RESULT_HOLDABLE));
1860  query_p->is_holdable = false;
1861 
1862  /* add query entry to the query table */
1863  qmgr_add_query_entry (thread_p, query_p, tran_index);
1864 
1865  /* to return query id */
1866  *query_id_p = query_p->query_id;
1867 
1868  list_id_p = qmgr_process_query (thread_p, NULL, xasl_stream, xasl_stream_size, dbval_count, dbvals_p, *flag_p,
1869  query_p, tran_entry_p);
1870  if (list_id_p == NULL)
1871  {
1872  goto exit_on_error;
1873  }
1874 
1875  /* everything is ok, mark that the query is completed */
1876  qmgr_mark_query_as_completed (query_p);
1877 
1878 end:
1879  if (IS_TRIGGER_INVOLVED (*flag_p))
1880  {
1881  session_set_trigger_state (thread_p, false);
1882  }
1883 
1884 #if defined (SERVER_MODE)
1885  if (dbvals_p)
1886  {
1887  for (i = 0, dbval = dbvals_p; i < dbval_count; i++, dbval++)
1888  {
1889  pr_clear_value (dbval);
1890  }
1891  db_private_free_and_init (thread_p, dbvals_p);
1892  }
1893 #endif
1894 
1895  if (DO_NOT_COLLECT_EXEC_STATS (*flag_p) && saved_is_stats_on == true)
1896  {
1897  perfmon_start_watch (thread_p);
1898  }
1899 
1900 #if defined (SERVER_MODE)
1901  qmgr_reset_query_exec_info (tran_index);
1902 #endif
1903 
1904  return list_id_p;
1905 
1906 exit_on_error:
1907 
1908  /*
1909  * free the query entry when error occurs. note that the query_id should be
1910  * set to 0 so as to upper levels can detect the error.
1911  */
1912  if (query_p)
1913  {
1914  /* mark that the query is completed and then delete this query entry */
1915  qmgr_mark_query_as_completed (query_p);
1916 
1917  if (qmgr_free_query_temp_file (thread_p, query_p, tran_index) != NO_ERROR)
1918  {
1919  er_log_debug (ARG_FILE_LINE, "xqmgr_prepare_and_execute_query: qmgr_free_query_temp_file");
1920  }
1921  qmgr_delete_query_entry (thread_p, query_p->query_id, tran_index);
1922  }
1923 
1924  *query_id_p = 0;
1925 
1926  if (list_id_p)
1927  {
1928  QFILE_FREE_AND_INIT_LIST_ID (list_id_p);
1929  }
1930 
1931  if (xasl_trace == true && saved_is_stats_on == false)
1932  {
1933  perfmon_stop_watch (thread_p);
1934  }
1935 
1936  goto end;
1937 }
1938 
1939 /*
1940  * xqmgr_end_query () -
1941  * return: int (NO_ERROR or ER_FAILED)
1942  * thrd(in) : this thread handle
1943  * query_id(in) : Query Identifier
1944  *
1945  * Note: The query result file is destroyed for the specified query.
1946  * If the query is not repetitive, this calls also removes the
1947  * query entry from the server query table and invalidates the
1948  * query identifier. If the query result file destruction fails,
1949  * ER_FAILED code is returned, but still query entry is removed
1950  * query identifier is invalidated for unrepetitive queries.
1951  */
1952 int
1953 xqmgr_end_query (THREAD_ENTRY * thread_p, QUERY_ID query_id)
1954 {
1955  QMGR_QUERY_ENTRY *query_p = NULL;
1956  QMGR_TRAN_ENTRY *tran_entry_p = NULL;
1957  int tran_index, rc = NO_ERROR;
1958 
1959  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1960 
1961  /* get query entry */
1962  if (qmgr_Query_table.tran_entries_p == NULL)
1963  {
1965  return ER_FAILED;
1966  }
1967 
1968  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
1969 
1970  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
1971  if (query_p == NULL)
1972  {
1973  /* maybe this is a holdable result and we'll find it in the session state object */
1974  xsession_remove_query_entry_info (thread_p, query_id);
1975  return NO_ERROR;
1976  }
1977 
1978  if (query_p->is_holdable)
1979  {
1980  /* We also need to remove the associated query from the session. The call below will not destroy the associated
1981  * list files */
1982  xsession_clear_query_entry_info (thread_p, query_id);
1983  }
1984 
1985  assert (query_p->query_status == QUERY_COMPLETED);
1986 
1987  /* query is closed */
1988  if (query_p->xasl_ent && query_p->list_ent)
1989  {
1990  (void) qfile_end_use_of_list_cache_entry (thread_p, query_p->list_ent, false);
1991  }
1992 
1993  /* destroy the temp file from list id */
1994  if (query_p->list_id)
1995  {
1997 
1998  /* free external volumes, if any */
1999  rc = qmgr_free_query_temp_file (thread_p, query_p, tran_index);
2000  }
2001 
2002  XASL_ID_SET_NULL (&query_p->xasl_id);
2003  qmgr_delete_query_entry (thread_p, query_p->query_id, tran_index);
2004 
2005  return rc;
2006 }
2007 
2008 /*
2009  * xqmgr_drop_all_query_plans () - Drop all the stored query plans
2010  * return: NO_ERROR or ER_FAILED
2011  *
2012  * Note: Clear all XASL/filter predicate cache entries out upon request of the client.
2013  */
2014 int
2016 {
2017  xcache_drop_all (thread_p);
2018  fpcache_drop_all (thread_p);
2019  return NO_ERROR;
2020 }
2021 
2022 /*
2023  * xqmgr_dump_query_plans () - Dump the content of the XASL cache
2024  * return:
2025  * outfp(in) :
2026  */
2027 void
2028 xqmgr_dump_query_plans (THREAD_ENTRY * thread_p, FILE * out_fp)
2029 {
2030  xcache_dump (thread_p, out_fp);
2031  fpcache_dump (thread_p, out_fp);
2032 }
2033 
2034 /*
2035  * xqmgr_dump_query_cache () -
2036  * return:
2037  * outfp(in) :
2038  */
2039 void
2040 xqmgr_dump_query_cache (THREAD_ENTRY * thread_p, FILE * out_fp)
2041 {
2042  (void) qfile_dump_list_cache_internal (thread_p, out_fp);
2043 }
2044 
2045 /*
2046  * TRANSACTION COORDINATION ROUTINES
2047  */
2048 
2049 static void
2051 {
2052  OID_BLOCK_LIST *oid_block_p;
2053  OID *class_oid_p;
2054  int i;
2055 
2056  for (oid_block_p = tran_entry_p->modified_classes_p; oid_block_p; oid_block_p = oid_block_p->next)
2057  {
2058  for (i = 0, class_oid_p = oid_block_p->oid_array; i < oid_block_p->last_oid_idx; i++, class_oid_p++)
2059  {
2060  if (xcache_invalidate_qcaches (thread_p, class_oid_p) != NO_ERROR)
2061  {
2063  "qm_clear_trans_wakeup: qexec_clear_list_cache_by_class failed for class { %d %d %d }\n",
2064  class_oid_p->pageid, class_oid_p->slotid, class_oid_p->volid);
2065  }
2066  }
2067  }
2068 }
2069 
2070 static bool
2071 qmgr_is_related_class_modified (THREAD_ENTRY * thread_p, XASL_CACHE_ENTRY * xasl_cache, int tran_index)
2072 {
2073  QMGR_TRAN_ENTRY *tran_entry_p;
2074  OID_BLOCK_LIST *oid_block_p;
2075 
2076  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2077 
2078  for (oid_block_p = tran_entry_p->modified_classes_p; oid_block_p; oid_block_p = oid_block_p->next)
2079  {
2080  QMGR_QUERY_ENTRY *query_p;
2081  OID *class_oid_p;
2082  int oid_idx, i;
2083 
2084  for (i = 0; i < oid_block_p->last_oid_idx; i++)
2085  {
2086  class_oid_p = &oid_block_p->oid_array[i];
2087  for (oid_idx = 0; oid_idx < xasl_cache->n_related_objects; oid_idx++)
2088  {
2089  if (OID_EQ (&xasl_cache->related_objects[oid_idx].oid, class_oid_p))
2090  {
2091  /* Found relation. */
2092  return true;
2093  }
2094  }
2095  }
2096  }
2097 
2098  return false;
2099 }
2100 
2101 /*
2102  * qmgr_clear_trans_wakeup () -
2103  * return:
2104  * tran_index(in) : Log Transaction index
2105  * tran_died(in) : Flag to indicate if the transaction has died
2106  * is_abort(in) :
2107  *
2108  * Note: This routine is called by the transaction manager and perfoms
2109  * a clean_up processing for the given transaction index. For
2110  * each non-repetitive query (that is not currently executing)
2111  * issued by the transaction, it
2112  * destroys the query result file, the XASL tree plan and
2113  * invalidates the query entry(identifier). For each repetitive
2114  * query issued by the transaction, it destroys the query result
2115  * file, however it destroys the XASL tree plan and the query
2116  * entry(identifier), only if the transaction has died. The XASL
2117  * tree plan for repetitive queries is kept for aborted
2118  * transactions because it can still be used by the transaction
2119  * to execute queries.
2120  */
2121 void
2122 qmgr_clear_trans_wakeup (THREAD_ENTRY * thread_p, int tran_index, bool is_tran_died, bool is_abort)
2123 {
2124  QMGR_QUERY_ENTRY *query_p, *q;
2125  QMGR_TRAN_ENTRY *tran_entry_p;
2126 
2127  /* for bulletproofing check if tran_index is a valid index, note that normally this should never happen... */
2128  if (tran_index >= qmgr_Query_table.num_trans
2129 #if defined (SERVER_MODE)
2130  || tran_index == LOG_SYSTEM_TRAN_INDEX
2131 #endif
2132  )
2133  {
2134 #ifdef QP_DEBUG
2135  er_log_debug (ARG_FILE_LINE, "qm_clear_trans_wakeup:Invalid transaction index %d called...\n", tran_index);
2136 #endif
2137  return;
2138  }
2139 
2140  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2141  /* if the transaction is aborting, clear relative cache entries */
2142  if (tran_entry_p->modified_classes_p)
2143  {
2145  {
2146  qmgr_clear_relative_cache_entries (thread_p, tran_entry_p);
2147  }
2148  qmgr_free_oid_block (thread_p, tran_entry_p->modified_classes_p);
2149  tran_entry_p->modified_classes_p = NULL;
2150  }
2151  if (tran_entry_p->query_entry_list_p == NULL)
2152  {
2153  return;
2154  }
2155 
2156 #if defined (SERVER_MODE) && !defined (NDEBUG)
2157  /* there should be no active query */
2158  for (query_p = tran_entry_p->query_entry_list_p; query_p != NULL; query_p = query_p->next)
2159  {
2160  assert (query_p->query_status == QUERY_COMPLETED);
2161  }
2162 #endif
2163 
2164  query_p = tran_entry_p->query_entry_list_p;
2165  while (query_p)
2166  {
2167  if (query_p->is_holdable)
2168  {
2169  if (is_abort || is_tran_died)
2170  {
2171  /* Make sure query entry info is not leaked in session. */
2172  xsession_clear_query_entry_info (thread_p, query_p->query_id);
2173  }
2174  else
2175  {
2176  /* this is a commit and we have to add the result to the holdable queries list. */
2177  if (query_p->query_status != QUERY_COMPLETED)
2178  {
2179  er_log_debug (ARG_FILE_LINE, "query %d not completed !\n", query_p->query_id);
2180  }
2181  else
2182  {
2183  er_log_debug (ARG_FILE_LINE, "query %d is completed!\n", query_p->query_id);
2184  }
2185  xsession_store_query_entry_info (thread_p, query_p);
2186  /* reset result info */
2187  query_p->list_id = NULL;
2188  query_p->temp_vfid = NULL;
2189  }
2190  }
2191 
2192  /* destroy the query result if not destroyed yet */
2193  if (query_p->list_id)
2194  {
2195  qfile_close_list (thread_p, query_p->list_id);
2197  }
2198 
2199  if (query_p->temp_vfid != NULL)
2200  {
2201  (void) qmgr_free_query_temp_file_helper (thread_p, query_p);
2202  }
2203 
2204  XASL_ID_SET_NULL (&query_p->xasl_id);
2205 
2206  /* end use of the list file of the cached result */
2207  if (query_p->xasl_ent != NULL && query_p->list_ent != NULL)
2208  {
2209  (void) qfile_end_use_of_list_cache_entry (thread_p, query_p->list_ent, false);
2210  }
2211 
2212  /* remove query entry */
2213  tran_entry_p->query_entry_list_p = query_p->next;
2214  qmgr_free_query_entry (thread_p, tran_entry_p, query_p);
2215 
2216  query_p = tran_entry_p->query_entry_list_p;
2217  }
2218 
2219  assert (tran_entry_p->query_entry_list_p == NULL);
2220  tran_entry_p->trans_stat = QMGR_TRAN_TERMINATED;
2221 }
2222 
2223 #if defined(ENABLE_UNUSED_FUNCTION)
2224 /*
2225  * qmgr_get_tran_status () -
2226  * return:
2227  * tran_index(in) :
2228  */
2230 qmgr_get_tran_status (THREAD_ENTRY * thread_p, int tran_index)
2231 {
2232  if (tran_index >= 0)
2233  {
2234  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2235  }
2236 
2237  return qmgr_Query_table.tran_entries_p[tran_index].trans_stat;
2238 }
2239 
2240 /*
2241  * qmgr_set_tran_status () -
2242  * return:
2243  * tran_index(in) :
2244  * trans_status(in) :
2245  */
2246 void
2247 qmgr_set_tran_status (THREAD_ENTRY * thread_p, int tran_index, QMGR_TRAN_STATUS trans_status)
2248 {
2249  if (tran_index >= 0)
2250  {
2251  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2252  }
2253 
2254  qmgr_Query_table.tran_entries_p[tran_index].trans_stat = trans_status;
2255 }
2256 #endif /* ENABLE_UNUSED_FUNCTION */
2257 
2258 /*
2259  * qmgr_free_oid_block () -
2260  * return:
2261  * oid_block(in) :
2262  */
2263 static void
2265 {
2266  OID_BLOCK_LIST *p;
2267 
2268  for (p = oid_block_p; p; p = p->next)
2269  {
2270  p->last_oid_idx = 0;
2271  }
2272 }
2273 
2274 /*
2275  * qmgr_add_modified_class () -
2276  * return:
2277  * class_oid(in) :
2278  */
2279 void
2280 qmgr_add_modified_class (THREAD_ENTRY * thread_p, const OID * class_oid_p)
2281 {
2282  int tran_index;
2283  QMGR_TRAN_ENTRY *tran_entry_p;
2284  OID_BLOCK_LIST *oid_block_p, *tmp_oid_block_p;
2285  OID *tmp_oid_p;
2286  int i;
2287  bool found;
2288 
2289  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2290  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2291  if (tran_entry_p->modified_classes_p == NULL)
2292  {
2293  tran_entry_p->modified_classes_p = (OID_BLOCK_LIST *) malloc (sizeof (OID_BLOCK_LIST));
2294  if (tran_entry_p->modified_classes_p == NULL)
2295  {
2297  return;
2298  }
2299  tran_entry_p->modified_classes_p->last_oid_idx = 0;
2300  tran_entry_p->modified_classes_p->next = NULL;
2301  }
2302 
2303  found = false;
2304  tmp_oid_block_p = tran_entry_p->modified_classes_p;
2305  do
2306  {
2307  oid_block_p = tmp_oid_block_p;
2308  for (i = 0, tmp_oid_p = oid_block_p->oid_array; i < oid_block_p->last_oid_idx; i++, tmp_oid_p++)
2309  {
2310  if (oid_compare (class_oid_p, tmp_oid_p) == 0)
2311  {
2312  found = true;
2313  break;
2314  }
2315  }
2316  tmp_oid_block_p = oid_block_p->next;
2317  }
2318  while (tmp_oid_block_p);
2319 
2320  if (!found)
2321  {
2322  if (oid_block_p->last_oid_idx < OID_BLOCK_ARRAY_SIZE)
2323  {
2324  oid_block_p->oid_array[oid_block_p->last_oid_idx++] = *class_oid_p;
2325  }
2326  else if ((oid_block_p->next = (OID_BLOCK_LIST *) malloc (sizeof (OID_BLOCK_LIST))))
2327  {
2328  oid_block_p = oid_block_p->next;
2329  oid_block_p->last_oid_idx = 0;
2330  oid_block_p->next = NULL;
2331  oid_block_p->oid_array[oid_block_p->last_oid_idx++] = *class_oid_p;
2332  }
2333  else
2334  {
2335  assert (false);
2336  }
2337  }
2338 }
2339 
2340 /*
2341  * PAGE ALLOCATION/DEALLOCATION ROUTINES
2342  */
2343 
2344 /*
2345  * qmgr_get_old_page () -
2346  * return:
2347  * vpidp(in) :
2348  * tfile_vfidp(in) :
2349  */
2350 PAGE_PTR
2351 qmgr_get_old_page (THREAD_ENTRY * thread_p, VPID * vpid_p, QMGR_TEMP_FILE * tfile_vfid_p)
2352 {
2353  int tran_index;
2354  PAGE_PTR page_p;
2355 #if defined(SERVER_MODE)
2356  bool dummy;
2357 #endif /* SERVER_MODE */
2358 
2359  if (vpid_p->volid == NULL_VOLID && tfile_vfid_p == NULL)
2360  {
2362  return NULL;
2363  }
2364 
2365  if (vpid_p->volid == NULL_VOLID)
2366  {
2367  /* return memory buffer */
2368  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2369 
2370  if (vpid_p->pageid >= 0 && vpid_p->pageid <= tfile_vfid_p->membuf_last)
2371  {
2372  page_p = tfile_vfid_p->membuf[vpid_p->pageid];
2373 
2374  /* interrupt check */
2375 #if defined (SERVER_MODE)
2376  if (logtb_get_check_interrupt (thread_p) == true
2377  && logtb_is_interrupted_tran (thread_p, true, &dummy, tran_index) == true)
2378  {
2380  page_p = NULL;
2381  }
2382 #endif
2383  }
2384  else
2385  {
2387  page_p = NULL;
2388  }
2389  }
2390  else
2391  {
2392  /* return temp file page */
2393  page_p = pgbuf_fix (thread_p, vpid_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
2394 
2395  if (page_p != NULL)
2396  {
2397  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_QRESULT);
2398  }
2399  }
2400 
2401  return page_p;
2402 }
2403 
2404 /*
2405  * qmgr_free_old_page () -
2406  * return:
2407  * page_ptr(in) :
2408  * tfile_vfidp(in) :
2409  */
2410 void
2411 qmgr_free_old_page (THREAD_ENTRY * thread_p, PAGE_PTR page_p, QMGR_TEMP_FILE * tfile_vfid_p)
2412 {
2413  QMGR_PAGE_TYPE page_type;
2414 
2415  if (page_p == NULL)
2416  {
2417  assert (0);
2418  return;
2419  }
2420  if (tfile_vfid_p == NULL)
2421  {
2422  pgbuf_unfix (thread_p, page_p);
2423  return;
2424  }
2425 
2426  page_type = qmgr_get_page_type (page_p, tfile_vfid_p);
2427  if (page_type == QMGR_UNKNOWN_PAGE)
2428  {
2429  assert (false);
2430  return;
2431  }
2432 
2433  if (page_type == QMGR_TEMP_FILE_PAGE)
2434  {
2435  /* The list files came from list file cache have no tfile_vfid_p. */
2436  pgbuf_unfix (thread_p, page_p);
2437  }
2438 #if defined (SERVER_MODE)
2439  else
2440  {
2441  assert (page_type == QMGR_MEMBUF_PAGE);
2442  }
2443 #endif
2444 }
2445 
2446 /*
2447  * qmgr_set_dirty_page () -
2448  * return:
2449  * page_ptr(in) :
2450  * free_page(in) :
2451  * addrp(in) :
2452  * tfile_vfidp(in) :
2453  */
2454 void
2455 qmgr_set_dirty_page (THREAD_ENTRY * thread_p, PAGE_PTR page_p, int free_page, LOG_DATA_ADDR * addr_p,
2456  QMGR_TEMP_FILE * tfile_vfid_p)
2457 {
2458  QMGR_PAGE_TYPE page_type;
2459 
2460  page_type = qmgr_get_page_type (page_p, tfile_vfid_p);
2461  if (page_type == QMGR_UNKNOWN_PAGE)
2462  {
2463  assert (false);
2464  return;
2465  }
2466 
2467  if (page_type == QMGR_TEMP_FILE_PAGE)
2468  {
2469  log_skip_logging (thread_p, addr_p);
2470  pgbuf_set_dirty (thread_p, page_p, free_page);
2471  }
2472 #if defined (SERVER_MODE)
2473  else if (free_page == (int) FREE)
2474  {
2475  assert (page_type == QMGR_MEMBUF_PAGE);
2476  }
2477 #endif
2478 }
2479 
2480 /*
2481  * qmgr_get_new_page () -
2482  * return: PAGE_PTR
2483  * vpidp(in) : Set to the allocated real page identifier
2484  * tfile_vfidp(in) : Query Associated with the XASL tree
2485  *
2486  * Note: A new query file page is allocated and returned. The page fetched and returned, is not locked.
2487  * This routine is called succesively to allocate pages for the query result files (list files) or XASL tree files.
2488  * If an error occurs, NULL pointer is returned.
2489  */
2490 PAGE_PTR
2491 qmgr_get_new_page (THREAD_ENTRY * thread_p, VPID * vpid_p, QMGR_TEMP_FILE * tfile_vfid_p)
2492 {
2493  PAGE_PTR page_p;
2494  QMGR_QUERY_ENTRY *query_p = NULL;
2495 
2496  if (tfile_vfid_p == NULL)
2497  {
2499  return NULL;
2500  }
2501 
2502  /* first page, return memory buffer instead real temp file page */
2503  if (tfile_vfid_p->membuf != NULL && tfile_vfid_p->membuf_last < tfile_vfid_p->membuf_npages - 1)
2504  {
2505  vpid_p->volid = NULL_VOLID;
2506  vpid_p->pageid = ++(tfile_vfid_p->membuf_last);
2507  return tfile_vfid_p->membuf[tfile_vfid_p->membuf_last];
2508  }
2509 
2510  /* memory buffer is exhausted; create temp file */
2511  if (VFID_ISNULL (&tfile_vfid_p->temp_vfid))
2512  {
2513  TDE_ALGORITHM tde_algo = TDE_ALGORITHM_NONE;
2514  if (file_create_temp (thread_p, 1, &tfile_vfid_p->temp_vfid) != NO_ERROR)
2515  {
2516  ASSERT_ERROR ();
2517  return NULL;
2518  }
2519  tfile_vfid_p->temp_file_type = FILE_TEMP;
2520 
2521  if (tfile_vfid_p->tde_encrypted)
2522  {
2524  }
2525 
2526  if (file_apply_tde_algorithm (thread_p, &tfile_vfid_p->temp_vfid, tde_algo) != NO_ERROR)
2527  {
2528  ASSERT_ERROR ();
2529  file_temp_retire (thread_p, &tfile_vfid_p->temp_vfid);
2530  VFID_SET_NULL (&tfile_vfid_p->temp_vfid);
2531  return NULL;
2532  }
2533  }
2534 
2535  /* try to get pages from an external temp file */
2536  page_p = qmgr_get_external_file_page (thread_p, vpid_p, tfile_vfid_p);
2537  if (page_p == NULL)
2538  {
2539  /* more temp file page is unavailable; cause error to stop the query */
2540  vpid_p->pageid = NULL_PAGEID;
2542  {
2544  }
2545  }
2546 
2547  return page_p;
2548 }
2549 
2550 /*
2551  * qmgr_init_external_file_page () - initialize new query result page
2552  *
2553  * return : NO_ERROR
2554  * thread_p (in) : thread entry
2555  * page (in) : new page
2556  * args (in) : not used
2557  */
2558 static int
2560 {
2562 
2563  pgbuf_set_page_ptype (thread_p, page, PAGE_QRESULT);
2564  qmgr_put_page_header (page, &page_header);
2565  pgbuf_set_dirty (thread_p, page, DONT_FREE);
2566 
2567  return NO_ERROR;
2568 }
2569 
2570 /*
2571  * qmgr_get_external_file_page () -
2572  * return: PAGE_PTR
2573  * vpid(in) : Set to the allocated virtual page identifier
2574  * tmp_vfid(in) : tempfile_vfid struct pointer
2575  *
2576  * Note: This function tries to allocate a new page from an external query file, fetchs and returns the page pointer.
2577  * Since pages are not shared by different transactions, it does not lock the page on fetching.
2578  * If it can not allocate a new page, necessary error code is set and NULL pointer is returned.
2579  */
2580 static PAGE_PTR
2581 qmgr_get_external_file_page (THREAD_ENTRY * thread_p, VPID * vpid_p, QMGR_TEMP_FILE * tmp_vfid_p)
2582 {
2583  PAGE_PTR page_p = NULL;
2584 
2585  VPID_SET_NULL (vpid_p);
2586  if (file_alloc (thread_p, &tmp_vfid_p->temp_vfid, qmgr_init_external_file_page, NULL, vpid_p, &page_p) != NO_ERROR)
2587  {
2588  ASSERT_ERROR ();
2589  return NULL;
2590  }
2591  assert (page_p != NULL);
2592  assert (pgbuf_get_page_ptype (thread_p, page_p) == PAGE_QRESULT);
2593  return page_p;
2594 }
2595 
2596 static QMGR_TEMP_FILE *
2598 {
2599  size_t size;
2600  QMGR_TEMP_FILE *tempfile_p;
2601 
2602  size = DB_ALIGN (sizeof (QMGR_TEMP_FILE), MAX_ALIGNMENT);
2603  size += DB_ALIGN (sizeof (PAGE_PTR) * num_buffer_pages, MAX_ALIGNMENT);
2604  size += DB_PAGESIZE * num_buffer_pages;
2605 
2606  tempfile_p = (QMGR_TEMP_FILE *) malloc (size);
2607  if (tempfile_p == NULL)
2608  {
2610  return NULL;
2611  }
2612  memset (tempfile_p, 0x00, size);
2613 
2614  return tempfile_p;
2615 }
2616 
2617 /*
2618  * qmgr_create_new_temp_file () -
2619  * return:
2620  * query_id(in) :
2621  */
2623 qmgr_create_new_temp_file (THREAD_ENTRY * thread_p, QUERY_ID query_id, QMGR_TEMP_FILE_MEMBUF_TYPE membuf_type)
2624 {
2625  QMGR_QUERY_ENTRY *query_p;
2626  QMGR_TRAN_ENTRY *tran_entry_p;
2627  int tran_index, i, num_buffer_pages;
2628  QMGR_TEMP_FILE *tfile_vfid_p, *temp;
2629  PAGE_PTR page_p;
2630  QFILE_PAGE_HEADER pgheader = { 0, NULL_PAGEID, NULL_PAGEID, 0, NULL_PAGEID, NULL_VOLID, NULL_VOLID, NULL_VOLID };
2631  static int temp_mem_buffer_pages = prm_get_integer_value (PRM_ID_TEMP_MEM_BUFFER_PAGES);
2632  static int index_scan_key_buffer_pages = prm_get_integer_value (PRM_ID_INDEX_SCAN_KEY_BUFFER_PAGES);
2633 
2634  assert (QMGR_IS_VALID_MEMBUF_TYPE (membuf_type));
2635 
2636  if (!QMGR_IS_VALID_MEMBUF_TYPE (membuf_type))
2637  {
2638  return NULL;
2639  }
2640 
2641  num_buffer_pages = ((membuf_type == TEMP_FILE_MEMBUF_NORMAL) ? temp_mem_buffer_pages : index_scan_key_buffer_pages);
2642 
2643  tfile_vfid_p = qmgr_get_temp_file_from_list (&qmgr_Query_table.temp_file_list[membuf_type]);
2644  if (tfile_vfid_p == NULL)
2645  {
2646  tfile_vfid_p = qmgr_allocate_tempfile_with_buffer (num_buffer_pages);
2647  }
2648 
2649  if (tfile_vfid_p == NULL)
2650  {
2651  return NULL;
2652  }
2653 
2654  tfile_vfid_p->membuf = (PAGE_PTR *) ((PAGE_PTR) tfile_vfid_p + DB_ALIGN (sizeof (QMGR_TEMP_FILE), MAX_ALIGNMENT));
2655 
2656  /* initialize tfile_vfid */
2657  VFID_SET_NULL (&tfile_vfid_p->temp_vfid);
2658  tfile_vfid_p->temp_file_type = FILE_TEMP;
2659  tfile_vfid_p->membuf_npages = num_buffer_pages;
2660  tfile_vfid_p->membuf_type = membuf_type;
2661  tfile_vfid_p->preserved = false;
2662  tfile_vfid_p->tde_encrypted = false;
2663  tfile_vfid_p->membuf_last = -1;
2664 
2665  page_p = (PAGE_PTR) ((PAGE_PTR) tfile_vfid_p->membuf
2666  + DB_ALIGN (sizeof (PAGE_PTR) * tfile_vfid_p->membuf_npages, MAX_ALIGNMENT));
2667 
2668  for (i = 0; i < tfile_vfid_p->membuf_npages; i++)
2669  {
2670  tfile_vfid_p->membuf[i] = page_p;
2671  qmgr_put_page_header (page_p, &pgheader);
2672  page_p += DB_PAGESIZE;
2673  }
2674 
2675  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2676  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2677 
2678  /* find query entry */
2679  if (qmgr_Query_table.tran_entries_p != NULL)
2680  {
2681  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
2682  }
2683  else
2684  {
2685  query_p = NULL;
2686  }
2687 
2688  if (query_p == NULL)
2689  {
2690  free_and_init (tfile_vfid_p);
2692  return NULL;
2693  }
2694 
2695  if (query_p->includes_tde_class)
2696  {
2697  tfile_vfid_p->tde_encrypted = true;
2698  }
2699 
2700  /* chain allocated tfile_vfid to the query_entry */
2701  temp = query_p->temp_vfid;
2702  query_p->temp_vfid = tfile_vfid_p;
2703  if (temp != NULL)
2704  {
2705  /* link to the list */
2706  tfile_vfid_p->next = temp;
2707  tfile_vfid_p->prev = temp->prev;
2708  tfile_vfid_p->prev->next = tfile_vfid_p;
2709  temp->prev = tfile_vfid_p;
2710  }
2711  else
2712  {
2713  /* Add transaction to wfg as a holder of temporary file space, but only do so for the first temp file that we
2714  * create. From the wfg's point of view, there's no difference between holding one file or holding one hundred. */
2715  tfile_vfid_p->next = tfile_vfid_p;
2716  tfile_vfid_p->prev = tfile_vfid_p;
2717  }
2718 
2719  /* increment the counter of query entry */
2720  query_p->num_tmp++;
2721 
2722  return tfile_vfid_p;
2723 }
2724 
2725 /*
2726  * qmgr_create_result_file () - create a temporary file for query result
2727  * return:
2728  * query_id(in) :
2729  */
2731 qmgr_create_result_file (THREAD_ENTRY * thread_p, QUERY_ID query_id)
2732 {
2733  QMGR_QUERY_ENTRY *query_p;
2734  int tran_index;
2735  QMGR_TEMP_FILE *tfile_vfid_p, *temp;
2736  QMGR_TRAN_ENTRY *tran_entry_p;
2737  TDE_ALGORITHM tde_algo = TDE_ALGORITHM_NONE;
2738 
2739  /* Allocate a tfile_vfid and create a temporary file for query result */
2740 
2741  tfile_vfid_p = (QMGR_TEMP_FILE *) malloc (sizeof (QMGR_TEMP_FILE));
2742  if (tfile_vfid_p == NULL)
2743  {
2745  return NULL;
2746  }
2747 
2748  VFID_SET_NULL (&tfile_vfid_p->temp_vfid);
2749 
2750  if (file_create_query_area (thread_p, &tfile_vfid_p->temp_vfid) != NO_ERROR)
2751  {
2752  free_and_init (tfile_vfid_p);
2753  return NULL;
2754  }
2755 
2756 
2757  tfile_vfid_p->temp_file_type = FILE_QUERY_AREA;
2758 
2760  tfile_vfid_p->membuf = NULL;
2761  tfile_vfid_p->membuf_npages = 0;
2762  tfile_vfid_p->membuf_type = TEMP_FILE_MEMBUF_NONE;
2763  tfile_vfid_p->preserved = false;
2764  tfile_vfid_p->tde_encrypted = false;
2765 
2766  /* Find the query entry and chain the created temp file to the entry */
2767 
2768  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2769  tran_entry_p = &(qmgr_Query_table.tran_entries_p[tran_index]);
2770 
2771  /* find the query entry */
2772  if (qmgr_Query_table.tran_entries_p != NULL)
2773  {
2774  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
2775  }
2776  else
2777  {
2778  query_p = NULL;
2779  }
2780 
2781  if (query_p == NULL)
2782  {
2783  /* query entry is not found */
2785  file_temp_retire (thread_p, &tfile_vfid_p->temp_vfid);
2786  free_and_init (tfile_vfid_p);
2787  return NULL;
2788  }
2789 
2790  if (query_p->includes_tde_class)
2791  {
2792  tfile_vfid_p->tde_encrypted = true;
2794  }
2795 
2796  if (file_apply_tde_algorithm (thread_p, &tfile_vfid_p->temp_vfid, tde_algo) != NO_ERROR)
2797  {
2798  file_temp_retire (thread_p, &tfile_vfid_p->temp_vfid);
2799  free_and_init (tfile_vfid_p);
2800  return NULL;
2801  }
2802 
2804  {
2805  file_temp_preserve (thread_p, &tfile_vfid_p->temp_vfid);
2806  tfile_vfid_p->preserved = true;
2807  }
2808 
2809  /* chain the tfile_vfid to the query_entry->temp_vfid */
2810  temp = query_p->temp_vfid;
2811  query_p->temp_vfid = tfile_vfid_p;
2812  if (temp != NULL)
2813  {
2814  /* insert into the head of the double linked list */
2815  tfile_vfid_p->next = temp;
2816  tfile_vfid_p->prev = temp->prev;
2817  tfile_vfid_p->prev->next = tfile_vfid_p;
2818  temp->prev = tfile_vfid_p;
2819  }
2820  else
2821  {
2822  /* first one */
2823  tfile_vfid_p->next = tfile_vfid_p;
2824  tfile_vfid_p->prev = tfile_vfid_p;
2825  }
2826 
2827  /* increment the counter of query entry */
2828  query_p->num_tmp++;
2829 
2830  return tfile_vfid_p;
2831 }
2832 
2833 /*
2834  * qmgr_free_temp_file_list () - free temporary files in tfile_vfid_p
2835  * return : error code or NO_ERROR
2836  * thread_p (in) :
2837  * tfile_vfid_p (in) : temporary files list
2838  * query_id (in) : query id
2839  * is_error (in) : true if query was unsuccessful
2840  * was_preserved (in) : true if query was preserved
2841  */
2842 int
2843 qmgr_free_temp_file_list (THREAD_ENTRY * thread_p, QMGR_TEMP_FILE * tfile_vfid_p, QUERY_ID query_id, bool is_error)
2844 {
2845  QMGR_TEMP_FILE *temp = NULL;
2846  int rc = NO_ERROR, fd_ret = NO_ERROR;
2847 
2848  /* make sure temp file list is not cyclic */
2849  assert (tfile_vfid_p->prev == NULL || tfile_vfid_p->prev->next == NULL);
2850 
2851  while (tfile_vfid_p)
2852  {
2853  fd_ret = NO_ERROR;
2854  if ((tfile_vfid_p->temp_file_type != FILE_QUERY_AREA || is_error) && !VFID_ISNULL (&tfile_vfid_p->temp_vfid))
2855  {
2856  if (tfile_vfid_p->preserved)
2857  {
2858  fd_ret = file_temp_retire_preserved (thread_p, &tfile_vfid_p->temp_vfid);
2859  if (fd_ret != NO_ERROR)
2860  {
2861  /* set error but continue with the destroy process */
2862  ASSERT_ERROR ();
2863  rc = ER_FAILED;
2864  }
2865  }
2866  else
2867  {
2868  fd_ret = file_temp_retire (thread_p, &tfile_vfid_p->temp_vfid);
2869  if (fd_ret != NO_ERROR)
2870  {
2871  /* set error but continue with the destroy process */
2872  ASSERT_ERROR ();
2873  rc = ER_FAILED;
2874  }
2875  }
2876  }
2877 
2878  temp = tfile_vfid_p;
2879  tfile_vfid_p = tfile_vfid_p->next;
2880 
2881  if (temp->temp_file_type != FILE_QUERY_AREA)
2882  {
2884  }
2885  else
2886  {
2887  free_and_init (temp);
2888  }
2889  }
2890 
2891  return rc;
2892 }
2893 
2894 /*
2895  * qmgr_free_query_temp_file_helper () -
2896  * return: int (NO_ERROR or ER_FAILED)
2897  * query_entryp(in/out) : Query entry ptr to determine what temp file (if any) to destroy
2898  *
2899  * Note: Destroy the external temporary file used, if any.
2900  */
2901 static int
2903 {
2904  QMGR_TEMP_FILE *tfile_vfid_p;
2905  int rc = NO_ERROR;
2906 
2907  assert (query_p != NULL);
2908 
2909  if (query_p->temp_vfid != NULL)
2910  {
2911  bool is_error = (query_p->errid < 0);
2912 
2913  tfile_vfid_p = query_p->temp_vfid;
2914  tfile_vfid_p->prev->next = NULL;
2915 
2916  rc = qmgr_free_temp_file_list (thread_p, tfile_vfid_p, query_p->query_id, is_error);
2917 
2918  query_p->temp_vfid = NULL;
2919  }
2920 
2921  return rc;
2922 }
2923 
2924 /*
2925  * qmgr_free_query_temp_file () -
2926  * return: int (NO_ERROR or ER_FAILED)
2927  * query_entryp(in/out) : Query entry ptr to determine what temp file (if any) to destroy
2928  * tran_idx(in) :
2929  *
2930  * Note: Destroy the external temporary file used, if any.
2931  */
2932 static int
2933 qmgr_free_query_temp_file (THREAD_ENTRY * thread_p, QMGR_QUERY_ENTRY * query_p, int tran_index)
2934 {
2935  int rc;
2936  QMGR_TRAN_ENTRY *tran_entry_p;
2937 
2938  if (query_p == NULL || qmgr_Query_table.tran_entries_p == NULL)
2939  {
2940  return NO_ERROR;
2941  }
2942 
2943  if (tran_index == NULL_TRAN_INDEX)
2944  {
2945  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2946  }
2947 
2948  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2949 
2950  rc = NO_ERROR;
2951  if (query_p->temp_vfid != NULL)
2952  {
2953  rc = qmgr_free_query_temp_file_helper (thread_p, query_p);
2954  }
2955 
2956  return rc;
2957 }
2958 
2959 /*
2960  * qmgr_free_list_temp_file () -
2961  * return: int (NO_ERROR or ER_FAILED)
2962  * query_id(in) : Query ID to determine what temp file (if any) to destroy
2963  * tfile_vfidp(in): Address of QMGR_TEMP_FILE
2964  *
2965  * Note: Destroy the external temporary file used, if any. The caller
2966  * is responsible for setting pointers to this tmp_vfid to NULL afterwards.
2967  */
2968 int
2969 qmgr_free_list_temp_file (THREAD_ENTRY * thread_p, QUERY_ID query_id, QMGR_TEMP_FILE * tfile_vfid_p)
2970 {
2971  QMGR_QUERY_ENTRY *query_p;
2972  QMGR_TRAN_ENTRY *tran_entry_p;
2973  int tran_index, rc;
2974 
2975  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2976  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
2977 
2978  if (qmgr_Query_table.tran_entries_p != NULL)
2979  {
2980  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
2981  }
2982  else
2983  {
2984  query_p = NULL;
2985  }
2986 
2987  if (query_p == NULL)
2988  {
2989  return NO_ERROR;
2990  }
2991 
2992  rc = NO_ERROR;
2993  if (query_p->temp_vfid)
2994  {
2995  if (!VFID_ISNULL (&tfile_vfid_p->temp_vfid))
2996  {
2997  if (tfile_vfid_p->preserved)
2998  {
2999  if (file_temp_retire_preserved (thread_p, &tfile_vfid_p->temp_vfid) != NO_ERROR)
3000  {
3001  /* stop; return error */
3002  rc = ER_FAILED;
3003  }
3004  }
3005  else if (file_temp_retire (thread_p, &tfile_vfid_p->temp_vfid) != NO_ERROR)
3006  {
3007  /* stop; return error */
3008  rc = ER_FAILED;
3009  }
3010  VFID_SET_NULL (&tfile_vfid_p->temp_vfid);
3011  }
3012 
3013  if (query_p->temp_vfid->next == query_p->temp_vfid)
3014  {
3015  query_p->temp_vfid = NULL;
3016  }
3017  else
3018  {
3019  tfile_vfid_p->next->prev = tfile_vfid_p->prev;
3020  tfile_vfid_p->prev->next = tfile_vfid_p->next;
3021  if (query_p->temp_vfid == tfile_vfid_p)
3022  {
3023  query_p->temp_vfid = tfile_vfid_p->next;
3024  }
3025  }
3026 
3027  if (tfile_vfid_p->temp_file_type != FILE_QUERY_AREA)
3028  {
3029  qmgr_put_temp_file_into_list (tfile_vfid_p);
3030  }
3031  else if (tfile_vfid_p)
3032  {
3033  /* free too many temp_file */
3034  free_and_init (tfile_vfid_p);
3035  }
3036  }
3037 
3038  return NO_ERROR;
3039 }
3040 
3041 #if defined (SERVER_MODE)
3042 /*
3043  * qmgr_is_query_interrupted () -
3044  * return:
3045  * query_id(in) :
3046  */
3047 bool
3048 qmgr_is_query_interrupted (THREAD_ENTRY * thread_p, QUERY_ID query_id)
3049 {
3050  QMGR_QUERY_ENTRY *query_p = NULL;
3051  QMGR_TRAN_ENTRY *tran_entry_p;
3052  int tran_index;
3053  bool dummy;
3054 
3055  /*
3056  * get query entry - This is done in-line to avoid qmgr_get_query_entry
3057  * from returning NULL when the query is being interrupted
3058  */
3059  if (qmgr_Query_table.tran_entries_p == NULL)
3060  {
3062  return true;
3063  }
3064 
3065  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
3066  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
3067 
3068  query_p = qmgr_find_query_entry (tran_entry_p->query_entry_list_p, query_id);
3069  if (query_p == NULL)
3070  {
3072  return true;
3073  }
3074 
3075  return (logtb_get_check_interrupt (thread_p) && logtb_is_interrupted_tran (thread_p, true, &dummy, tran_index));
3076 }
3077 #endif /* SERVER_MODE */
3078 
3079 #if defined (ENABLE_UNUSED_FUNCTION)
3080 /*
3081  * qmgr_get_query_error_with_entry () -
3082  * return:
3083  * query_entryp(in) :
3084  */
3085 int
3086 qmgr_get_query_error_with_entry (QMGR_QUERY_ENTRY * query_p)
3087 {
3088  int errid;
3089  char *er_msg;
3090  char *error_area, *p;
3091  int rv;
3092 
3093  errid = query_p->errid;
3094  er_msg = query_p->er_msg;
3095 
3096  if (errid < 0)
3097  {
3098  p = error_area = (char *) malloc (3 * OR_INT_SIZE + strlen (er_msg) + 1);
3099 
3100  if (error_area)
3101  {
3102  p = or_pack_int (p, errid);
3103  p = or_pack_int (p, ER_ERROR_SEVERITY);
3104  p = or_pack_int (p, strlen (er_msg) + 1);
3105  strcpy (p, er_msg);
3106 
3107  er_set_area_error (error_area);
3108  free_and_init (error_area);
3109  }
3110  }
3111 
3112  return errid;
3113 }
3114 #endif /* ENABLE_UNUSED_FUNCTION */
3115 
3116 /*
3117  * qmgr_set_query_error () - set current thread's error to query entry
3118  * return:
3119  * query_id(in) :
3120  */
3121 void
3122 qmgr_set_query_error (THREAD_ENTRY * thread_p, QUERY_ID query_id)
3123 {
3124  QMGR_QUERY_ENTRY *query_p;
3125 
3126  query_p = qmgr_get_query_entry (thread_p, query_id, NULL_TRAN_INDEX);
3127  if (query_p != NULL)
3128  {
3129  if (query_p->errid != NO_ERROR)
3130  {
3131  /* if an error was already set, don't overwrite it */
3132  return;
3133  }
3134 
3135  assert (er_errid () != NO_ERROR);
3136  query_p->errid = er_errid ();
3137  if (query_p->errid != NO_ERROR)
3138  {
3139 #if defined (SERVER_MODE)
3140  char *ptr = (char *) er_msg ();
3141 
3142  if (ptr != NULL)
3143  {
3144  query_p->er_msg = strdup (ptr);
3145  }
3146  else
3147  {
3148  query_p->er_msg = NULL;
3149  }
3150 #else
3151  query_p->er_msg = (char *) er_msg ();
3152 #endif
3153  }
3154  else
3155  {
3156  query_p->er_msg = NULL;
3157  }
3158  }
3159 }
3160 
3161 #if defined (SERVER_MODE)
3162 /*
3163  * qmgr_find_leaf () -
3164  * return:
3165  * xasl(in) :
3166  */
3167 static XASL_NODE *
3168 qmgr_find_leaf (XASL_NODE * xasl_p)
3169 {
3170  /* Search down the left side until a BUILDLIST_PROC node is found */
3171  for (xasl_p = xasl_p->proc.union_.left; xasl_p; xasl_p = xasl_p->proc.union_.left)
3172  {
3173  if (xasl_p->type == BUILDLIST_PROC)
3174  {
3175  break;
3176  }
3177  }
3178 
3179  return xasl_p;
3180 }
3181 #endif /* (SERVER_MODE) */
3182 
3183 void
3185 {
3186  QFILE_PAGE_HEADER header;
3187 
3188  header.pg_tplcnt = 0;
3190  header.prev_pgid = header.next_pgid = header.ovfl_pgid = NULL_PAGEID;
3191  header.prev_volid = header.next_volid = header.ovfl_volid = NULL_VOLID;
3192 
3193  qmgr_put_page_header (page_p, &header);
3194 }
3195 
3196 /*
3197  * qmgr_initialize_temp_file_list () -
3198  * return: none
3199  * temp_file_list_p(in): temporary file list to be initialized
3200  * membuf_type(in):
3201  */
3202 void
3204 {
3205  int i, num_buffer_pages;
3206  QMGR_TEMP_FILE *temp_file_p;
3207  int rv;
3208 
3209  assert (temp_file_list_p != NULL && QMGR_IS_VALID_MEMBUF_TYPE (membuf_type));
3210  if (temp_file_list_p == NULL || !QMGR_IS_VALID_MEMBUF_TYPE (membuf_type))
3211  {
3212  return;
3213  }
3214 
3215  num_buffer_pages = ((membuf_type == TEMP_FILE_MEMBUF_NORMAL) ? prm_get_integer_value (PRM_ID_TEMP_MEM_BUFFER_PAGES)
3217 
3218  pthread_mutex_init (&temp_file_list_p->mutex, NULL);
3219  rv = pthread_mutex_lock (&temp_file_list_p->mutex);
3220  temp_file_list_p->list = NULL;
3221 
3222  for (i = 0; i < QMGR_TEMP_FILE_FREE_LIST_SIZE; i++)
3223  {
3224  temp_file_p = qmgr_allocate_tempfile_with_buffer (num_buffer_pages);
3225  if (temp_file_p == NULL)
3226  {
3227  break;
3228  }
3229  /* add to the free list */
3230  temp_file_p->prev = NULL;
3231  temp_file_p->next = temp_file_list_p->list;
3232  temp_file_p->membuf_npages = num_buffer_pages;
3233  temp_file_p->membuf_type = membuf_type;
3234  temp_file_list_p->list = temp_file_p;
3235  }
3236 
3237  temp_file_list_p->count = i;
3238 
3239  pthread_mutex_unlock (&temp_file_list_p->mutex);
3240 }
3241 
3242 /*
3243  * qmgr_finalize_temp_file_list () -
3244  * return: none
3245  * temp_file_list_p(in): temporary file list to be finalized
3246  */
3247 void
3249 {
3250  QMGR_TEMP_FILE *temp_file_p;
3251 
3252  assert (temp_file_list_p != NULL);
3253  if (temp_file_list_p == NULL)
3254  {
3255  return;
3256  }
3257 
3258  while (temp_file_list_p->list)
3259  {
3260  temp_file_p = temp_file_list_p->list;
3261  temp_file_list_p->list = temp_file_p->next;
3262  free_and_init (temp_file_p);
3263  }
3264  temp_file_list_p->count = 0;
3265  pthread_mutex_destroy (&temp_file_list_p->mutex);
3266 }
3267 
3268 /*
3269  * qmgr_get_temp_file_from_list () -
3270  * return: temporary file
3271  * temp_file_list_p(in): temporary file list
3272  */
3275 {
3276  QMGR_TEMP_FILE *temp_file_p = NULL;
3277  int rv;
3278 
3279  assert (temp_file_list_p != NULL);
3280  if (temp_file_list_p == NULL)
3281  {
3282  return NULL;
3283  }
3284 
3285  rv = pthread_mutex_lock (&temp_file_list_p->mutex);
3286 
3287  /* delete from the free list */
3288  if (temp_file_list_p->list)
3289  {
3290  temp_file_p = temp_file_list_p->list;
3291  temp_file_list_p->list = temp_file_p->next;
3292  temp_file_p->prev = temp_file_p->next = NULL;
3293  temp_file_list_p->count--;
3294  }
3295 
3296  pthread_mutex_unlock (&temp_file_list_p->mutex);
3297 
3298  return temp_file_p;
3299 }
3300 
3301 /*
3302  * qmgr_put_temp_file_into_list () -
3303  * return: none
3304  * temp_file_list_p(in): temporary file list
3305  */
3306 void
3308 {
3309  QMGR_TEMP_FILE_LIST *temp_file_list_p;
3310  int rv;
3311 
3312  assert (temp_file_p != NULL);
3313  if (temp_file_p == NULL)
3314  {
3315  return;
3316  }
3317 
3318  temp_file_p->membuf_last = -1;
3319 
3320  if (QMGR_IS_VALID_MEMBUF_TYPE (temp_file_p->membuf_type))
3321  {
3322  temp_file_list_p = &qmgr_Query_table.temp_file_list[temp_file_p->membuf_type];
3323 
3324  rv = pthread_mutex_lock (&temp_file_list_p->mutex);
3325 
3326  /* add to the free list */
3327  if (temp_file_list_p->count < QMGR_TEMP_FILE_FREE_LIST_SIZE)
3328  {
3329  temp_file_p->prev = NULL;
3330  temp_file_p->next = temp_file_list_p->list;
3331  temp_file_list_p->list = temp_file_p;
3332  temp_file_list_p->count++;
3333  temp_file_p = NULL;
3334  }
3335 
3336  pthread_mutex_unlock (&temp_file_list_p->mutex);
3337  }
3338  if (temp_file_p)
3339  {
3340  free_and_init (temp_file_p);
3341  }
3342 }
3343 
3344 /*
3345  * qmgr_get_temp_file_membuf_pages () -
3346  * return: number of membuf pages belonging to the temporary file
3347  * temp_file_list_p(in): temporary file
3348  */
3349 int
3351 {
3352  assert (temp_file_p != NULL);
3353  if (temp_file_p == NULL)
3354  {
3355  return -1;
3356  }
3357  return temp_file_p->membuf_npages;
3358 }
3359 
3360 #if defined (SERVER_MODE)
3361 /*
3362  * qmgr_set_query_exec_info_to_tdes () - calculate timeout and set to transaction
3363  * descriptor
3364  * return: void
3365  * tran_index(in):
3366  * query_timeout(in): milli seconds
3367  */
3368 static void
3369 qmgr_set_query_exec_info_to_tdes (int tran_index, int query_timeout, const XASL_ID * xasl_id)
3370 {
3371  LOG_TDES *tdes_p;
3372 
3373  tdes_p = LOG_FIND_TDES (tran_index);
3374  assert (tdes_p != NULL);
3375  if (tdes_p != NULL)
3376  {
3377  /* We use log_Clock_msec instead of calling gettimeofday if the system supports atomic built-ins. */
3378  tdes_p->query_start_time = log_get_clock_msec ();
3379 
3380  if (query_timeout > 0)
3381  {
3382  tdes_p->query_timeout = tdes_p->query_start_time + query_timeout;
3383  }
3384  else if (query_timeout == 0)
3385  {
3386  tdes_p->query_timeout = 0;
3387  }
3388  else if (query_timeout != -1)
3389  {
3390  /* already expired */
3391  tdes_p->query_timeout = tdes_p->query_start_time;
3392  }
3393  else
3394  {
3395  /*
3396  * query_timeout == -1
3397  * This means that the query is not the first of a bundle of queries.
3398  * We will apply a timeout to the bundle, not each query.
3399  * Actually CAS always sends -1 in this case.
3400  */
3401  }
3402  if (tdes_p->tran_start_time == 0)
3403  {
3404  /* set transaction start time, if this is the first query */
3405  tdes_p->tran_start_time = tdes_p->query_start_time;
3406  }
3407  if (xasl_id != NULL)
3408  {
3409  XASL_ID_COPY (&tdes_p->xasl_id, xasl_id);
3410  }
3411  }
3412 }
3413 
3414 /*
3415  * qmgr_reset_query_exec_info () - reset query_start_time and xasl_id of tdes
3416  * return: void
3417  * tran_index(in):
3418  */
3419 static void
3420 qmgr_reset_query_exec_info (int tran_index)
3421 {
3422  LOG_TDES *tdes_p;
3423 
3424  tdes_p = LOG_FIND_TDES (tran_index);
3425  assert (tdes_p != NULL);
3426  if (tdes_p != NULL)
3427  {
3428  tdes_p->query_start_time = 0;
3429  XASL_ID_SET_NULL (&tdes_p->xasl_id);
3430  tdes_p->query_timeout = 0;
3431  }
3432 }
3433 #endif
3434 
3435 /*
3436  * qmgr_get_sql_id ()
3437  * return: error_code
3438  * sql_id_buf(out):
3439  * buf_size(in):
3440  * query(in):
3441  * sql_len(in):
3442  *
3443  * note : caller must free sql_id_buf
3444  *
3445  * CUBRID SQL_ID is generated from md5 hash_value. The last 13 hexa-digit string of md5-hash(32 hexa-digit) string.
3446  * Oracle's SQL_ID is also generated from md5 hash-value. But it uses the last 8 hexa-digit to generate 13-digit string.
3447  * So the SQL_ID of a query is different in CUBRID and oracle, even though the length is same.
3448  */
3449 int
3450 qmgr_get_sql_id (THREAD_ENTRY * thread_p, char **sql_id_buf, char *query, size_t sql_len)
3451 {
3452  char hashstring[32 + 1] = { '\0' };
3453  char *ret_buf;
3454 
3455  if (sql_id_buf == NULL)
3456  {
3457  assert_release (0);
3458  return ER_FAILED;
3459  }
3460 
3461  ret_buf = (char *) malloc (sizeof (char) * (QMGR_SQL_ID_LENGTH + 1));
3462  if (ret_buf == NULL)
3463  {
3465  return ER_OUT_OF_VIRTUAL_MEMORY;
3466  }
3467 
3468  int ec = crypt_md5_buffer_hex (query, sql_len, hashstring);
3469  if (ec != NO_ERROR)
3470  {
3471  free (ret_buf);
3472  return ec;
3473  }
3474 
3475  /* copy last 13 hexa-digit to ret_buf */
3476  strncpy (ret_buf, hashstring + 19, QMGR_SQL_ID_LENGTH);
3477  ret_buf[QMGR_SQL_ID_LENGTH] = '\0';
3478 
3479  *sql_id_buf = ret_buf;
3480 
3481  return NO_ERROR;
3482 }
3483 
3484 /* qmgr_get_rand_buf() : return the drand48_data reference
3485  * thread_p(in):
3486  */
3487 struct drand48_data *
3489 {
3490 #if defined(SERVER_MODE)
3491  return &thread_p->rand_buf;
3492 #else
3493  return &qmgr_rand_buf;
3494 #endif
3495 }
3496 
3497 /*
3498  * qmgr_get_current_query_id () - return the current query id
3499  * return: QUERY_ID
3500  * thread_p(in):
3501  */
3502 QUERY_ID
3504 {
3505  QMGR_TRAN_ENTRY *tran_entry_p = NULL;
3506  QUERY_ID query_id = NULL_QUERY_ID;
3507  int tran_index;
3508 
3509  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
3510  tran_entry_p = &qmgr_Query_table.tran_entries_p[tran_index];
3511 
3512  if (tran_entry_p->query_entry_list_p != NULL)
3513  {
3514  query_id = tran_entry_p->query_entry_list_p->query_id;
3515  }
3516 
3517  return query_id;
3518 }
3519 
3520 /*
3521  * qmgr_get_query_sql_user_text () - return sql_user_text of the given query_id
3522  * return: query string
3523  * thread_p(in):
3524  * query_id(in):
3525  * tran_index(in):
3526  */
3527 char *
3528 qmgr_get_query_sql_user_text (THREAD_ENTRY * thread_p, QUERY_ID query_id, int tran_index)
3529 {
3530  QMGR_QUERY_ENTRY *query_ent_p = NULL;
3531  XASL_CACHE_ENTRY *xasl_ent_p = NULL;
3532  char *query_str = NULL;
3533 
3534  query_ent_p = qmgr_get_query_entry (thread_p, query_id, tran_index);
3535  if (query_ent_p != NULL)
3536  {
3537  xasl_ent_p = query_ent_p->xasl_ent;
3538  if (xasl_ent_p != NULL)
3539  {
3540  query_str = xasl_ent_p->sql_info.sql_user_text;
3541  }
3542  }
3543 
3544  return query_str;
3545 }
void qmgr_dump(void)
#define IS_TRIGGER_INVOLVED(flag)
Definition: query_list.h:578
int scan_initialize(void)
int stx_map_stream_to_xasl(THREAD_ENTRY *thread_p, xasl_node **xasl_tree, bool use_xasl_clone, char *xasl_stream, int xasl_stream_size, XASL_UNPACK_INFO **xasl_unpack_info_ptr)
#define QFILE_LAST_TUPLE_OFFSET
Definition: query_list.h:53
char * PAGE_PTR
static void qmgr_add_query_entry(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *q_ptr, int trans_ind)
char * or_unpack_oid(char *ptr, OID *oid)
int xsession_remove_query_entry_info(THREAD_ENTRY *thread_p, const QUERY_ID query_id)
Definition: session_sr.c:343
QMGR_TRAN_STATUS
Definition: query_manager.h:61
int file_temp_retire(THREAD_ENTRY *thread_p, const VFID *vfid)
QFILE_LIST_CACHE_ENTRY * list_ent
QFILE_LIST_ID * list_id
#define NO_ERROR
Definition: error_code.h:46
int xcache_find_sha1(THREAD_ENTRY *thread_p, const SHA1Hash *sha1, const XASL_CACHE_SEARCH_MODE search_mode, XASL_CACHE_ENTRY **xcache_entry, xasl_cache_rt_check_result *rt_check)
Definition: xasl_cache.c:791
static void qmgr_free_tran_entries(void)
void xsession_store_query_entry_info(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *qentry_p)
Definition: session_sr.c:318
#define QFILE_OVERFLOW_PAGE_ID_OFFSET
Definition: query_list.h:54
void qmgr_set_query_error(THREAD_ENTRY *thread_p, QUERY_ID query_id)
#define pthread_mutex_unlock(a)
Definition: query_manager.c:56
XASL_NODE_HEADER * xasl_header
Definition: xasl.h:611
#define ER_FILE_NOT_ENOUGH_PAGES_IN_VOLUME
Definition: error_code.h:89
int qfile_end_use_of_list_cache_entry(THREAD_ENTRY *thread_p, QFILE_LIST_CACHE_ENTRY *lent, bool marker)
Definition: list_file.c:5849
XCACHE_RELATED_OBJECT * related_objects
Definition: xasl_cache.h:105
struct qmgr_temp_file * tfile_vfid
Definition: query_list.h:440
#define CACHE_TIME_RESET(T)
Definition: cache_time.h:40
DB_VALUE * vals
Definition: dbtype_def.h:1100
#define ASSERT_ERROR()
struct qmgr_tran_entry QMGR_TRAN_ENTRY
Definition: query_manager.c:96
void qmgr_clear_trans_wakeup(THREAD_ENTRY *thread_p, int tran_index, bool is_tran_died, bool is_abort)
#define QFILE_PREV_PAGE_ID_OFFSET
Definition: query_list.h:51
static void qmgr_clear_relative_cache_entries(THREAD_ENTRY *thread_p, QMGR_TRAN_ENTRY *tran_entry_p)
QFILE_TUPLE_VALUE_TYPE_LIST type_list
Definition: query_list.h:428
static QMGR_QUERY_ENTRY * qmgr_find_query_entry(QMGR_QUERY_ENTRY *query_list_p, QUERY_ID query_id)
QUERY_ID query_id
Definition: query_list.h:438
#define XASL_TO_BE_CACHED
Definition: xasl.h:481
PAGE_PTR last_pgptr
Definition: query_list.h:434
void qmgr_free_old_page(THREAD_ENTRY *thread_p, PAGE_PTR page_p, QMGR_TEMP_FILE *tfile_vfid_p)
int errid
#define QFILE_FREE_AND_INIT_LIST_ID(list_id)
Definition: list_file.h:56
SHA1Hash sha1
static OID_BLOCK_LIST * qmgr_allocate_oid_block(THREAD_ENTRY *thread_p)
struct oid_block_list OID_BLOCK_LIST
#define pthread_mutex_init(a, b)
Definition: query_manager.c:53
QFILE_LIST_CACHE_ENTRY * qfile_lookup_list_cache_entry(THREAD_ENTRY *thread_p, int list_ht_no, const DB_VALUE_ARRAY *params, bool *result_cached)
Definition: list_file.c:5480
int thread_get_recursion_depth(cubthread::entry *thread_p)
int logtb_get_number_of_total_tran_indices(void)
PAGE_PTR qmgr_get_old_page(THREAD_ENTRY *thread_p, VPID *vpid_p, QMGR_TEMP_FILE *tfile_vfid_p)
#define ER_FAILED
Definition: error_code.h:47
void qfile_load_xasl_node_header(THREAD_ENTRY *thread_p, char *xasl_stream, xasl_node_header *xasl_header_p)
Definition: list_file.c:1063
const int LOG_SYSTEM_TRAN_INDEX
#define pthread_mutex_destroy(a)
Definition: query_manager.c:54
#define csect_enter(a, b, c)
Definition: cnv.c:138
#define IS_XASL_TRACE_JSON(flag)
Definition: query_list.h:576
union xasl_node::@155 proc
#define pgbuf_unfix(thread_p, pgptr)
Definition: page_buffer.h:276
QMGR_TEMP_FILE * prev
Definition: query_manager.h:79
#define ER_QPROC_INVALID_XASLNODE
Definition: error_code.h:532
static void qmgr_mark_query_as_completed(QMGR_QUERY_ENTRY *query_p)
#define ASSERT_ERROR_AND_SET(error_code)
int num_tmp
#define assert_release(e)
Definition: error_manager.h:96
void pgbuf_set_dirty(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, bool free_page)
Definition: page_buffer.c:4280
INT64 log_get_clock_msec(void)
static bool qmgr_is_related_class_modified(THREAD_ENTRY *thread_p, XASL_CACHE_ENTRY *xasl_cache, int tran_index)
struct oid_block_list * next
Definition: query_manager.c:91
int qmgr_allocate_tran_entries(THREAD_ENTRY *thread_p, int num_new_entries)
xasl_cache_rt_check_result
Definition: xasl_cache.h:147
UNION_PROC_NODE union_
Definition: xasl.h:1017
static QMGR_QUERY_ENTRY * qmgr_allocate_query_entry(THREAD_ENTRY *thread_p, QMGR_TRAN_ENTRY *tran_entry_p)
int num_query_entries
#define QFILE_PREV_VOL_ID_OFFSET
Definition: query_list.h:55
LOG_TDES * LOG_FIND_TDES(int tran_index)
Definition: log_impl.h:1095
OID oid_array[OID_BLOCK_ARRAY_SIZE]
Definition: query_manager.c:93
static PAGE_PTR qmgr_get_external_file_page(THREAD_ENTRY *thread_p, VPID *vpid, QMGR_TEMP_FILE *vfid)
int32_t pageid
Definition: dbtype_def.h:879
#define MAX_NTRANS
void qmgr_setup_empty_list_file(char *page_p)
int er_errid(void)
void xcache_retire_clone(THREAD_ENTRY *thread_p, XASL_CACHE_ENTRY *xcache_entry, XASL_CLONE *xclone)
Definition: xasl_cache.c:2040
PROC_TYPE type
Definition: xasl.h:953
#define XASL_INCLUDES_TDE_CLASS
Definition: xasl.h:493
bool logtb_get_check_interrupt(THREAD_ENTRY *thread_p)
int xcache_insert(THREAD_ENTRY *thread_p, const compile_context *context, XASL_STREAM *stream, int n_oid, const OID *class_oids, const int *class_locks, const int *tcards, XASL_CACHE_ENTRY **xcache_entry)
Definition: xasl_cache.c:1350
#define er_log_debug(...)
HL_HEAPID db_change_private_heap(THREAD_ENTRY *thread_p, HL_HEAPID heap_id)
Definition: memory_alloc.c:337
static void qmgr_put_temp_file_into_list(QMGR_TEMP_FILE *temp_file_p)
static QMGR_TEMP_FILE * qmgr_get_temp_file_from_list(QMGR_TEMP_FILE_LIST *temp_file_list_p)
#define DO_NOT_COLLECT_EXEC_STATS(flag)
Definition: query_list.h:573
#define MAX_ALIGNMENT
Definition: memory_alloc.h:70
#define ER_QM_QENTRY_RUNOUT
Definition: error_code.h:1030
#define pthread_mutex_lock(a)
Definition: query_manager.c:55
INT64 query_start_time
Definition: log_impl.h:520
#define VFID_ISNULL(vfid_ptr)
Definition: file_manager.h:72
void THREAD_ENTRY
pthread_mutex_t mutex
static int qmgr_init_external_file_page(THREAD_ENTRY *thread_p, PAGE_PTR page, void *args)
#define NULL_PAGEID
#define SHA1_AS_ARGS(sha1)
Definition: sha1.h:56
XASL_NODE * xasl
Definition: xasl_cache.h:65
QMGR_TEMP_FILE * qmgr_create_result_file(THREAD_ENTRY *thread_p, QUERY_ID query_id)
bool xcache_can_entry_cache_list(XASL_CACHE_ENTRY *xcache_entry)
Definition: xasl_cache.c:2004
LOCK
bool session_is_queryid_idle(THREAD_ENTRY *thread_p, const QUERY_ID query_id, QUERY_ID *max_query_id_uses)
Definition: session.c:2647
QFILE_LIST_ID * xqmgr_execute_query(THREAD_ENTRY *thread_p, const XASL_ID *xasl_id_p, QUERY_ID *query_id_p, int dbval_count, void *dbval_p, QUERY_FLAG *flag_p, CACHE_TIME *client_cache_time_p, CACHE_TIME *server_cache_time_p, int query_timeout, xasl_cache_ent **ret_cache_entry_p)
static struct drand48_data qmgr_rand_buf
#define FREE(PTR)
Definition: cas_common.h:56
int xsession_clear_query_entry_info(THREAD_ENTRY *thread_p, const QUERY_ID query_id)
Definition: session_sr.c:357
int xcache_invalidate_qcaches(THREAD_ENTRY *thread_p, const OID *oid)
Definition: xasl_cache.c:1689
QMGR_QUERY_ENTRY * free_query_entry_list_p
PAGE_TYPE pgbuf_get_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr)
Definition: page_buffer.c:4675
#define XASL_CLONE_INITIALIZER
Definition: xasl_cache.h:67
#define QFILE_OVERFLOW_VOL_ID_OFFSET
Definition: query_list.h:57
int qmgr_get_temp_file_membuf_pages(QMGR_TEMP_FILE *temp_file_p)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
void thread_set_trace_format(cubthread::entry *thread_p, int format)
#define XASL_SET_FLAG(x, f)
Definition: xasl.h:496
#define QFILE_NEXT_PAGE_ID_OFFSET
Definition: query_list.h:52
#define XASL_ID_COPY(X1, X2)
Definition: xasl.h:562
#define assert(x)
void log_skip_logging(THREAD_ENTRY *thread_p, LOG_DATA_ADDR *addr)
Definition: log_manager.c:3244
TDE_ALGORITHM
Definition: tde.h:71
static void qmgr_deallocate_query_entries(QMGR_QUERY_ENTRY *q_ptr)
int query_id_generator
bool pgbuf_check_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
static bool qmgr_can_get_result_from_cache(QUERY_FLAG flag)
int prm_get_integer_value(PARAM_ID prm_id)
#define ER_QPROC_OUT_OF_TEMP_SPACE
Definition: error_code.h:879
#define ER_GENERIC_ERROR
Definition: error_code.h:49
int er_set_area_error(char *server_area)
QMGR_QUERY_STATUS query_status
void qfile_destroy_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:2163
int num_exec_queries
Definition: log_impl.h:529
CACHE_TIME time_stored
int file_apply_tde_algorithm(THREAD_ENTRY *thread_p, const VFID *vfid, const TDE_ALGORITHM tde_algo)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
static void qmgr_delete_query_entry(THREAD_ENTRY *thread_p, QUERY_ID query_id, int trans_ind)
QMGR_TEMP_FILE_MEMBUF_TYPE membuf_type
Definition: query_manager.h:85
#define QFILE_PAGE_HEADER_SIZE
Definition: query_list.h:47
QUERY_FLAG query_flag
QMGR_TEMP_FILE_LIST temp_file_list[QMGR_NUM_TEMP_FILE_LISTS]
bool logtb_is_interrupted_tran(THREAD_ENTRY *thread_p, bool clear, bool *continue_checking, int tran_index)
int xcache_find_xasl_id_for_execute(THREAD_ENTRY *thread_p, const XASL_ID *xid, XASL_CACHE_ENTRY **xcache_entry, XASL_CLONE *xclone)
Definition: xasl_cache.c:888
#define QMGR_TEMP_FILE_FREE_LIST_SIZE
Definition: query_manager.c:64
#define ER_QPROC_UNKNOWN_QUERYID
Definition: error_code.h:529
QFILE_LIST_ID * qfile_duplicate_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p, int flag)
Definition: list_file.c:4174
QFILE_LIST_CACHE_ENTRY * qfile_update_list_cache_entry(THREAD_ENTRY *thread_p, int list_ht_no, const DB_VALUE_ARRAY *params, const QFILE_LIST_ID *list_id, XASL_CACHE_ENTRY *xasl)
Definition: list_file.c:5627
void xcache_unfix(THREAD_ENTRY *thread_p, XASL_CACHE_ENTRY *xcache_entry)
Definition: xasl_cache.c:1083
Definition: list_file.h:82
PAGEID prev_pgid
Definition: list_file.h:69
QFILE_LIST_ID list_id
Definition: list_file.h:86
QMGR_TEMP_FILE * qmgr_create_new_temp_file(THREAD_ENTRY *thread_p, QUERY_ID query_id, QMGR_TEMP_FILE_MEMBUF_TYPE membuf_type)
#define QFILE_RESERVED_OFFSET
Definition: query_list.h:58
int qmgr_initialize(THREAD_ENTRY *thread_p)
#define CACHE_TIME_AS_ARGS(ct)
Definition: cache_time.h:35
int qmgr_free_list_temp_file(THREAD_ENTRY *thread_p, QUERY_ID query_id, QMGR_TEMP_FILE *tfile_vfid_p)
XASL_ID xasl_id
Definition: xasl_cache.h:92
short volid
Definition: dbtype_def.h:880
xasl_cache_ent * xasl_ent
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
bool includes_tde_class
#define QFILE_NEXT_VOL_ID_OFFSET
Definition: query_list.h:56
static int rv
Definition: area_alloc.c:52
QMGR_QUERY_TABLE qmgr_Query_table
static int qmgr_free_query_temp_file_helper(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *query_p)
static void qmgr_finalize_temp_file_list(QMGR_TEMP_FILE_LIST *temp_file_list_p)
SORT_LIST * sort_list
Definition: query_list.h:429
static void qmgr_deallocate_oid_blocks(OID_BLOCK_LIST *oid_block)
char * er_msg
#define NULL
Definition: freelistheap.h:34
int file_alloc(THREAD_ENTRY *thread_p, const VFID *vfid, FILE_INIT_PAGE_FUNC f_init, void *f_init_args, VPID *vpid_out, PAGE_PTR *page_out)
void file_temp_preserve(THREAD_ENTRY *thread_p, const VFID *vfid)
Definition: query_manager.c:97
#define XASL_IS_FLAGED(x, f)
Definition: xasl.h:495
const char * er_msg(void)
XASL_ID xasl_id
#define IS_XASL_CACHE_PINNED_REFERENCE(flag)
Definition: query_list.h:580
int qfile_dump_list_cache_internal(THREAD_ENTRY *thread_p, FILE *fp)
Definition: list_file.c:5321
#define SERVER_MODE
int method_Num_method_jsp_calls
Definition: method_scan.c:54
int crypt_md5_buffer_hex(const char *buffer, size_t len, char *resblock)
Definition: crypt_opfunc.c:646
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define pgbuf_fix(thread_p, vpid, fetch_mode, requestmode, condition)
Definition: page_buffer.h:255
#define CACHE_TIME_MAKE(CT, TV)
Definition: cache_time.h:48
#define csect_exit(a, b)
Definition: cnv.c:139
char * or_unpack_int(char *ptr, int *number)
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
OID_BLOCK_LIST * modified_classes_p
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
bool is_holdable
int file_create_temp(THREAD_ENTRY *thread_p, int npages, VFID *vfid)
PAGEID next_pgid
Definition: list_file.h:70
int file_temp_retire_preserved(THREAD_ENTRY *thread_p, const VFID *vfid)
#define OR_PUT_SHORT(ptr, val)
int pr_clear_value(DB_VALUE *value)
void qmgr_add_modified_class(THREAD_ENTRY *thread_p, const OID *class_oid_p)
EXECUTION_INFO sql_info
Definition: xasl_cache.h:103
XASL_ID xasl_id
Definition: log_impl.h:522
int xqmgr_end_query(THREAD_ENTRY *thread_p, QUERY_ID query_id)
FILE_TYPE temp_file_type
Definition: query_manager.h:80
QMGR_TEMP_FILE * temp_vfid
static void qmgr_put_page_header(PAGE_PTR page_p, QFILE_PAGE_HEADER *header_p)
void thread_trace_on(cubthread::entry *thread_p)
QUERY_ID query_id
void qmgr_set_dirty_page(THREAD_ENTRY *thread_p, PAGE_PTR page_p, int free_page, LOG_DATA_ADDR *addr_p, QMGR_TEMP_FILE *tfile_vfid_p)
static void qmgr_initialize_temp_file_list(QMGR_TEMP_FILE_LIST *temp_file_list_p, QMGR_TEMP_FILE_MEMBUF_TYPE membuf_type)
static QMGR_TEMP_FILE * qmgr_allocate_tempfile_with_buffer(int num_buffer_pages)
struct timeval time_created
Definition: list_file.h:97
#define NULL_TRAN_INDEX
void free_xasl_unpack_info(THREAD_ENTRY *thread_p, REFPTR(XASL_UNPACK_INFO, xasl_unpack_info))
DB_VALUE_ARRAY bind_history[MAX_NUM_EXEC_QUERY_HISTORY]
Definition: log_impl.h:530
static int rc
Definition: serial.c:50
char * or_pack_int(char *ptr, int number)
STATIC_INLINE void perfmon_inc_stat(THREAD_ENTRY *thread_p, PERF_STAT_ID psid) __attribute__((ALWAYS_INLINE))
#define ER_INTERRUPTED
Definition: error_code.h:51
int n_related_objects
Definition: xasl_cache.h:110
QMGR_TRAN_STATUS trans_stat
Definition: query_manager.c:99
LOG_TDES * LOG_FIND_CURRENT_TDES(THREAD_ENTRY *thread_p=NULL)
Definition: log_impl.h:1115
#define LOG_FIND_THREAD_TRAN_INDEX(thrd)
Definition: perf_monitor.h:158
INT64 tran_start_time
Definition: log_impl.h:521
int xqmgr_drop_all_query_plans(THREAD_ENTRY *thread_p)
QUERY_ID qmgr_get_current_query_id(THREAD_ENTRY *thread_p)
bool qfile_has_no_cache_entries()
Definition: list_file.c:6494
#define ARG_FILE_LINE
Definition: error_manager.h:44
PAGE_PTR * membuf
Definition: query_manager.h:83
XASL_NODE * left
Definition: xasl.h:289
#define QFILE_PAGE_HEADER_INITIALIZER
Definition: list_file.h:77
#define QMGR_IS_VALID_MEMBUF_TYPE(m)
Definition: query_manager.c:71
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
#define QMGR_NUM_TEMP_FILE_LISTS
Definition: query_manager.c:66
qfile_list_id * qexec_execute_query(THREAD_ENTRY *thread_p, xasl_node *xasl, int dbval_cnt, const DB_VALUE *dbval_ptr, QUERY_ID query_id)
QMGR_QUERY_ENTRY * next
#define QMGR_MAX_QUERY_ENTRY_PER_TRAN
Definition: query_manager.c:62
QFILE_LIST_ID * qfile_clone_list_id(const QFILE_LIST_ID *list_id_p, bool is_include_sort_list)
Definition: list_file.c:501
QMGR_TEMP_FILE * next
Definition: query_manager.h:78
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define DB_ALIGN(offset, align)
Definition: memory_alloc.h:84
#define strlen(s1)
Definition: intl_support.c:43
PAGE_PTR qmgr_get_new_page(THREAD_ENTRY *thread_p, VPID *vpid_p, QMGR_TEMP_FILE *tfile_vfid_p)
static void qmgr_free_query_entry(THREAD_ENTRY *thread_p, QMGR_TRAN_ENTRY *tran_entry_p, QMGR_QUERY_ENTRY *q_ptr)
static bool qmgr_is_allowed_result_cache(QUERY_FLAG flag)
int oid_compare(const void *a, const void *b)
Definition: oid.c:243
void xcache_dump(THREAD_ENTRY *thread_p, FILE *fp)
Definition: xasl_cache.c:1911
#define QMGR_SQL_ID_LENGTH
Definition: query_manager.c:68
static void qmgr_free_oid_block(THREAD_ENTRY *thread_p, OID_BLOCK_LIST *oid_block)
#define DB_PAGESIZE
#define QFILE_IS_LIST_CACHE_DISABLED
Definition: list_file.h:54
void fpcache_drop_all(THREAD_ENTRY *thread_p)
char * qmgr_get_query_sql_user_text(THREAD_ENTRY *thread_p, QUERY_ID query_id, int tran_index)
int xqmgr_prepare_query(THREAD_ENTRY *thread_p, COMPILE_CONTEXT *context, xasl_stream *stream)
static QMGR_PAGE_TYPE qmgr_get_page_type(PAGE_PTR page_p, QMGR_TEMP_FILE *temp_file_p)
void pgbuf_set_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
Definition: page_buffer.c:4847
int query_timeout
Definition: cas.c:160
INT64 query_timeout
Definition: log_impl.h:518
int session_set_trigger_state(THREAD_ENTRY *thread_p, bool in_trigger)
Definition: session.c:1534
qmgr_page_type
Definition: query_manager.c:73
#define OR_PUT_INT(ptr, val)
void xqmgr_dump_query_plans(THREAD_ENTRY *thread_p, FILE *out_fp)
struct drand48_data * qmgr_get_rand_buf(THREAD_ENTRY *thread_p)
#define OID_BLOCK_ARRAY_SIZE
Definition: query_manager.c:88
XASL_ID * xasl_id
Definition: xasl.h:610
enum qmgr_page_type QMGR_PAGE_TYPE
Definition: query_manager.c:79
xasl_unpack_info * xasl_buf
Definition: xasl_cache.h:64
void scan_finalize(void)
char * buffer
Definition: xasl.h:613
int qmgr_free_temp_file_list(THREAD_ENTRY *thread_p, QMGR_TEMP_FILE *tfile_vfid_p, QUERY_ID query_id, bool is_error)
int i
Definition: dynamic_load.c:954
char * pr_valstring(const DB_VALUE *val)
void qfile_close_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:1263
#define QFILE_TUPLE_COUNT_OFFSET
Definition: query_list.h:50
int file_create_query_area(THREAD_ENTRY *thread_p, VFID *vfid)
static void qmgr_initialize_tran_entry(QMGR_TRAN_ENTRY *tran_entry_p)
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
static int copy_bind_value_to_tdes(THREAD_ENTRY *thread_p, int num_bind_vals, DB_VALUE *bind_vals)
int dbval_cnt
Definition: xasl.h:1040
#define ER_QPROC_INVALID_TEMP_FILE
Definition: error_code.h:904
void qfile_finalize(void)
Definition: list_file.c:1117
char * strdup(const char *str)
Definition: porting.c:901
#define NULL_VOLID
QFILE_LIST_ID * xqmgr_prepare_and_execute_query(THREAD_ENTRY *thread_p, char *xasl_stream, int xasl_stream_size, QUERY_ID *query_id_p, int dbval_count, void *dbval_p, QUERY_FLAG *flag_p, int query_timeout)
int qfile_initialize(void)
Definition: list_file.c:1095
int QUERY_FLAG
Definition: query_list.h:585
int qmgr_get_sql_id(THREAD_ENTRY *thread_p, char **sql_id_buf, char *query, size_t sql_len)
#define IS_IN_METHOD_OR_JSP_CALL()
Definition: query_manager.c:58
char * sql_user_text
Definition: xasl_cache.h:77
void fpcache_dump(THREAD_ENTRY *thread_p, FILE *fp)
#define DONT_FREE
Definition: page_buffer.h:41
QMGR_QUERY_ENTRY * query_entry_list_p
static QFILE_LIST_ID * qmgr_process_query(THREAD_ENTRY *thread_p, XASL_NODE *xasl_tree, char *xasl_stream, int xasl_stream_size, int dbval_count, const DB_VALUE *dbvals_p, QUERY_FLAG flag, QMGR_QUERY_ENTRY *query_p, QMGR_TRAN_ENTRY *tran_entry_p)
int total_count
#define XASL_ID_SET_NULL(X)
Definition: xasl.h:546
QMGR_TEMP_FILE_MEMBUF_TYPE
Definition: query_manager.h:52
#define VPID_SET_NULL(vpid_ptr)
Definition: dbtype_def.h:906
OID_BLOCK_LIST * free_oid_block_list_p
void qmgr_finalize(THREAD_ENTRY *thread_p)
void xcache_drop_all(THREAD_ENTRY *thread_p)
Definition: xasl_cache.c:1890
#define VFID_SET_NULL(vfid_ptr)
Definition: file_manager.h:65
const char ** p
Definition: dynamic_load.c:945
char * or_unpack_db_value(char *buffer, DB_VALUE *val)
QMGR_TEMP_FILE * list
QMGR_TRAN_ENTRY * tran_entries_p
#define IS_XASL_TRACE_TEXT(flag)
Definition: query_list.h:575
static int qmgr_free_query_temp_file(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *qptr, int tran_idx)
void xqmgr_dump_query_cache(THREAD_ENTRY *thread_p, FILE *out_fp)
#define XASL_RETURN_GENERATED_KEYS
Definition: xasl.h:490
PAGEID ovfl_pgid
Definition: list_file.h:72
#define MAX_NUM_EXEC_QUERY_HISTORY
Definition: log_impl.h:275
QMGR_QUERY_ENTRY * qmgr_get_query_entry(THREAD_ENTRY *thread_p, QUERY_ID query_id, int tran_index)
static bool qmgr_can_get_from_cache(QUERY_FLAG flag)
int xsession_load_query_entry_info(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *qentry_p)
Definition: session_sr.c:330