CUBRID Engine  latest
session.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  * session.c - session state internal API
21  */
22 
23 #ident "$Id$"
24 
25 
26 #include <assert.h>
27 
28 #if !defined(WINDOWS)
29 #include <sys/time.h>
30 #include <sys/resource.h>
31 #endif /* !WINDDOWS */
32 
33 #include "system.h"
34 #include "session.h"
35 
36 #include "boot_sr.h"
37 #include "jansson.h"
38 #include "critical_section.h"
39 #include "error_manager.h"
40 #include "system_parameter.h"
41 #include "environment_variable.h"
42 #if defined(SERVER_MODE)
43 #include "connection_sr.h"
44 #else /* !defined (SERVER_MODE) = defined (SA_MODE) */
45 #include "db.h"
46 #endif /* defined (SA_MODE) */
47 #include "lock_free.h"
48 #include "object_primitive.h"
49 #include "dbtype.h"
50 #include "string_opfunc.h"
51 #include "thread_daemon.hpp"
52 #include "thread_entry_task.hpp"
54 #include "thread_manager.hpp"
55 #include "xasl_cache.h"
56 
57 #if !defined(SERVER_MODE)
58 #define pthread_mutex_init(a, b)
59 #define pthread_mutex_destroy(a)
60 #define pthread_mutex_lock(a) 0
61 #define pthread_mutex_trylock(a) 0
62 #define pthread_mutex_unlock(a)
63 static int rv;
64 #endif /* not SERVER_MODE */
65 
66 #define SESSIONS_HASH_SIZE 1000
67 #define MAX_SESSION_VARIABLES_COUNT 20
68 #define MAX_PREPARED_STATEMENTS_COUNT 20
69 
70 typedef struct session_info SESSION_INFO;
72 {
74  int count;
75 };
76 
79 {
80  char *name;
83 };
84 
87 {
88  char *name;
89  char *alias_print;
92  char *info;
94 };
97 {
98  QUERY_ID query_id; /* unique query identifier */
99  QFILE_LIST_ID *list_id; /* result list file identifier */
100  QMGR_TEMP_FILE *temp_file; /* temp files */
101  int num_tmp; /* number of temp files allocated */
102  int total_count; /* total number of file pages allocated for the entire query */
104 
106 };
107 
110 {
111  SESSION_ID id; /* session id */
112  SESSION_STATE *stack; /* used in freelist */
113  SESSION_STATE *next; /* used in hash table */
114  pthread_mutex_t mutex; /* state mutex */
115  UINT64 del_id; /* delete transaction ID (for lock free) */
116 
126  time_t active_time;
128  char *trace_stats;
129  char *plan_string;
134 
136 
137  // *INDENT-OFF*
138  session_state ();
139  ~session_state ();
140  // *INDENT-ON*
141 };
142 
143 /* session state manipulation functions */
144 static void *session_state_alloc (void);
145 static int session_state_free (void *st);
146 static int session_state_init (void *st);
147 static int session_state_uninit (void *st);
148 static int session_key_copy (void *src, void *dest);
149 static unsigned int session_key_hash (void *key, int hash_table_size);
150 static int session_key_compare (void *k1, void *k2);
151 static int session_key_increment (void *key, void *existing);
152 
153 /* session state structure descriptor for hash table */
155  offsetof (SESSION_STATE, stack),
156  offsetof (SESSION_STATE, next),
157  offsetof (SESSION_STATE, del_id),
158  offsetof (SESSION_STATE, id),
159  offsetof (SESSION_STATE, mutex),
160 
162 
171 };
172 
173 // *INDENT-OFF*
175 using session_hashmap_iterator = session_hashmap_type::iterator;
176 // *INDENT-ON*
177 
178 typedef struct active_sessions
179 {
183 
184  // *INDENT-OFF*
186  : states_hashmap {}
187  , last_session_id (0)
188  , num_holdable_cursors (0)
189  {
190  }
191  // *INDENT-ON*
193 
194 /* the active sessions storage */
196 
197 static int session_remove_expired_sessions (THREAD_ENTRY * thread_p);
198 
199 static int session_check_timeout (SESSION_STATE * session_p, SESSION_INFO * active_sessions, bool * remove);
200 
202 
203 static int session_add_variable (SESSION_STATE * state_p, const DB_VALUE * name, DB_VALUE * value);
204 
205 static int session_drop_variable (SESSION_STATE * state_p, const DB_VALUE * name);
206 
207 static void free_session_variable (SESSION_VARIABLE * var);
208 
209 static void update_session_variable (SESSION_VARIABLE * var, const DB_VALUE * new_value);
210 
211 static DB_VALUE *db_value_alloc_and_copy (const DB_VALUE * src);
212 
213 static int session_dump_session (SESSION_STATE * session);
214 static void session_dump_variable (SESSION_VARIABLE * var);
216 
218 static int session_preserve_temporary_files (THREAD_ENTRY * thread_p, SESSION_QUERY_ENTRY * q_entry);
219 static void sentry_to_qentry (const SESSION_QUERY_ENTRY * sentry_p, QMGR_QUERY_ENTRY * qentry_p);
220 static void session_free_sentry_data (THREAD_ENTRY * thread_p, SESSION_QUERY_ENTRY * sentry_p);
221 static void session_set_conn_entry_data (THREAD_ENTRY * thread_p, SESSION_STATE * session_p);
223 #if !defined (NDEBUG) && defined (SERVER_MODE)
224 static int session_state_verify_ref_count (THREAD_ENTRY * thread_p, SESSION_STATE * session_p);
225 #endif
226 
227 // *INDENT-OFF*
229 
230 static void session_control_daemon_init ();
231 static void session_control_daemon_destroy ();
232 
234 {
236 }
237 
239 {
241 }
242 // *INDENT-ON*
243 
244 /*
245  * session_state_alloc () - allocate a new session state
246  * returns: new pointer or NULL on error
247  */
248 static void *
250 {
251  SESSION_STATE *state;
252 
253  state = (SESSION_STATE *) malloc (sizeof (SESSION_STATE));
254  if (state != NULL)
255  {
256  pthread_mutex_init (&state->mutex, NULL);
257  }
258  return (void *) state;
259 }
260 
261 /*
262  * session_state_free () - free a session state
263  * returns: error code or NO_ERROR
264  * st(in): state to free
265  */
266 static int
268 {
269  if (st != NULL)
270  {
272  free (st);
273  return NO_ERROR;
274  }
275  else
276  {
277  return ER_FAILED;
278  }
279 }
280 
281 /*
282  * session_state_init () - initialize a session state
283  * returns: error code or NO_ERROR
284  * st(in): state to initialize
285  */
286 static int
288 {
289  SESSION_STATE *session_p = (SESSION_STATE *) st;
290 
291  if (st == NULL)
292  {
293  return ER_FAILED;
294  }
295 
296  /* initialize fields */
297  db_make_null (&session_p->cur_insert_id);
298  db_make_null (&session_p->last_insert_id);
299  session_p->is_trigger_involved = false;
300  session_p->is_last_insert_id_generated = false;
301  session_p->row_count = -1;
302  session_p->session_variables = NULL;
303  session_p->statements = NULL;
304  session_p->queries = NULL;
305  session_p->session_parameters = NULL;
306  session_p->trace_stats = NULL;
307  session_p->plan_string = NULL;
308  session_p->ref_count = 0;
309  session_p->trace_format = QUERY_TRACE_TEXT;
310  session_p->private_lru_index = -1;
311  session_p->auto_commit = false;
312  session_p->load_session_p = NULL;
313 
314  return NO_ERROR;
315 }
316 
317 /*
318  * session_state_uninit () - uninitialize a session state
319  * returns: error code or NO_ERROR
320  * st(in): state to uninitialize
321  */
322 static int
324 {
325  SESSION_STATE *session = (SESSION_STATE *) st;
326  SESSION_VARIABLE *vcurent = NULL, *vnext = NULL;
327  PREPARED_STATEMENT *pcurent = NULL, *pnext = NULL;
329  SESSION_QUERY_ENTRY *qcurent = NULL, *qnext = NULL;
330  int cnt = 0;
331 
332  if (session == NULL)
333  {
334  return NO_ERROR;
335  }
336 #if defined (SESSION_DEBUG)
337  er_log_debug (ARG_FILE_LINE, "session_free_session %u\n", session->id);
338 #endif /* SESSION_DEBUG */
339 
341 
342  /* free session variables */
343  vcurent = session->session_variables;
344  while (vcurent != NULL)
345  {
346  vnext = vcurent->next;
347  free_session_variable (vcurent);
348  vcurent = vnext;
349  }
350  session->session_variables = NULL;
351 
352  /* free session statements */
353  pcurent = session->statements;
354  while (pcurent != NULL)
355  {
356  pnext = pcurent->next;
358  pcurent = pnext;
359  }
360  session->statements = NULL;
361 
362  /* free holdable queries */
363  qcurent = session->queries;
364  while (qcurent)
365  {
366  qnext = qcurent->next;
367  qcurent->next = NULL;
368  session_free_sentry_data (thread_p, qcurent);
369  free_and_init (qcurent);
370  qcurent = qnext;
371  cnt++;
372  }
373  session->queries = NULL;
374 
375  if (session->session_parameters)
376  {
378  }
379 
380  (void) pgbuf_release_private_lru (thread_p, session->private_lru_index);
381  session->private_lru_index = -1;
382 
383 #if defined (SESSION_DEBUG)
384  er_log_debug (ARG_FILE_LINE, "session_free_session closed %d queries for %d\n", cnt, session->id);
385 #endif /* SESSION_DEBUG */
386 
387  pr_clear_value (&session->cur_insert_id);
388  pr_clear_value (&session->last_insert_id);
389 
390  if (session->trace_stats != NULL)
391  {
392  free_and_init (session->trace_stats);
393  }
394 
395  if (session->plan_string != NULL)
396  {
397  free_and_init (session->plan_string);
398  }
399 
400  return NO_ERROR;
401 }
402 
403 /*
404  * session_key_copy () - copy a session key
405  * returns: error code or NO_ERROR
406  * src(in): source
407  * dest(in): destination
408  */
409 static int
410 session_key_copy (void *src, void *dest)
411 {
412  SESSION_ID *src_id, *dest_id;
413 
414  if (src == NULL || dest == NULL)
415  {
416  return ER_FAILED;
417  }
418 
419  src_id = (SESSION_ID *) src;
420  dest_id = (SESSION_ID *) dest;
421 
422  *dest_id = *src_id;
423 
424  /* all ok */
425  return NO_ERROR;
426 }
427 
428 /*
429  * session_key_hash () - hashing function for the session hash
430  * return: int
431  * key(in): Session key
432  * htsize(in): Memory Hash Table Size
433  *
434  * Note: Generate a hash number for the given key for the given hash table
435  * size.
436  */
437 static unsigned int
438 session_key_hash (void *key, int hash_table_size)
439 {
440  SESSION_ID id = *((SESSION_ID *) key);
441  return (id % hash_table_size);
442 }
443 
444 /*
445  * sessions_key_compare () - Compare two session keys
446  * return: int (true or false)
447  * key_left (in) : First session key
448  * key_right (in) : Second session key
449  */
450 static int
451 session_key_compare (void *k1, void *k2)
452 {
453  SESSION_ID *key1, *key2;
454 
455  key1 = (SESSION_ID *) k1;
456  key2 = (SESSION_ID *) k2;
457 
458  if (k1 == NULL || k2 == NULL)
459  {
460  /* should not happen */
461  assert (false);
462  return 0;
463  }
464 
465  if (*key1 == *key2)
466  {
467  /* equal */
468  return 0;
469  }
470  else
471  {
472  /* not equal */
473  return 1;
474  }
475 }
476 
477 /*
478  * session_key_increment () - increment a key
479  * returns: error code or NO_ERROR
480  * key(in): key to increment
481  * existing(in): existing entry with same key (NOT USED)
482  */
483 static int
484 session_key_increment (void *key, void *existing)
485 {
486  SESSION_ID *key_p = (SESSION_ID *) key;
487 
488  if (key == NULL)
489  {
490  return ER_FAILED;
491  }
492  else
493  {
494  (*key_p)++;
495  return NO_ERROR;
496  }
497 }
498 
499 /*
500  * session_free_prepared_statement () - free memory allocated for a prepared
501  * statement
502  * return : void
503  * stmt_p (in) : prepared statement object
504  */
505 static void
507 {
508  if (stmt_p == NULL)
509  {
510  return;
511  }
512 
513 #if defined (SESSION_DEBUG)
514  er_log_debug (ARG_FILE_LINE, "drop statement %s\n", stmt_p->name);
515 #endif /* SESSION_DEBUG */
516 
517  if (stmt_p->name != NULL)
518  {
519  free_and_init (stmt_p->name);
520  }
521  if (stmt_p->alias_print != NULL)
522  {
523  free_and_init (stmt_p->alias_print);
524  }
525  if (stmt_p->info != NULL)
526  {
527  free_and_init (stmt_p->info);
528  }
529 
530  free_and_init (stmt_p);
531 }
532 
533 // *INDENT-OFF*
534 #if defined (SERVER_MODE)
535 void
536 session_control_daemon_execute (cubthread::entry & thread_ref)
537 {
538  if (!BO_IS_SERVER_RESTARTED ())
539  {
540  // wait for boot to finish
541  return;
542  }
543 
544  session_remove_expired_sessions (&thread_ref);
545 }
546 
547 /*
548  * session_control_daemon_init () - initialize session control daemon
549  */
550 void
552 {
553  assert (session_Control_daemon == NULL);
554 
555  cubthread::looper looper = cubthread::looper (std::chrono::seconds (60));
556  cubthread::entry_callable_task *daemon_task =
557  new cubthread::entry_callable_task (std::bind (session_control_daemon_execute, std::placeholders::_1));
558 
559  // create session control daemon thread
560  session_Control_daemon = cubthread::get_manager ()->create_daemon (looper, daemon_task, "session_control");
561 }
562 
563 /*
564  * session_control_daemon_destroy () - destroy session control daemon
565  */
566 void
568 {
569  cubthread::get_manager ()->destroy_daemon (session_Control_daemon);
570 }
571 #endif /* SERVER_MODE */
572 // *INDENT-ON*
573 
574 /*
575  * session_states_init () - Initialize session states area
576  *
577  * Note: Creates and initializes a main memory hash table that will be
578  * used by session states operations. This routine should only be
579  * called once during server boot.
580  */
581 void
583 {
584  sessions.last_session_id = 0;
585  sessions.num_holdable_cursors = 0;
586 
587 #if defined (SESSION_DEBUG)
588  er_log_debug (ARG_FILE_LINE, "creating session states table\n");
589 #endif /* SESSION_DEBUG */
590 
591  sessions.states_hashmap.init (sessions_Ts, THREAD_TS_SESSIONS, SESSIONS_HASH_SIZE, 2, 50, session_state_Descriptor);
592 
593 #if defined (SERVER_MODE)
595 #endif /* SERVER_MODE */
596 }
597 
598 /*
599  * session_states_finalize () - cleanup the session states information
600  * return: NO_ERROR or error code
601  * thread_p (in) : the thread executing this function
602  *
603  * Note: This function deletes the session states global storage area.
604  * This function should be called only during server shutdown
605  */
606 void
608 {
609 #if defined (SERVER_MODE)
611 #endif /* SERVER_MODE */
612 
613  const char *env_value = envvar_get ("DUMP_SESSION");
614  if (env_value != NULL)
615  {
616  session_states_dump (thread_p);
617  }
618 
619 #if defined (SESSION_DEBUG)
620  er_log_debug (ARG_FILE_LINE, "deleting session state table\n");
621 #endif /* SESSION_DEBUG */
622 
623  /* destroy hash and freelist */
624  sessions.states_hashmap.destroy ();
625 }
626 
627 /*
628  * session_state_create () - Create a sessions state with the specified id
629  * return: NO_ERROR or error code
630  * session_id (in) : the session id
631  *
632  * Note: This function creates and adds a sessions state object to the
633  * sessions state memory hash. This function should be called when a
634  * session starts.
635  */
636 int
638 {
639  SESSION_STATE *session_p = NULL;
640  SESSION_ID next_session_id;
641 
642  assert (id != NULL);
643 
644 #if defined (SERVER_MODE)
645  if (thread_p && thread_p->conn_entry && thread_p->conn_entry->session_p)
646  {
647  SESSION_ID old_id = thread_p->conn_entry->session_id;
648 
649  /* session_check_session should clear session_p, right? add safe-guard if necessary. */
650 
651  assert (thread_p->conn_entry->session_p->id == old_id);
652 
653  session_p = sessions.states_hashmap.find (thread_p, old_id);
654  if (session_p == NULL)
655  {
656  thread_p->conn_entry->session_id = DB_EMPTY_SESSION;
657  thread_p->conn_entry->session_p = NULL;
658  }
659  else
660  {
661  assert (session_p == thread_p->conn_entry->session_p);
662 
663 #if !defined(NDEBUG)
664  session_state_verify_ref_count (thread_p, session_p);
665 #endif
666  thread_p->conn_entry->session_id = DB_EMPTY_SESSION;
667  thread_p->conn_entry->session_p = NULL;
668  session_state_decrease_ref_count (thread_p, session_p);
669 
670  logtb_set_current_user_active (thread_p, false);
671  pthread_mutex_unlock (&session_p->mutex);
672  }
673  }
674 #endif
675 
676  /* create search key */
677  next_session_id = ATOMIC_INC_32 (&sessions.last_session_id, 1);
678  *id = next_session_id;
679 
680  /* insert new entry into hash table */
681  (void) sessions.states_hashmap.insert (thread_p, *id, session_p);
682  if (session_p == NULL)
683  {
684  /* should not happen */
685  assert (false);
686  return ER_FAILED;
687  }
688 
689  /* inserted key might have been incremented; if last_session_id was not modified in the meantime, store the new value
690  */
691  ATOMIC_CAS_32 (&sessions.last_session_id, next_session_id, *id);
692 
693  /* initialize session active time */
694  session_p->active_time = time (NULL);
695 
696 #if defined (SERVER_MODE)
697 #if !defined (NDEBUG)
698  (void) session_state_verify_ref_count (thread_p, session_p);
699 #endif
700  /* increase reference count of new session_p */
701  session_state_increase_ref_count (thread_p, session_p);
702 
703  session_p->private_lru_index = pgbuf_assign_private_lru (thread_p, false, (int) session_p->id);
704  /* set as thread session */
705  session_set_conn_entry_data (thread_p, session_p);
706 
707  logtb_set_current_user_active (thread_p, true);
708 #endif
709 
710  /* done with the entry */
711  pthread_mutex_unlock (&session_p->mutex);
712 
713 #if defined (SESSION_DEBUG)
714  /* debug logging */
715  er_log_debug (ARG_FILE_LINE, "adding session with id %u\n", *id);
717  {
718  session_hashmap_iterator it = { thread_p, sessions.states_hashmap };
719  SESSION_STATE *state;
720 
721  er_log_debug (ARG_FILE_LINE, "printing active sessions\n");
722 
723  for (state = it.iterate (); state != NULL; state = it.iterate ())
724  {
725  er_log_debug (ARG_FILE_LINE, "session %u", state->id);
726  }
727 
728  er_log_debug (ARG_FILE_LINE, "finished printing active sessions\n");
729  }
730 #endif /* SESSION_DEBUG */
731 
732  return NO_ERROR;
733 }
734 
735 /*
736  * session_state_destroy () - close a session state
737  * return : NO_ERROR or error code
738  * id(in) : the identifier for the session
739  */
740 int
742 {
743  SESSION_STATE *session_p;
744  int error = NO_ERROR, success = 0;
745 
746 #if defined (SESSION_DEBUG)
747  er_log_debug (ARG_FILE_LINE, "removing session %u", id);
748 #endif /* SESSION_DEBUG */
749 
750  SESSION_ID key_id = id;
751  session_p = sessions.states_hashmap.find (thread_p, key_id);
752  if (session_p == NULL)
753  {
755  return ER_SES_SESSION_EXPIRED;
756  }
757 
758 #if defined (SERVER_MODE)
759  assert (session_p->ref_count > 0);
760 
761  if (thread_p != NULL && thread_p->conn_entry != NULL && thread_p->conn_entry->session_p != NULL
762  && thread_p->conn_entry->session_p == session_p)
763  {
764  thread_p->conn_entry->session_p = NULL;
765  thread_p->conn_entry->session_id = DB_EMPTY_SESSION;
766 
767  session_state_decrease_ref_count (thread_p, session_p);
768  }
769  else
770  {
771  /* do we accept this case?? if we don't, add safe-guard here. */
772  }
773 
774  logtb_set_current_user_active (thread_p, false);
775 
776  if (session_p->ref_count > 0)
777  {
778  /* This session_state is busy, I can't remove */
779  pthread_mutex_unlock (&session_p->mutex);
780 
781  return NO_ERROR;
782  }
783 
784  /* Now we can destroy this session */
785  assert (session_p->ref_count == 0);
786 #endif
787 
788  /* Destroy the session related resources like session parameters */
789  (void) session_state_uninit (session_p);
790 
791  // delete from hash
792  if (!sessions.states_hashmap.erase_locked (thread_p, key_id, session_p))
793  {
794  /* we don't have clear operations on this hash table, this shouldn't happen */
795  pthread_mutex_unlock (&session_p->mutex);
796  assert_release (false);
797  return ER_FAILED;
798  }
799 
800  return error;
801 }
802 
803 /*
804  * session_check_session () - check if the session state with id
805  * exists and update the timeout for it
806  * return : NO_ERROR or error code
807  * id(in) : the identifier for the session
808  */
809 int
811 {
812  SESSION_STATE *session_p = NULL;
813  int error = NO_ERROR;
814 
815 #if defined (SESSION_DEBUG)
816  er_log_debug (ARG_FILE_LINE, "updating timeout for session_id %u\n", id);
817 #endif /* SESSION_DEBUG */
818 
819 #if defined (SERVER_MODE)
820  if (thread_p && thread_p->conn_entry && thread_p->conn_entry->session_p)
821  {
822  SESSION_ID old_id = thread_p->conn_entry->session_id;
823 
824  assert (thread_p->conn_entry->session_p->id == old_id);
825 
826  session_p = sessions.states_hashmap.find (thread_p, old_id);
827  if (session_p == NULL)
828  {
829  /* the session in connection entry no longer exists... */
830  /* todo: add safe guard if we cannot accept this case */
831  thread_p->conn_entry->session_id = DB_EMPTY_SESSION;
832  thread_p->conn_entry->session_p = NULL;
833 
834  return ER_FAILED;
835  }
836 
837  assert (session_p == thread_p->conn_entry->session_p);
838 
839 #if !defined(NDEBUG)
840  session_state_verify_ref_count (thread_p, session_p);
841 #endif
842  thread_p->conn_entry->session_id = DB_EMPTY_SESSION;
843  thread_p->conn_entry->session_p = NULL;
844  session_state_decrease_ref_count (thread_p, session_p);
845 
846  logtb_set_current_user_active (thread_p, false);
847  pthread_mutex_unlock (&session_p->mutex);
848  }
849 #endif
850 
851  SESSION_ID key_id = id;
852  session_p = sessions.states_hashmap.find (thread_p, key_id);
853  if (session_p == NULL)
854  {
856  return ER_SES_SESSION_EXPIRED;
857  }
858 
859  /* update session active time */
860  session_p->active_time = time (NULL);
861 
862 #if defined (SERVER_MODE)
863 #if !defined (NDEBUG)
864  (void) session_state_verify_ref_count (thread_p, session_p);
865 #endif
866  /* increase reference count of new session_p */
867  session_state_increase_ref_count (thread_p, session_p);
868  session_set_conn_entry_data (thread_p, session_p);
869 
870  logtb_set_current_user_active (thread_p, true);
871 #endif
872 
873  /* done with the entry */
874  pthread_mutex_unlock (&session_p->mutex);
875 
876  return error;
877 }
878 
879 /*
880  * session_remove_expired_sessions () - remove expired sessions
881  * return : NO_ERROR or error code
882  */
883 static int
885 {
886 #define EXPIRED_SESSION_BUFFER_SIZE 1024
887  session_hashmap_iterator it = { thread_p, sessions.states_hashmap };
888  SESSION_STATE *state = NULL;
889  int err = NO_ERROR, success = 0;
890  bool is_expired = false;
892  SESSION_ID expired_sid_buffer[EXPIRED_SESSION_BUFFER_SIZE];
893  int n_expired_sids = 0;
894  int sid_index;
895  bool finished = false;
896 
897  active_sessions.count = -1;
898  active_sessions.session_ids = NULL;
899 
900  /* Loop until all expired sessions are removed.
901  * NOTE: We cannot call lf_hash_delete while iterating... lf_hash_delete may have to retry, which also resets the
902  * lock-free transaction. And resetting lock-free transaction can break our iterator.
903  */
904  while (!finished)
905  {
906  it.restart ();
907  while (true)
908  {
909  state = it.iterate ();
910  if (state == NULL)
911  {
912  finished = true;
913  break;
914  }
915 
916  /* iterate next. the mutex lock of the current state will be released */
917  if (session_check_timeout (state, &active_sessions, &is_expired) != NO_ERROR)
918  {
919  pthread_mutex_unlock (&state->mutex);
920  sessions.states_hashmap.end_tran (thread_p);
921  err = ER_FAILED;
922  goto exit_on_end;
923  }
924 
925  if (is_expired)
926  {
927  expired_sid_buffer[n_expired_sids++] = state->id;
928  if (n_expired_sids == EXPIRED_SESSION_BUFFER_SIZE)
929  {
930  /* No more room in buffer */
931 
932  /* Interrupt iteration. */
933  /* Free current entry mutex. */
934  pthread_mutex_unlock (&state->mutex);
935  /* End lock-free transaction started by iterator. */
936  sessions.states_hashmap.end_tran (thread_p);
937  break;
938  }
939  }
940  }
941 
942  /* Remove expired sessions. */
943  for (sid_index = 0; sid_index < n_expired_sids; sid_index++)
944  {
945  if (!sessions.states_hashmap.erase (thread_p, expired_sid_buffer[sid_index]))
946  {
947  /* we don't have clear operations on this hash table, this shouldn't happen */
948  assert_release (false);
949  err = ER_FAILED;
950  goto exit_on_end;
951  }
952  }
953  n_expired_sids = 0;
954  }
955 
956 exit_on_end:
957  if (active_sessions.session_ids != NULL)
958  {
959  assert (active_sessions.count > 0);
960  free_and_init (active_sessions.session_ids);
961  }
962 
963  return err;
964 
965 #undef EXPIRED_SESSION_BUFFER_SIZE
966 }
967 
968 /*
969  * session_check_timeout () - verify if a session timeout expired
970  * return : NO_ERROR or error code
971  * session_p(in) : session id
972  * active_sessions(in) : array of the active sessions info
973  * remove(out) : true if session timeout expired and it doesn't have an active connection, false otherwise
974  */
975 static int
977 {
978  int err = NO_ERROR;
979  time_t curr_time = time (NULL);
980 
981  (*remove) = false;
982 
983  if ((curr_time - session_p->active_time) >= prm_get_integer_value (PRM_ID_SESSION_STATE_TIMEOUT))
984  {
985 #if defined (SERVER_MODE)
986  int i;
987 
988  /* first see if we still have an active connection */
989  if (active_sessions->count == -1)
990  {
991  /* we need to get the active connection list */
992  err = css_get_session_ids_for_active_connections (&active_sessions->session_ids, &active_sessions->count);
993  if (err != NO_ERROR)
994  {
995  return err;
996  }
997  }
998  for (i = 0; i < active_sessions->count; i++)
999  {
1000  if (active_sessions->session_ids[i] == session_p->id)
1001  {
1002  /* also update session active time */
1003  session_p->active_time = time (NULL);
1004  return err;
1005  }
1006  }
1007 #endif
1008  /* remove this session: timeout expired and it doesn't have an active connection. */
1009 #if defined (SESSION_DEBUG)
1010  er_log_debug (ARG_FILE_LINE, "timeout expired for session %u\n", session_p->id);
1011 #endif /* SESSION_DEBUG */
1012 
1013  (*remove) = true;
1014  }
1015  else
1016  {
1017 #if defined (SESSION_DEBUG)
1018  er_log_debug (ARG_FILE_LINE, "timeout ok for session %u\n", session_p->id);
1019 #endif /* SESSION_DEBUG */
1020  }
1021 
1022  return err;
1023 }
1024 
1025 /*
1026  * free_session_variable () - free memory allocated for a session variable
1027  * return : void
1028  * var (in) : session variable
1029  */
1030 static void
1032 {
1033  if (var == NULL)
1034  {
1035  return;
1036  }
1037 
1038  if (var->name != NULL)
1039  {
1040  free_and_init (var->name);
1041  }
1042 
1043  if (var->value != NULL)
1044  {
1046  {
1047  /* free allocated string */
1048  free_and_init (var->value->data.ch.medium.buf);
1049  }
1050  free_and_init (var->value);
1051  }
1052 
1053  free_and_init (var);
1054 }
1055 
1056 /*
1057  * session_add_variable () - add a session variable to the list
1058  * return: error code
1059  * state_p (in) : session state object
1060  * name (in) : name of the variable
1061  * value (in) : variable value
1062  */
1063 static int
1064 session_add_variable (SESSION_STATE * state_p, const DB_VALUE * name, DB_VALUE * value)
1065 {
1066  SESSION_VARIABLE *var = NULL;
1067  SESSION_VARIABLE *current = NULL;
1068  int count = 0;
1069  size_t len;
1070  const char *name_str;
1071 
1073 
1074  name_str = db_get_string (name);
1075 
1076  assert (name_str != NULL);
1077 
1078  len = db_get_string_size (name);
1079  len = MAX (len, strlen ("collect_exec_stats"));
1080 
1081  if (strncasecmp (name_str, "collect_exec_stats", len) == 0)
1082  {
1083  if (db_get_int (value) == 1)
1084  {
1085  perfmon_start_watch (NULL);
1086  }
1087  else if (db_get_int (value) == 0)
1088  {
1089  perfmon_stop_watch (NULL);
1090  }
1091  }
1092  else if (strncasecmp (name_str, "trace_plan", 10) == 0)
1093  {
1094  if (state_p->plan_string != NULL)
1095  {
1096  free_and_init (state_p->plan_string);
1097  }
1098 
1099  state_p->plan_string = strdup (db_get_string (value));
1100  }
1101 
1102  current = state_p->session_variables;
1103  while (current)
1104  {
1105  assert (current->name != NULL);
1106 
1107  if (intl_identifier_casecmp (name_str, current->name) == 0)
1108  {
1109  /* if it already exists, just update the value */
1110  update_session_variable (current, value);
1111  return NO_ERROR;
1112  }
1113 
1114  current = current->next;
1115  count++;
1116  }
1117 
1118  if (count >= MAX_SESSION_VARIABLES_COUNT)
1119  {
1121  return ER_FAILED;
1122  }
1123 
1124  /* create a new session variable and add it to the list */
1125  var = (SESSION_VARIABLE *) malloc (sizeof (SESSION_VARIABLE));
1126  if (var == NULL)
1127  {
1129  return ER_FAILED;
1130  }
1131 
1132  len = db_get_string_size (name);
1133  var->name = (char *) malloc (len + 1);
1134  if (var->name == NULL)
1135  {
1137  goto error;
1138  }
1139 
1140  memcpy (var->name, name_str, len);
1141  var->name[len] = 0;
1142 
1143  var->value = db_value_alloc_and_copy (value);
1144 
1145  /* add new variable to the beginning of the list */
1146  var->next = state_p->session_variables;
1147  state_p->session_variables = var;
1148 
1149  return NO_ERROR;
1150 
1151 error:
1152  if (var != NULL)
1153  {
1154  if (var->name)
1155  {
1156  free_and_init (var->name);
1157  }
1158 
1159  pr_clear_value (var->value);
1160  free_and_init (var);
1161  }
1162 
1163  return ER_FAILED;
1164 }
1165 
1166 /*
1167  * db_value_alloc_and_copy () - create a DB_VALUE on the heap
1168  * return : DB_VALUE or NULL
1169  * src (in) : value to copy
1170  */
1171 static DB_VALUE *
1173 {
1174  DB_TYPE src_dbtype;
1175  TP_DOMAIN *domain = NULL;
1176  DB_VALUE *dest = NULL;
1177  DB_VALUE conv;
1178  int length = 0, precision = 0, scale = 0;
1179  char *str = NULL;
1180  const char *src_str;
1181 
1182  dest = (DB_VALUE *) malloc (sizeof (DB_VALUE));
1183  if (dest == NULL)
1184  {
1186  return NULL;
1187  }
1188 
1189  src_dbtype = DB_VALUE_DOMAIN_TYPE (src);
1190  if (DB_IS_NULL (src))
1191  {
1192  db_make_null (dest);
1193  return dest;
1194  }
1195 
1196  if (TP_IS_NUMERIC_TYPE (src_dbtype))
1197  {
1198  pr_clone_value ((DB_VALUE *) src, dest);
1199  return dest;
1200  }
1201 
1202  if (!QSTR_IS_ANY_CHAR_OR_BIT (src_dbtype))
1203  {
1204  /* attempt to convert to varchar */
1205  db_make_null (&conv);
1208 
1209  if (tp_value_cast (src, &conv, domain, false) != DOMAIN_COMPATIBLE)
1210  {
1211  db_make_null (dest);
1212  return dest;
1213  }
1214 
1215  src_dbtype = DB_TYPE_VARCHAR;
1216  free_and_init (dest);
1217  dest = db_value_alloc_and_copy (&conv);
1218  pr_clear_value (&conv);
1219 
1220  return dest;
1221  }
1222 
1223  length = db_get_string_size (src);
1224  scale = 0;
1225  str = (char *) malloc (length + 1);
1226  if (str == NULL)
1227  {
1228  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) (length + 1));
1229  return NULL;
1230  }
1231 
1232  src_str = db_get_string (src);
1233  if (src_str != NULL)
1234  {
1235  memcpy (str, src_str, length);
1236  }
1237 
1238  precision = db_value_precision (src);
1239  db_value_domain_init (dest, src_dbtype, precision, scale);
1240  dest->need_clear = true;
1241  switch (src_dbtype)
1242  {
1243  case DB_TYPE_CHAR:
1244  db_make_char (dest, precision, str, length, db_get_string_codeset (src), db_get_string_collation (src));
1245  break;
1246  case DB_TYPE_NCHAR:
1247  db_make_nchar (dest, precision, str, length, db_get_string_codeset (src), db_get_string_collation (src));
1248  break;
1249  case DB_TYPE_VARCHAR:
1250  db_make_varchar (dest, precision, str, length, db_get_string_codeset (src), db_get_string_collation (src));
1251  break;
1252  case DB_TYPE_VARNCHAR:
1253  db_make_varnchar (dest, precision, str, length, db_get_string_codeset (src), db_get_string_collation (src));
1254  break;
1255  case DB_TYPE_BIT:
1256  db_make_bit (dest, precision, str, length);
1257  break;
1258  case DB_TYPE_VARBIT:
1259  db_make_varbit (dest, precision, str, length);
1260  break;
1261  default:
1262  assert (false);
1263  return NULL;
1264  }
1265 
1266  return dest;
1267 }
1268 
1269 /*
1270  * update_session_variable () - update the value of a session variable
1271  * return : void
1272  * var (in/out) : the variable to update
1273  * new_value (in) : the new value
1274  */
1275 static void
1277 {
1278  if (var->value != NULL)
1279  {
1281  {
1282  /* free allocated string */
1283  free_and_init (var->value->data.ch.medium.buf);
1284  }
1285  free_and_init (var->value);
1286  }
1287 
1288  var->value = db_value_alloc_and_copy (new_value);
1289 }
1290 
1291 /*
1292  * session_drop_variable () - drop a session variable from the list
1293  * return: error code
1294  * state_p (in) : session state object
1295  * name (in) : name of the variable
1296  */
1297 static int
1299 {
1300  SESSION_VARIABLE *current = NULL, *prev = NULL;
1301  const char *name_str;
1302 
1303  if (state_p->session_variables == NULL)
1304  {
1305  return NO_ERROR;
1306  }
1307 
1309  name_str = db_get_string (name);
1310 
1311  assert (name_str != NULL);
1312 
1313  current = state_p->session_variables;
1314  while (current)
1315  {
1316  assert (current->name != NULL);
1317 
1318  if (intl_identifier_casecmp (name_str, current->name) == 0)
1319  {
1320  SESSION_VARIABLE *next = current->next;
1321  free_session_variable (current);
1322  if (prev == NULL)
1323  {
1324  state_p->session_variables = next;
1325  }
1326  else
1327  {
1328  prev->next = next;
1329  }
1330  return NO_ERROR;
1331  }
1332 
1333  prev = current;
1334  current = current->next;
1335  }
1336 
1337  return NO_ERROR;
1338 }
1339 
1340 /*
1341  * session_get_session_id () - get the session id associated with a thread
1342  * return : NO_ERROR or error code
1343  * thread_p (in) : thread for which to get the session id
1344  * session_id(out): session_id
1345  */
1346 int
1348 {
1349  assert (id != NULL);
1350 
1351 #if !defined(SERVER_MODE)
1352  *id = db_Session_id;
1353 
1354  return NO_ERROR;
1355 #else
1356  if (thread_p == NULL)
1357  {
1358  return ER_FAILED;
1359  }
1360 
1361  if (thread_p->conn_entry == NULL)
1362  {
1363  return ER_FAILED;
1364  }
1365 
1366  *id = thread_p->conn_entry->session_id;
1367 
1368  return NO_ERROR;
1369 #endif /* SERVER_MODE */
1370 }
1371 
1372 /*
1373  * session_get_last_insert_id () - get the value of the last inserted id
1374  * in the session associated with a thread
1375  * return : NO_ERROR or error code
1376  * thread_p (in) : thread that identifies the session
1377  * value (out) : pointer into which to store the last insert id value
1378  * update_last_insert_id(in): whether update the last insert id
1379  */
1380 int
1381 session_get_last_insert_id (THREAD_ENTRY * thread_p, DB_VALUE * value, bool update_last_insert_id)
1382 {
1383  SESSION_STATE *state_p = NULL;
1384 
1385  assert (value != NULL);
1386  state_p = session_get_session_state (thread_p);
1387  if (state_p == NULL)
1388  {
1389  return ER_FAILED;
1390  }
1391  if (update_last_insert_id && !state_p->is_trigger_involved && !DB_IS_NULL (&state_p->cur_insert_id))
1392  {
1393  pr_clone_value (&state_p->cur_insert_id, &state_p->last_insert_id);
1394  pr_clear_value (&state_p->cur_insert_id);
1395  }
1396  pr_clone_value (&state_p->last_insert_id, value);
1397 
1398  return NO_ERROR;
1399 }
1400 
1401 /*
1402  * session_set_cur_insert_id () - set the value of the current inserted id
1403  * in the session associated with a thread
1404  * return : NO_ERROR or error code
1405  * thread_p (in) : thread that identifies the session
1406  * value (in) : the value of the last inserted id
1407  * force (in) : update the value unconditionally
1408  *
1409  * Note: Even though we allow other data types for serial columns, the session
1410  * keeps the value of the last insert id as a DB_TYPE_NUMERIC. This function
1411  * performs a coercion here if needed.
1412  */
1413 int
1414 session_set_cur_insert_id (THREAD_ENTRY * thread_p, const DB_VALUE * value, bool force)
1415 {
1416  SESSION_STATE *state_p = NULL;
1417  bool need_coercion = false;
1418 
1419  if (DB_VALUE_TYPE (value) != DB_TYPE_NUMERIC)
1420  {
1421  need_coercion = true;
1422  }
1423  else if (DB_VALUE_PRECISION (value) != DB_MAX_NUMERIC_PRECISION || DB_VALUE_SCALE (value) != 0)
1424  {
1425  need_coercion = true;
1426  }
1427 
1428  state_p = session_get_session_state (thread_p);
1429  if (state_p == NULL)
1430  {
1431  return ER_FAILED;
1432  }
1433 
1434  if ((force == false && state_p->is_last_insert_id_generated == true) || state_p->is_trigger_involved == true)
1435  {
1436  return NO_ERROR;
1437  }
1438 
1439  if (!DB_IS_NULL (&state_p->cur_insert_id))
1440  {
1441  pr_clone_value (&state_p->cur_insert_id, &state_p->last_insert_id);
1442  pr_clear_value (&state_p->cur_insert_id);
1443  }
1444 
1445  if (!need_coercion)
1446  {
1447  pr_clone_value ((DB_VALUE *) value, &state_p->cur_insert_id);
1448  }
1449  else
1450  {
1453  num->scale = 0;
1454  if (tp_value_cast (value, &state_p->cur_insert_id, num, false) != DOMAIN_COMPATIBLE)
1455  {
1456  pr_clear_value (&state_p->cur_insert_id);
1457  return ER_FAILED;
1458  }
1459  }
1460 
1461  state_p->is_last_insert_id_generated = true;
1462 
1463  return NO_ERROR;
1464 }
1465 
1466 /*
1467  * session_reset_cur_insert_id () - reset the current insert_id as NULL
1468  * when the insert fail.
1469  * return : NO_ERROR or error code
1470  * thread_p (in) : thread that identifies the session
1471  */
1472 int
1474 {
1475  SESSION_STATE *state_p = NULL;
1476 
1477  state_p = session_get_session_state (thread_p);
1478  if (state_p == NULL)
1479  {
1480  return ER_FAILED;
1481  }
1482 
1483  if (state_p->is_trigger_involved)
1484  {
1485  return NO_ERROR;
1486  }
1487 
1488  if (state_p->is_last_insert_id_generated == false)
1489  {
1490  return NO_ERROR;
1491  }
1492 
1493  pr_clear_value (&state_p->cur_insert_id);
1494  state_p->is_last_insert_id_generated = false;
1495 
1496  return NO_ERROR;
1497 }
1498 
1499 /*
1500  * session_begin_insert_values () - set is_last_insert_id_generated to false
1501  * in the session associated with a thread
1502  * return : NO_ERROR or error code
1503  * thread_p (in) : thread that identifies the session
1504  */
1505 int
1507 {
1508  SESSION_STATE *state_p = NULL;
1509 
1510  state_p = session_get_session_state (thread_p);
1511  if (state_p == NULL)
1512  {
1513  return ER_FAILED;
1514  }
1515 
1516  if (state_p->is_trigger_involved)
1517  {
1518  return NO_ERROR;
1519  }
1520 
1521  state_p->is_last_insert_id_generated = false;
1522 
1523  return NO_ERROR;
1524 }
1525 
1526 /*
1527  * session_set_trigger_state () - set is_trigger_involved
1528  *
1529  * return : NO_ERROR or error code
1530  * thread_p (in) : thread that identifies the session
1531  * in_trigger(in):
1532  */
1533 int
1534 session_set_trigger_state (THREAD_ENTRY * thread_p, bool in_trigger)
1535 {
1536  SESSION_STATE *state_p = NULL;
1537 
1538  state_p = session_get_session_state (thread_p);
1539  if (state_p == NULL)
1540  {
1541  return ER_FAILED;
1542  }
1543 
1544  state_p->is_trigger_involved = in_trigger;
1545 
1546  return NO_ERROR;
1547 }
1548 
1549 
1550 
1551 /*
1552  * session_get_row_count () - get the affected row count from the session
1553  * associated with a thread
1554  * return : NO_ERROR or error code
1555  * thread_p(in) : thread that identifies the session
1556  * row_count(out) : pointer into which to store the count
1557  *
1558  * Note: Row count refers to the number of rows affected by the last INSERT,
1559  * UPDATE or DELETE statement
1560  */
1561 int
1562 session_get_row_count (THREAD_ENTRY * thread_p, int *row_count)
1563 {
1564  SESSION_STATE *state_p = NULL;
1565 
1566  assert (row_count != NULL);
1567  state_p = session_get_session_state (thread_p);
1568  if (state_p == NULL)
1569  {
1570  return ER_FAILED;
1571  }
1572 
1573  *row_count = state_p->row_count;
1574 
1575  return NO_ERROR;
1576 }
1577 
1578 /*
1579  * session_set_row_count () - set the count of affected rows for a session
1580  *
1581  * return : NO_ERROR or error code
1582  * thread_p(in) : thread that identifies the session
1583  * row_count(in) : row count
1584  */
1585 int
1586 session_set_row_count (THREAD_ENTRY * thread_p, const int row_count)
1587 {
1588  SESSION_STATE *state_p = NULL;
1589  state_p = session_get_session_state (thread_p);
1590  if (state_p == NULL)
1591  {
1592  return ER_FAILED;
1593  }
1594 
1595 #if 0
1596  er_log_debug (ARG_FILE_LINE, "setting row_count for session %u to %d\n", state_p->id, state_p->row_count);
1597 #endif
1598 
1599  state_p->row_count = row_count;
1600 
1601  return NO_ERROR;
1602 }
1603 
1604 /*
1605  * session_get_session_params () - get the list of session parameters stored
1606  * in session_state
1607  *
1608  * return : NO_ERROR or error code
1609  * thread_p(in) : thread that identifies the session
1610  * session_parameters_ptr(out) : pointer to session parameter list
1611  */
1612 int
1613 session_get_session_parameters (THREAD_ENTRY * thread_p, SESSION_PARAM ** session_parameters_ptr)
1614 {
1615  SESSION_STATE *state_p = NULL;
1616 
1617  assert (session_parameters_ptr != NULL);
1618  if (*session_parameters_ptr)
1619  {
1620  free_and_init (*session_parameters_ptr);
1621  }
1622  state_p = session_get_session_state (thread_p);
1623  if (state_p == NULL)
1624  {
1625  return ER_FAILED;
1626  }
1627 
1628  *session_parameters_ptr = state_p->session_parameters;
1629 
1630  return NO_ERROR;
1631 }
1632 
1633 /*
1634  * session_set_session_parameters () - set session parameters to session state
1635  *
1636  * return : error code
1637  * thread_p (in) : worker thread
1638  * session_parameters (in) : array of session parameters
1639  */
1640 int
1642 {
1643  SESSION_STATE *state_p = NULL;
1644 
1645  assert (session_parameters != NULL);
1646  state_p = session_get_session_state (thread_p);
1647  if (state_p == NULL)
1648  {
1649  return ER_FAILED;
1650  }
1651 
1652  state_p->session_parameters = session_parameters;
1653 
1654  return NO_ERROR;
1655 }
1656 
1657 /*
1658  * session_create_prepared_statement () - create a prepared statement and add
1659  * it to the prepared statements list
1660  * return : NO_ERROR or error code
1661  * thread_p (in) : thread entry
1662  * name (in) : the name of the statement
1663  * alias_print (in) : the printed compiled statement
1664  * sha1 (in) : sha1 hash for printed compiled statement
1665  * info (in) : serialized prepared statement info
1666  * info_len (in) : serialized buffer length
1667  *
1668  * Note: This function assumes that the memory for its arguments was
1669  * dynamically allocated and does not copy the values received. It's important
1670  * that the caller never frees this memory. If an error occurs, this function
1671  * will free the memory allocated for its arguments.
1672  */
1673 int
1674 session_create_prepared_statement (THREAD_ENTRY * thread_p, char *name, char *alias_print, SHA1Hash * sha1, char *info,
1675  int info_len)
1676 {
1677  SESSION_STATE *state_p = NULL;
1678  PREPARED_STATEMENT *stmt_p = NULL;
1679  int err = NO_ERROR;
1680 
1681  stmt_p = (PREPARED_STATEMENT *) malloc (sizeof (PREPARED_STATEMENT));
1682  if (stmt_p == NULL)
1683  {
1685  err = ER_FAILED;
1686  goto error;
1687  }
1688 
1689  stmt_p->name = name;
1690  stmt_p->alias_print = alias_print;
1691  stmt_p->sha1 = *sha1;
1692  stmt_p->info_length = info_len;
1693  stmt_p->info = info;
1694  stmt_p->next = NULL;
1695 
1696  state_p = session_get_session_state (thread_p);
1697  if (state_p == NULL)
1698  {
1699  err = ER_FAILED;
1700  goto error;
1701  }
1702 
1703 #if defined (SESSION_DEBUG)
1704  er_log_debug (ARG_FILE_LINE, "create statement %s(%d)\n", name, state_p->id);
1705 #endif /* SESSION_DEBUG */
1706 
1707  if (state_p->statements == NULL)
1708  {
1709  state_p->statements = stmt_p;
1710  }
1711  else
1712  {
1713  /* find and remove prepared statements with the same name */
1714  int cnt = 0;
1715  PREPARED_STATEMENT *current = NULL, *prev = NULL;
1716 
1717  current = state_p->statements;
1718  while (current != NULL)
1719  {
1720  if (intl_identifier_casecmp (current->name, name) == 0)
1721  {
1722  /* we need to remove it */
1723  if (prev == NULL)
1724  {
1725  state_p->statements = current->next;
1726  }
1727  else
1728  {
1729  prev->next = current->next;
1730  }
1731  current->next = NULL;
1733  break;
1734  }
1735  cnt++;
1736  prev = current;
1737  current = current->next;
1738  }
1739 
1740  if (cnt >= MAX_PREPARED_STATEMENTS_COUNT)
1741  {
1743  err = ER_FAILED;
1744  goto error;
1745  }
1746  else if (state_p->statements == NULL)
1747  {
1748  /* add the new statement at the beginning of the list */
1749  state_p->statements = stmt_p;
1750  }
1751  else
1752  {
1753  stmt_p->next = state_p->statements;
1754  state_p->statements = stmt_p;
1755  }
1756  }
1757 
1758 #if defined (SESSION_DEBUG)
1759  er_log_debug (ARG_FILE_LINE, "success %s(%d)\n", name, state_p->id);
1760 #endif /* SESSION_DEBUG */
1761 
1762  return NO_ERROR;
1763 
1764 error:
1765  if (stmt_p != NULL)
1766  {
1767  free_and_init (stmt_p);
1768  }
1769 
1770  return err;
1771 }
1772 
1773 /*
1774  * session_get_prepared_statement () - get available information about a prepared statement
1775  * return: NO_ERROR or error code
1776  * thread_p (in) :
1777  * name (in) : the name of the prepared statement
1778  * info (out) : serialized prepared statement information
1779  * info_len (out) : serialized buffer length
1780  * xasl_id (out) : XASL ID for this statement
1781  *
1782  * Note: This function allocates memory for query, columns and parameters using db_private_alloc. This memory must be
1783  * freed by the caller by using db_private_free.
1784  */
1785 int
1786 session_get_prepared_statement (THREAD_ENTRY * thread_p, const char *name, char **info, int *info_len,
1787  xasl_cache_ent ** xasl_entry)
1788 {
1789  SESSION_STATE *state_p = NULL;
1790  PREPARED_STATEMENT *stmt_p = NULL;
1791  int err = NO_ERROR;
1792  const char *alias_print;
1793  char *data = NULL;
1794 
1795  assert (xasl_entry != NULL);
1796  state_p = session_get_session_state (thread_p);
1797  if (state_p == NULL)
1798  {
1799  return ER_FAILED;
1800  }
1801  for (stmt_p = state_p->statements; stmt_p != NULL; stmt_p = stmt_p->next)
1802  {
1803  if (intl_identifier_casecmp (stmt_p->name, name) == 0)
1804  {
1805  break;
1806  }
1807  }
1808 
1809  if (stmt_p == NULL)
1810  {
1811  /* prepared statement not found */
1813  return ER_FAILED;
1814  }
1815 
1816  /* alias_print */
1817  alias_print = stmt_p->alias_print;
1818  *info_len = stmt_p->info_length;
1819 
1820  if (stmt_p->info_length == 0)
1821  {
1822  *info = NULL;
1823  }
1824  else
1825  {
1826  data = (char *) malloc (stmt_p->info_length);
1827  if (data == NULL)
1828  {
1830  return ER_FAILED;
1831  }
1832  memcpy (data, stmt_p->info, stmt_p->info_length);
1833  *info = data;
1834  }
1835 
1836  /* since the xasl id is not session specific, we can fetch it outside of the session critical section */
1837  if (alias_print == NULL)
1838  {
1839  /* if we don't have an alias print, we do not search for the XASL entry */
1840  *xasl_entry = NULL;
1841 #if defined (SESSION_DEBUG)
1842  er_log_debug (ARG_FILE_LINE, "found null xasl_id for %s(%d)\n", name, state_p->id);
1843 #endif /* SESSION_DEBUG */
1844  return NO_ERROR;
1845  }
1846 
1847  *xasl_entry = NULL;
1848  err = xcache_find_sha1 (thread_p, &stmt_p->sha1, XASL_CACHE_SEARCH_GENERIC, xasl_entry, NULL);
1849  if (err != NO_ERROR)
1850  {
1851  ASSERT_ERROR ();
1852  return err;
1853  }
1854 
1855  return NO_ERROR;
1856 }
1857 
1858 /*
1859  * session_delete_prepared_statement () - delete a prepared statement
1860  * return : error code or NO_ERROR
1861  * thread_p (in) :
1862  * name (in) : name of the prepared statement
1863  */
1864 int
1865 session_delete_prepared_statement (THREAD_ENTRY * thread_p, const char *name)
1866 {
1867  SESSION_STATE *state_p = NULL;
1868  PREPARED_STATEMENT *stmt_p = NULL, *prev = NULL;
1869  bool found = false;
1870 
1871  state_p = session_get_session_state (thread_p);
1872  if (state_p == NULL)
1873  {
1874  return ER_FAILED;
1875  }
1876 
1877 #if defined (SESSION_DEBUG)
1878  er_log_debug (ARG_FILE_LINE, "dropping %s from session_id %d\n", name, state_p->id);
1879 #endif /* SESSION_DEBUG */
1880 
1881  for (stmt_p = state_p->statements, prev = NULL; stmt_p != NULL; prev = stmt_p, stmt_p = stmt_p->next)
1882  {
1883  if (intl_identifier_casecmp (stmt_p->name, name) == 0)
1884  {
1885  if (prev == NULL)
1886  {
1887  state_p->statements = stmt_p->next;
1888  }
1889  else
1890  {
1891  prev->next = stmt_p->next;
1892  }
1893  stmt_p->next = NULL;
1895  found = true;
1896  break;
1897  }
1898  }
1899 
1900  if (!found)
1901  {
1902  /* prepared statement not found */
1904  return ER_FAILED;
1905  }
1906 
1907  return NO_ERROR;
1908 }
1909 
1910 /*
1911  * login_user () - login user
1912  * return : error code
1913  * thread_p : worker thread
1914  * username(in) : name of the user
1915  */
1916 int
1917 login_user (THREAD_ENTRY * thread_p, const char *username)
1918 {
1919  int tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1920  LOG_TDES *tdes = NULL;
1921 
1922  tdes = LOG_FIND_TDES (tran_index);
1923  if (tdes != NULL)
1924  {
1925  tdes->client.set_user (username);
1926  }
1927 
1928  return NO_ERROR;
1929 }
1930 
1931 /*
1932  * session_set_session_variables () - set session variables
1933  * return : error code
1934  * thread_p (in) : worker thread
1935  * values (in) : array of variables to set
1936  * count (in) : number of elements in array
1937  */
1938 int
1940 {
1941  SESSION_STATE *state_p = NULL;
1942  int i = 0;
1943 
1944  assert (count % 2 == 0);
1945  state_p = session_get_session_state (thread_p);
1946  if (state_p == NULL)
1947  {
1948  return ER_FAILED;
1949  }
1950 
1951  for (i = 0; i < count; i += 2)
1952  {
1953  if (session_add_variable (state_p, &values[i], &values[i + 1]) != NO_ERROR)
1954  {
1955  return ER_FAILED;
1956  }
1957  }
1958 
1959  return NO_ERROR;
1960 }
1961 
1962 /*
1963  * session_define_variable () - define a session variable
1964  * return : int
1965  * thread_p (in) : worker thread
1966  * name (in) : name of the variable
1967  * value (in) : variable value
1968  */
1969 int
1970 session_define_variable (THREAD_ENTRY * thread_p, DB_VALUE * name, DB_VALUE * value, DB_VALUE * result)
1971 {
1972  SESSION_STATE *state_p = NULL;
1973  int err = NO_ERROR;
1974 
1976  state_p = session_get_session_state (thread_p);
1977  if (state_p == NULL)
1978  {
1979  return ER_FAILED;
1980  }
1981 
1982  err = session_add_variable (state_p, name, value);
1983  if (err == NO_ERROR)
1984  {
1985  pr_clone_value (value, result);
1986  }
1987  else
1988  {
1989  db_make_null (result);
1990  }
1991 
1992  return err;
1993 }
1994 
1995 /*
1996  * session_get_variable () - get the value of a variable
1997  * return : error code
1998  * thread_p (in) : worker thread
1999  * name (in) : name of the variable
2000  * result (out) : variable value
2001  */
2002 int
2003 session_get_variable (THREAD_ENTRY * thread_p, const DB_VALUE * name, DB_VALUE * result)
2004 {
2005  SESSION_STATE *state_p = NULL;
2006  const char *name_str;
2007  SESSION_VARIABLE *var;
2008 
2010 
2011  name_str = db_get_string (name);
2012  assert (name_str != NULL);
2013  state_p = session_get_session_state (thread_p);
2014  if (state_p == NULL)
2015  {
2016  return ER_FAILED;
2017  }
2018 
2019  var = state_p->session_variables;
2020  while (var != NULL)
2021  {
2022  assert (var->name != NULL);
2023 
2024  if (intl_identifier_casecmp (var->name, name_str) == 0)
2025  {
2026  pr_clone_value (var->value, result);
2027  break;
2028  }
2029  var = var->next;
2030  }
2031 
2032  if (var == NULL)
2033  {
2034  /* we didn't find it, set error and exit */
2035  char *var_name = NULL;
2036  size_t name_len = strlen (name_str);
2037 
2038  var_name = (char *) malloc (name_len + 1);
2039  if (var_name != NULL)
2040  {
2041  memcpy (var_name, name_str, name_len);
2042  var_name[name_len] = 0;
2043  }
2045 
2046  if (var_name != NULL)
2047  {
2048  free_and_init (var_name);
2049  }
2050 
2051  return ER_FAILED;
2052  }
2053 
2054  return NO_ERROR;
2055 }
2056 
2057 /*
2058  * session_get_session_variable_no_copy () - get the value of a session
2059  * variable
2060  * return : int
2061  * thread_p (in) : worker thread
2062  * name (in) : name of the variable
2063  * value (in/out): variable value
2064  * Note: This function gets a reference to a session variable from the session
2065  * state object. Because it gets the actual pointer, it is not thread safe
2066  * and it should only be called in the stand alone mode
2067  */
2068 int
2069 session_get_variable_no_copy (THREAD_ENTRY * thread_p, const DB_VALUE * name, DB_VALUE ** result)
2070 {
2071  SESSION_ID id;
2072  SESSION_STATE *state_p = NULL;
2073  size_t name_len;
2074  const char *name_str;
2075  SESSION_VARIABLE *var;
2076 
2077 #if defined (SERVER_MODE)
2078  /* do not call this function in a multi-threaded context */
2079  assert (false);
2080  return ER_FAILED;
2081 #endif
2082 
2083  assert (name != NULL);
2085  assert (result != NULL);
2086 
2087  name_str = db_get_string (name);
2088  name_len = (name_str != NULL) ? strlen (name_str) : 0;
2089 
2090  if (session_get_session_id (thread_p, &id) != NO_ERROR)
2091  {
2092  return ER_FAILED;
2093  }
2094 
2095  state_p = sessions.states_hashmap.find (thread_p, id);
2096  if (state_p == NULL)
2097  {
2099  return ER_FAILED;
2100  }
2101 
2102  var = state_p->session_variables;
2103  while (var != NULL)
2104  {
2105  assert (var->name != NULL);
2106 
2107  if (name_len != strlen (var->name))
2108  {
2109  var = var->next;
2110  continue;
2111  }
2112  if (strncasecmp (var->name, name_str, name_len) == 0)
2113  {
2114  *result = var->value;
2115  break;
2116  }
2117  var = var->next;
2118  }
2119 
2120  if (var == NULL)
2121  {
2122  /* we didn't find it, set error and exit */
2123  char *var_name = NULL;
2124 
2125  var_name = (char *) malloc (name_len + 1);
2126  if (var_name != NULL)
2127  {
2128  memcpy (var_name, name_str, name_len);
2129  var_name[name_len] = 0;
2130  }
2131 
2133 
2134  if (var_name != NULL)
2135  {
2136  free_and_init (var_name);
2137  }
2138 
2139  pthread_mutex_unlock (&state_p->mutex);
2140  return ER_FAILED;
2141  }
2142 
2143  /* done with the entry */
2144  pthread_mutex_unlock (&state_p->mutex);
2145 
2146  return NO_ERROR;
2147 }
2148 
2149 /*
2150  * session_drop_session_variables () - drop session variables
2151  * return : error code
2152  * thread_p (in) : worker thread
2153  * values (in) : array of variables to drop
2154  * count (in) : number of elements in array
2155  */
2156 int
2158 {
2159  SESSION_STATE *state_p = NULL;
2160  int i = 0;
2161 
2162  state_p = session_get_session_state (thread_p);
2163  if (state_p == NULL)
2164  {
2165  return ER_FAILED;
2166  }
2167 
2168  for (i = 0; i < count; i++)
2169  {
2170  if (session_drop_variable (state_p, &values[i]) != NO_ERROR)
2171  {
2172  return ER_FAILED;
2173  }
2174  }
2175 
2176  return NO_ERROR;
2177 }
2178 
2179 /*
2180  * session_get_exec_stats_and_clear () - get execution statistics
2181  * return : error code
2182  * thread_p (in) : worker thread
2183  * name (in) : name of the stats
2184  * result (out) : stats value
2185  */
2186 int
2188 {
2189  const char *name_str;
2190  UINT64 stat_val;
2191 
2193 
2194  name_str = db_get_string (name);
2195 
2196  stat_val = perfmon_get_stats_and_clear (thread_p, name_str);
2197  db_make_bigint (result, stat_val);
2198 
2199  return NO_ERROR;
2200 }
2201 
2202 /*
2203  * session_states_dump () - dump the session states information
2204  * return: void
2205  * thread_p (in) : the thread executing this function
2206  */
2207 void
2209 {
2210  session_hashmap_iterator it = { thread_p, sessions.states_hashmap };
2211  SESSION_STATE *state;
2212  size_t session_count = sessions.states_hashmap.get_element_count ();
2213  fprintf (stdout, "\nSESSION COUNT = %zu\n", session_count);
2214 
2215  for (state = it.iterate (); state != NULL; state = it.iterate ())
2216  {
2217  session_dump_session (state);
2218  }
2219 
2220  fflush (stdout);
2221 }
2222 
2223 /*
2224  * session_dump_session () - dump a session state
2225  * return : NO_ERROR
2226  * key(in) : the key from the MHT_TABLE for this session
2227  * data(in): session state data
2228  * args(in): not used
2229  */
2230 static int
2232 {
2233  SESSION_VARIABLE *vcurent, *vnext;
2234  PREPARED_STATEMENT *pcurent, *pnext;
2235  DB_VALUE v;
2236 
2237  fprintf (stdout, "SESSION ID = %d\n", session->id);
2238 
2240  fprintf (stdout, "\tLAST_INSERT_ID = %s\n", db_get_string (&v));
2241  db_value_clear (&v);
2242 
2243  fprintf (stdout, "\tROW_COUNT = %d\n", session->row_count);
2244 
2245  fprintf (stdout, "\tAUTO_COMMIT = %d\n", session->auto_commit);
2246 
2247  fprintf (stdout, "\tSESSION VARIABLES\n");
2248  vcurent = session->session_variables;
2249  while (vcurent != NULL)
2250  {
2251  vnext = vcurent->next;
2252  session_dump_variable (vcurent);
2253  vcurent = vnext;
2254  }
2255 
2256  fprintf (stdout, "\tPREPRARE STATEMENTS\n");
2257  pcurent = session->statements;
2258  while (pcurent != NULL)
2259  {
2260  pnext = pcurent->next;
2262  pcurent = pnext;
2263  }
2264 
2265  fprintf (stdout, "\n");
2266  return NO_ERROR;
2267 }
2268 
2269 /*
2270  * session_dump_variable () - dump a session variable
2271  * return : void
2272  * var (in) : session variable
2273  */
2274 static void
2276 {
2277  DB_VALUE v;
2278 
2279  if (var == NULL)
2280  {
2281  return;
2282  }
2283 
2284  if (var->name != NULL)
2285  {
2286  fprintf (stdout, "\t\t%s = ", var->name);
2287  }
2288 
2289  if (var->value != NULL)
2290  {
2292  fprintf (stdout, "%s\n", db_get_string (&v));
2293  db_value_clear (&v);
2294  }
2295 }
2296 
2297 /*
2298  * session_dump_prepared_statement () - dump a prepared statement
2299  * return : void
2300  * stmt_p (in) : prepared statement object
2301  */
2302 static void
2304 {
2305  if (stmt_p == NULL)
2306  {
2307  return;
2308  }
2309 
2310  if (stmt_p->name != NULL)
2311  {
2312  fprintf (stdout, "\t\t%s = ", stmt_p->name);
2313  }
2314 
2315  if (stmt_p->alias_print != NULL)
2316  {
2317  fprintf (stdout, "%s\n", stmt_p->alias_print);
2318  fprintf (stdout, "sha1 = %08x | %08x | %08x | %08x | %08x\n", SHA1_AS_ARGS (&stmt_p->sha1));
2319  }
2320 }
2321 
2322 /*
2323  * qentry_to_sentry () - create a session query entry from a query manager
2324  * entry
2325  * return : session query entry or NULL
2326  * qentry_p (in) : query manager query entry
2327  */
2328 static SESSION_QUERY_ENTRY *
2330 {
2331  SESSION_QUERY_ENTRY *sqentry_p = NULL;
2332  assert (qentry_p != NULL);
2333  sqentry_p = (SESSION_QUERY_ENTRY *) malloc (sizeof (SESSION_QUERY_ENTRY));
2334  if (sqentry_p == NULL)
2335  {
2337  return NULL;
2338  }
2339  sqentry_p->query_id = qentry_p->query_id;
2340  sqentry_p->list_id = qentry_p->list_id;
2341  sqentry_p->temp_file = qentry_p->temp_vfid;
2342 
2343  qentry_p->list_id = NULL;
2344  qentry_p->temp_vfid = NULL;
2345 
2346  sqentry_p->num_tmp = qentry_p->num_tmp;
2347  sqentry_p->total_count = qentry_p->total_count;
2348  sqentry_p->query_flag = qentry_p->query_flag;
2349 
2350  sqentry_p->next = NULL;
2351 
2352  return sqentry_p;
2353 }
2354 
2355 /*
2356  * session_preserve_temporary_files () - remove list files used by qentry_p
2357  * from the file manager so that it
2358  * doesn't delete them at transaction
2359  * end
2360  * return : error code or NO_ERROR
2361  * thread_p (in) :
2362  * qentry_p (in) : query entry
2363  */
2364 static int
2366 {
2367  QMGR_TEMP_FILE *tfile_vfid_p = NULL, *temp = NULL;
2368 
2369  if (qentry_p == NULL)
2370  {
2371  assert (false);
2372  return NO_ERROR;
2373  }
2374  if (qentry_p->list_id == NULL)
2375  {
2376  return NO_ERROR;
2377  }
2378  if (qentry_p->list_id->page_cnt == 0)
2379  {
2380  /* make sure temp_file is not cyclic */
2381  if (qentry_p->temp_file)
2382  {
2383  qentry_p->temp_file->prev->next = NULL;
2384  }
2385  return NO_ERROR;
2386  }
2387  if (qentry_p->temp_file)
2388  {
2389  tfile_vfid_p = qentry_p->temp_file;
2390  tfile_vfid_p->prev->next = NULL;
2391  while (tfile_vfid_p)
2392  {
2393  if (!VFID_ISNULL (&tfile_vfid_p->temp_vfid))
2394  {
2395  if (!tfile_vfid_p->preserved)
2396  {
2397  file_temp_preserve (thread_p, &tfile_vfid_p->temp_vfid);
2398  tfile_vfid_p->preserved = true;
2399  }
2400  }
2401  temp = tfile_vfid_p;
2402  tfile_vfid_p = tfile_vfid_p->next;
2403  }
2404  }
2405  return NO_ERROR;
2406 }
2407 
2408 /*
2409  * sentry_to_qentry () - create a query manager entry from a session query
2410  * entry
2411  * return : void
2412  * sentry_p (in) : session query entry
2413  * qentry_p (in/out) : query manager query entry
2414  */
2415 static void
2417 {
2418  qentry_p->query_id = sentry_p->query_id;
2419  qentry_p->list_id = sentry_p->list_id;
2420  qentry_p->temp_vfid = sentry_p->temp_file;
2421 
2422  qentry_p->list_ent = NULL;
2423  qentry_p->num_tmp = sentry_p->num_tmp;
2424  qentry_p->total_count = sentry_p->total_count;
2425  qentry_p->query_status = QUERY_COMPLETED;
2426  qentry_p->query_flag = sentry_p->query_flag;
2427  XASL_ID_SET_NULL (&qentry_p->xasl_id);
2428  qentry_p->xasl_ent = NULL;
2429  qentry_p->er_msg = NULL;
2430  qentry_p->is_holdable = true;
2431 }
2432 
2433 /*
2434  * session_store_query_entry_info () - create a query entry
2435  * return : void
2436  * thread_p (in) :
2437  * qentry_p (in) : query entry
2438  */
2439 void
2441 {
2442  SESSION_STATE *state_p = NULL;
2443  SESSION_QUERY_ENTRY *sqentry_p = NULL, *current = NULL;
2444 
2445  assert (qentry_p != NULL);
2446 
2447  state_p = session_get_session_state (thread_p);
2448  if (state_p == NULL)
2449  {
2450  return;
2451  }
2452 
2453  /* iterate over queries so we don't add the same query twice */
2454  current = state_p->queries;
2455  while (current != NULL)
2456  {
2457  if (current->query_id == qentry_p->query_id)
2458  {
2459  /* we don't need to add it again, just set list_id to null so that the query manager does not drop it */
2460  qentry_p->list_id = NULL;
2461  qentry_p->temp_vfid = NULL;
2462  return;
2463  }
2464  current = current->next;
2465  }
2466 
2467  /* We didn't find it. Create an entry and add it to the list */
2468  sqentry_p = qentry_to_sentry (qentry_p);
2469  if (sqentry_p == NULL)
2470  {
2471  return;
2472  }
2473 
2474  session_preserve_temporary_files (thread_p, sqentry_p);
2475 
2476  if (state_p->queries == NULL)
2477  {
2478  state_p->queries = sqentry_p;
2479  }
2480  else
2481  {
2482  sqentry_p->next = state_p->queries;
2483  state_p->queries = sqentry_p;
2484  }
2485 
2486  sessions.num_holdable_cursors++;
2487 }
2488 
2489 /*
2490  * session_free_sentry_data () - close list files associated with a query
2491  * entry
2492  * return : void
2493  * thread_p (in) :
2494  * sentry_p (in) :
2495  */
2496 static void
2498 {
2499  if (sentry_p == NULL)
2500  {
2501  return;
2502  }
2503 
2504  if (sentry_p->list_id != NULL)
2505  {
2506  qfile_close_list (thread_p, sentry_p->list_id);
2507  qfile_free_list_id (sentry_p->list_id);
2508  }
2509 
2510  if (sentry_p->temp_file != NULL)
2511  {
2512  qmgr_free_temp_file_list (thread_p, sentry_p->temp_file, sentry_p->query_id, false);
2513  }
2514 
2515  sessions.num_holdable_cursors--;
2516 }
2517 
2518 /*
2519  * session_load_query_entry_info () - search for a query entry
2520  * return : error code or NO_ERROR
2521  * thread_p (in) :
2522  * qentry_p (in/out) : query entry
2523  */
2524 int
2526 {
2527  SESSION_STATE *state_p = NULL;
2528  SESSION_QUERY_ENTRY *sentry_p = NULL;
2529 
2530  state_p = session_get_session_state (thread_p);
2531  if (state_p == NULL)
2532  {
2533  return ER_FAILED;
2534  }
2535 
2536  sentry_p = state_p->queries;
2537  while (sentry_p != NULL)
2538  {
2539  if (sentry_p->query_id == qentry_p->query_id)
2540  {
2541  sentry_to_qentry (sentry_p, qentry_p);
2542  return NO_ERROR;
2543  }
2544  sentry_p = sentry_p->next;
2545  }
2546  return ER_FAILED;
2547 }
2548 
2549 /*
2550  * session_remove_query_entry_info () - remove a query entry from the holdable queries list
2551  * return : error code or NO_ERROR
2552  * thread_p (in) : active thread
2553  * query_id (in) : query id
2554  */
2555 int
2556 session_remove_query_entry_info (THREAD_ENTRY * thread_p, const QUERY_ID query_id)
2557 {
2558  SESSION_STATE *state_p = NULL;
2559  SESSION_QUERY_ENTRY *sentry_p = NULL, *prev = NULL;
2560 
2561  state_p = session_get_session_state (thread_p);
2562  if (state_p == NULL)
2563  {
2564  return ER_FAILED;
2565  }
2566 
2567  sentry_p = state_p->queries;
2568  while (sentry_p != NULL)
2569  {
2570  if (sentry_p->query_id == query_id)
2571  {
2572  /* remove sentry_p from the queries list */
2573  if (prev == NULL)
2574  {
2575  state_p->queries = sentry_p->next;
2576  }
2577  else
2578  {
2579  prev->next = sentry_p->next;
2580  }
2581  session_free_sentry_data (thread_p, sentry_p);
2582 
2583  free_and_init (sentry_p);
2584  break;
2585  }
2586  prev = sentry_p;
2587  sentry_p = sentry_p->next;
2588  }
2589 
2590  return NO_ERROR;
2591 }
2592 
2593 /*
2594  * session_clear_query_entry_info () - remove a query entry from the holdable queries list but do not close the
2595  * associated list files
2596  * return : error code or NO_ERROR
2597  * thread_p (in) : active thread
2598  * query_id (in) : query id
2599  */
2600 int
2601 session_clear_query_entry_info (THREAD_ENTRY * thread_p, const QUERY_ID query_id)
2602 {
2603  SESSION_STATE *state_p = NULL;
2604  SESSION_QUERY_ENTRY *sentry_p = NULL, *prev = NULL;
2605 
2606  state_p = session_get_session_state (thread_p);
2607  if (state_p == NULL)
2608  {
2609  return ER_FAILED;
2610  }
2611 
2612  sentry_p = state_p->queries;
2613  while (sentry_p != NULL)
2614  {
2615  if (sentry_p->query_id == query_id)
2616  {
2617  /* remove sentry_p from the queries list */
2618  if (prev == NULL)
2619  {
2620  state_p->queries = sentry_p->next;
2621  }
2622  else
2623  {
2624  prev->next = sentry_p->next;
2625  }
2626 
2627  free_and_init (sentry_p);
2628  sessions.num_holdable_cursors--;
2629 
2630  break;
2631  }
2632  prev = sentry_p;
2633  sentry_p = sentry_p->next;
2634  }
2635 
2636  return NO_ERROR;
2637 }
2638 
2639 /*
2640  * session_is_queryid_idle () - search for a idle query entry among the holable results
2641  * return : true if the given query_id is idle, false otherwise
2642  * thread_p (in) :
2643  * query_id (in) : query id
2644  * max_query_id_uses (out): max query id among the active ones. caller may use it as a hint
2645  */
2646 bool
2647 session_is_queryid_idle (THREAD_ENTRY * thread_p, const QUERY_ID query_id, QUERY_ID * max_query_id_uses)
2648 {
2649  SESSION_STATE *state_p = NULL;
2650  SESSION_QUERY_ENTRY *sentry_p = NULL;
2651 
2652  *max_query_id_uses = 0;
2653 
2654  state_p = session_get_session_state (thread_p);
2655  if (state_p == NULL)
2656  {
2657  return true;
2658  }
2659 
2660  for (sentry_p = state_p->queries; sentry_p != NULL; sentry_p = sentry_p->next)
2661  {
2662  if (*max_query_id_uses < sentry_p->query_id)
2663  {
2664  *max_query_id_uses = sentry_p->query_id;
2665  }
2666 
2667  if (sentry_p->query_id == query_id)
2668  {
2669  return false;
2670  }
2671  }
2672 
2673  return true;
2674 }
2675 
2676 /*
2677  * session_set_conn_entry_data () - set references to session state objects
2678  * into the connection entry associated
2679  * with this thread
2680  * return : void
2681  * thread_p (in) : current thread
2682  * session_p (in) : session state object
2683  */
2684 static void
2686 {
2687 #if defined(SERVER_MODE)
2688  if (thread_p == NULL)
2689  {
2690  thread_p = thread_get_thread_entry_info ();
2691  if (thread_p == NULL)
2692  {
2693  return;
2694  }
2695  }
2696 
2697  if (thread_p->conn_entry != NULL)
2698  {
2699  /* If we have a connection entry associated with this thread, setup session data for this conn_entry */
2700  thread_p->conn_entry->session_p = session_p;
2701  thread_p->conn_entry->session_id = session_p->id;
2702  }
2703  thread_p->private_lru_index = session_p->private_lru_index;
2704 #endif
2705 }
2706 
2707 /*
2708  * session_get_session_parameter () - get a reference to a system parameter
2709  * return : session parameter object
2710  * thread_p (in) : thread entry
2711  * id (in) : parameter id
2712  */
2713 SESSION_PARAM *
2715 {
2716  int i, count;
2717  SESSION_STATE *session_p = NULL;
2718 
2719  session_p = session_get_session_state (thread_p);
2720  if (session_p == NULL)
2721  {
2722  return NULL;
2723  }
2724 
2725  assert (id <= PRM_LAST_ID);
2726 
2728  for (i = 0; i < count; i++)
2729  {
2730  if (session_p->session_parameters[i].prm_id == id)
2731  {
2732  return &session_p->session_parameters[i];
2733  }
2734  }
2735 
2736  return NULL;
2737 }
2738 
2739 /*
2740  * session_get_session_state () - get the session state object
2741  * return : session state object or NULL in case of error
2742  * thread_p (in) : thread for which to get the session
2743  */
2744 static SESSION_STATE *
2746 {
2747 #if defined(SERVER_MODE)
2748  /* The session state object cached in the conn_entry object associated with every server request. Instead of
2749  * accessing the session states hash through a critical section, we can just return the hashed value. */
2750  if (thread_p == NULL)
2751  {
2752  thread_p = thread_get_thread_entry_info ();
2753  }
2754  if (thread_p != NULL && thread_p->conn_entry != NULL && thread_p->conn_entry->session_p != NULL)
2755  {
2756  return thread_p->conn_entry->session_p;
2757  }
2758  else
2759  {
2760  /* any request for this object should find it cached in the connection entry */
2761  if (thread_p->type == TT_WORKER)
2762  {
2764  }
2765  return NULL;
2766  }
2767 #else
2768  SESSION_ID id;
2769  int error = NO_ERROR;
2770  SESSION_STATE *state_p = NULL;
2771 
2772  error = session_get_session_id (thread_p, &id);
2773  if (error != NO_ERROR)
2774  {
2775  return NULL;
2776  }
2777 
2778  state_p = sessions.states_hashmap.find (thread_p, id);
2779  if (state_p == NULL)
2780  {
2782  return NULL;
2783  }
2784 
2785  /* not in server mode so no need for mutex or HP */
2786  pthread_mutex_unlock (&state_p->mutex);
2787 
2788  return state_p;
2789 #endif
2790 }
2791 
2792 /*
2793  * session_get_trace_stats () - return query trace result
2794  * return : query trace
2795  * result(out) :
2796  */
2797 int
2799 {
2800  SESSION_STATE *state_p = NULL;
2801  char *trace_str = NULL;
2802  size_t sizeloc;
2803  FILE *fp;
2804  json_t *plan, *xasl, *stats;
2805  DB_VALUE temp_result;
2806 
2807  state_p = session_get_session_state (thread_p);
2808  if (state_p == NULL)
2809  {
2810  return ER_FAILED;
2811  }
2812 
2813  if (state_p->plan_string == NULL && state_p->trace_stats == NULL)
2814  {
2815  db_make_null (result);
2816  return NO_ERROR;
2817  }
2818 
2819  if (state_p->trace_format == QUERY_TRACE_TEXT)
2820  {
2821  fp = port_open_memstream (&trace_str, &sizeloc);
2822  if (fp)
2823  {
2824  if (state_p->plan_string != NULL)
2825  {
2826  fprintf (fp, "\nQuery Plan:\n%s", state_p->plan_string);
2827  }
2828 
2829  if (state_p->trace_stats != NULL)
2830  {
2831  fprintf (fp, "\nTrace Statistics:\n%s", state_p->trace_stats);
2832  }
2833 
2834  port_close_memstream (fp, &trace_str, &sizeloc);
2835  }
2836  }
2837  else if (state_p->trace_format == QUERY_TRACE_JSON)
2838  {
2839  stats = json_object ();
2840 
2841  if (state_p->plan_string != NULL)
2842  {
2843  plan = json_loads (state_p->plan_string, 0, NULL);
2844  if (plan != NULL)
2845  {
2846  json_object_set_new (stats, "Query Plan", plan);
2847  }
2848  }
2849 
2850  if (state_p->trace_stats != NULL)
2851  {
2852  xasl = json_loads (state_p->trace_stats, 0, NULL);
2853  if (xasl != NULL)
2854  {
2855  json_object_set_new (stats, "Trace Statistics", xasl);
2856  }
2857  }
2858 
2859  trace_str = json_dumps (stats, JSON_INDENT (2) | JSON_PRESERVE_ORDER);
2860 
2861  json_object_clear (stats);
2862  json_decref (stats);
2863  }
2864 
2865  if (trace_str != NULL)
2866  {
2867  db_make_string (&temp_result, trace_str);
2868  pr_clone_value (&temp_result, result);
2869  free_and_init (trace_str);
2870  }
2871  else
2872  {
2873  db_make_null (result);
2874  }
2875 
2876  thread_set_clear_trace (thread_p, true);
2877 
2878  return NO_ERROR;
2879 }
2880 
2881 /*
2882  * session_set_trace_stats () - save query trace result to session
2883  * return :
2884  * stats(in) :
2885  * format(in) :
2886  */
2887 int
2888 session_set_trace_stats (THREAD_ENTRY * thread_p, char *stats, int format)
2889 {
2890  SESSION_STATE *state_p = NULL;
2891 
2892  state_p = session_get_session_state (thread_p);
2893  if (state_p == NULL)
2894  {
2895  return ER_FAILED;
2896  }
2897 
2898  if (state_p->trace_stats != NULL)
2899  {
2900  free_and_init (state_p->trace_stats);
2901  }
2902 
2903  state_p->trace_stats = stats;
2904  state_p->trace_format = format;
2905 
2906  return NO_ERROR;
2907 }
2908 
2909 /*
2910  * session_clear_trace_stats () - clear query trace result from session
2911  * return :
2912  * stats(in) :
2913  * format(in) :
2914  */
2915 int
2917 {
2918  SESSION_STATE *state_p = NULL;
2919 
2920  assert (thread_need_clear_trace (thread_p) == true);
2921 
2922  state_p = session_get_session_state (thread_p);
2923  if (state_p == NULL)
2924  {
2925  return ER_FAILED;
2926  }
2927 
2928  if (state_p->plan_string != NULL)
2929  {
2930  free_and_init (state_p->plan_string);
2931  }
2932 
2933  if (state_p->trace_stats != NULL)
2934  {
2935  free_and_init (state_p->trace_stats);
2936  }
2937 
2938  thread_set_clear_trace (thread_p, false);
2939 
2940  return NO_ERROR;
2941 }
2942 
2943 /*
2944  * session_get_session_tz_region () - get a reference to the session timezone
2945  * region
2946  * return : reference to session TZ_REGION object
2947  * thread_p (in) : thread entry
2948  */
2949 TZ_REGION *
2951 {
2952  SESSION_STATE *session_p = NULL;
2953 
2954  session_p = session_get_session_state (thread_p);
2955  if (session_p == NULL)
2956  {
2957  return NULL;
2958  }
2959 
2960  return &session_p->session_tz_region;
2961 }
2962 
2963 
2964 #if !defined (NDEBUG) && defined (SERVER_MODE)
2965 /*
2966  * session_state_verify_ref_count () -
2967  * return :
2968  *
2969  */
2970 static int
2971 session_state_verify_ref_count (THREAD_ENTRY * thread_p, SESSION_STATE * session_p)
2972 {
2973  int ref_count = 0, r;
2974  CSS_CONN_ENTRY *conn;
2975 
2976  if (session_p == NULL)
2977  {
2978  assert (0);
2979  return ER_FAILED;
2980  }
2981 
2983  {
2984  assert (0);
2985  return ER_FAILED;
2986  }
2987 
2989 
2990  for (conn = css_Active_conn_anchor; conn != NULL; conn = conn->next)
2991  {
2992  if (session_p->id == conn->session_id)
2993  {
2994  ref_count++;
2995  }
2996  }
2997 
2998  if (ref_count != session_p->ref_count)
2999  {
3001  assert (0);
3002  return ER_FAILED;
3003  }
3004 
3006 
3007  return NO_ERROR;
3008 }
3009 #endif
3010 
3011 /*
3012  * session_state_increase_ref_count () -
3013  * return :
3014  *
3015  */
3016 #if defined (SERVER_MODE)
3017 int
3018 session_state_increase_ref_count (THREAD_ENTRY * thread_p, SESSION_STATE * state_p)
3019 {
3020  if (state_p == NULL)
3021  {
3022  assert (0);
3023  return ER_FAILED;
3024  }
3025 
3026  ATOMIC_INC_32 (&state_p->ref_count, 1);
3027 
3028  if (state_p->ref_count <= 0)
3029  {
3030  assert (state_p->ref_count > 0);
3031  ATOMIC_TAS_32 (&state_p->ref_count, 1);
3032  }
3033 
3034  return NO_ERROR;
3035 }
3036 
3037 /*
3038  * session_state_decrease_ref_count () -
3039  * return :
3040  *
3041  */
3042 int
3043 session_state_decrease_ref_count (THREAD_ENTRY * thread_p, SESSION_STATE * state_p)
3044 {
3045  if (state_p == NULL)
3046  {
3047  assert (0);
3048  return ER_FAILED;
3049  }
3050 
3051  ATOMIC_INC_32 (&state_p->ref_count, -1);
3052 
3053  if (state_p->ref_count < 0)
3054  {
3055  assert (state_p->ref_count >= 0);
3056  ATOMIC_TAS_32 (&state_p->ref_count, 0);
3057  }
3058 
3059  return NO_ERROR;
3060 }
3061 #endif
3062 
3063 /*
3064  * session_get_number_of_holdable_cursors () - return the number of holdable cursors
3065  *
3066  * return : the number of holdable cursors
3067  *
3068  */
3069 int
3071 {
3072  return sessions.num_holdable_cursors;
3073 }
3074 
3075 /*
3076  * session_get_private_lru_idx () - returns the LRU index of this session
3077  *
3078  *
3079  * return : LRU index
3080  * session_p (in) : session
3081  *
3082  */
3083 int
3084 session_get_private_lru_idx (const void *session_p)
3085 {
3086  return ((SESSION_STATE *) session_p)->private_lru_index;
3087 }
3088 
3089 /*
3090  * session_set_tran_auto_commit () - set transaction auto commit state
3091  *
3092  * return : NO_ERROR or error code
3093  * thread_p(in) : thread
3094  * auto_commit(in) : auto commit
3095  */
3096 int
3097 session_set_tran_auto_commit (THREAD_ENTRY * thread_p, bool auto_commit)
3098 {
3099  SESSION_STATE *state_p = NULL;
3100 
3101  state_p = session_get_session_state (thread_p);
3102  if (state_p == NULL)
3103  {
3104  return ER_FAILED;
3105  }
3106 
3107  state_p->auto_commit = auto_commit;
3108 
3109  return NO_ERROR;
3110 }
3111 
3112 int
3114 {
3115  SESSION_STATE *state_p = NULL;
3116 
3117  state_p = session_get_session_state (thread_p);
3118  if (state_p == NULL)
3119  {
3120  return ER_FAILED;
3121  }
3122 
3123  state_p->load_session_p = load_session_p;
3124 
3125  return NO_ERROR;
3126 }
3127 
3128 int
3129 session_get_load_session (THREAD_ENTRY * thread_p, REFPTR (load_session, load_session_ref_ptr))
3130 {
3131  SESSION_STATE *state_p = NULL;
3132 
3133  state_p = session_get_session_state (thread_p);
3134  if (state_p == NULL)
3135  {
3136  return ER_FAILED;
3137  }
3138 
3139  load_session_ref_ptr = state_p->load_session_p;
3140 
3141  return NO_ERROR;
3142 }
3143 
3144 /*
3145  * session_stop_attached_threads - stops extra attached threads (not connection worker thread)
3146  * associated with the session
3147  *
3148  */
3149 void
3151 {
3152 #if defined (SERVER_MODE)
3153  SESSION_STATE *session = (SESSION_STATE *) session_arg;
3154 
3155  assert (session != NULL);
3156 
3157  // on uninit abort and delete loaddb session
3158  if (session->load_session_p != NULL)
3159  {
3160  session->load_session_p->interrupt ();
3161  session->load_session_p->wait_for_completion ();
3162 
3163  delete session->load_session_p;
3164  session->load_session_p = NULL;
3165  }
3166 #endif
3167 }
static int session_drop_variable(SESSION_STATE *state_p, const DB_VALUE *name)
Definition: session.c:1298
SHA1Hash sha1
Definition: session.c:90
Definition: sha1.h:50
int login_user(THREAD_ENTRY *thread_p, const char *username)
Definition: session.c:1917
QFILE_LIST_CACHE_ENTRY * list_ent
QFILE_LIST_ID * list_id
cubthread::entry * thread_get_thread_entry_info(void)
bool auto_commit
Definition: session.c:119
int db_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const DB_DOMAIN *desired_domain)
Definition: db_macro.c:1779
#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 int session_key_compare(void *k1, void *k2)
Definition: session.c:451
void session_states_finalize(THREAD_ENTRY *thread_p)
Definition: session.c:607
char buf[DB_SMALL_CHAR_BUF_SIZE]
Definition: dbtype_def.h:991
#define END_SHARED_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:82
#define ER_SES_VARIABLE_NOT_FOUND
Definition: error_code.h:1338
int session_get_exec_stats_and_clear(THREAD_ENTRY *thread_p, const DB_VALUE *name, DB_VALUE *result)
Definition: session.c:2187
#define BO_IS_SERVER_RESTARTED()
Definition: boot_sr.h:84
static SESSION_QUERY_ENTRY * qentry_to_sentry(QMGR_QUERY_ENTRY *qentry_p)
Definition: session.c:2329
int session_get_last_insert_id(THREAD_ENTRY *thread_p, DB_VALUE *value, bool update_last_insert_id)
Definition: session.c:1381
#define ASSERT_ERROR()
static LF_ENTRY_DESCRIPTOR session_state_Descriptor
Definition: session.c:154
#define MAX_PREPARED_STATEMENTS_COUNT
Definition: session.c:68
int session_state_create(THREAD_ENTRY *thread_p, SESSION_ID *id)
Definition: session.c:637
SESSION_QUERY_ENTRY * queries
Definition: session.c:125
int session_get_variable(THREAD_ENTRY *thread_p, const DB_VALUE *name, DB_VALUE *result)
Definition: session.c:2003
int session_clear_trace_stats(THREAD_ENTRY *thread_p)
Definition: session.c:2916
int ref_count
Definition: session.c:131
static SESSION_STATE * session_get_session_state(THREAD_ENTRY *thread_p)
Definition: session.c:2745
~session_state()
Definition: session.c:238
int db_make_bigint(DB_VALUE *value, const DB_BIGINT num)
int db_get_int(const DB_VALUE *value)
DB_TYPE
Definition: dbtype_def.h:670
static int session_state_uninit(void *st)
Definition: session.c:323
static API_MUTEX mutex
Definition: api_util.c:72
#define ER_FAILED
Definition: error_code.h:47
SESSION_QUERY_ENTRY * next
Definition: session.c:105
int db_make_varchar(DB_VALUE *value, const int max_char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
int private_lru_index
Definition: session.c:133
int db_get_string_collation(const DB_VALUE *value)
LF_TRAN_SYSTEM sessions_Ts
Definition: lock_free.c:50
int session_check_session(THREAD_ENTRY *thread_p, const SESSION_ID id)
Definition: session.c:810
SESSION_PARAM * session_get_session_parameter(THREAD_ENTRY *thread_p, PARAM_ID id)
Definition: session.c:2714
static void session_free_sentry_data(THREAD_ENTRY *thread_p, SESSION_QUERY_ENTRY *sentry_p)
Definition: session.c:2497
static unsigned int session_key_hash(void *key, int hash_table_size)
Definition: session.c:438
QMGR_TEMP_FILE * prev
Definition: query_manager.h:79
int num_tmp
Definition: session.c:101
int session_remove_query_entry_info(THREAD_ENTRY *thread_p, const QUERY_ID query_id)
Definition: session.c:2556
SESSION_VARIABLE * session_variables
Definition: session.c:123
enum param_id PARAM_ID
SESSION_ID * session_ids
Definition: session.c:73
Definition: lock_free.h:63
bool thread_need_clear_trace(cubthread::entry *thread_p)
int num_tmp
#define assert_release(e)
Definition: error_manager.h:96
int session_set_session_parameters(THREAD_ENTRY *thread_p, SESSION_PARAM *session_parameters)
Definition: session.c:1641
static void free_session_variable(SESSION_VARIABLE *var)
Definition: session.c:1031
int session_clear_query_entry_info(THREAD_ENTRY *thread_p, const QUERY_ID query_id)
Definition: session.c:2601
QUERY_FLAG query_flag
Definition: session.c:103
static int session_add_variable(SESSION_STATE *state_p, const DB_VALUE *name, DB_VALUE *value)
Definition: session.c:1064
DB_VALUE cur_insert_id
Definition: session.c:120
static int session_remove_expired_sessions(THREAD_ENTRY *thread_p)
Definition: session.c:884
int session_load_query_entry_info(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *qentry_p)
Definition: session.c:2525
LOG_TDES * LOG_FIND_TDES(int tran_index)
Definition: log_impl.h:1095
static int session_check_timeout(SESSION_STATE *session_p, SESSION_INFO *active_sessions, bool *remove)
Definition: session.c:976
bool erase(cubthread::entry *thread_p, Key &key)
#define DB_VALUE_PRECISION(value)
Definition: dbtype.h:73
int session_reset_cur_insert_id(THREAD_ENTRY *thread_p)
Definition: session.c:1473
static void * session_state_alloc(void)
Definition: session.c:249
#define er_log_debug(...)
char * alias_print
Definition: session.c:89
SESSION_ID last_session_id
Definition: session.c:181
Definition: session.c:96
int session_drop_session_variables(THREAD_ENTRY *thread_p, DB_VALUE *values, const int count)
Definition: session.c:2157
void wait_for_completion()
static int session_state_init(void *st)
Definition: session.c:287
#define DB_VALUE_SCALE(value)
Definition: dbtype.h:74
SESSION_PARAM * session_parameters
Definition: session.c:127
#define VFID_ISNULL(vfid_ptr)
Definition: file_manager.h:72
void THREAD_ENTRY
struct active_sessions ACTIVE_SESSIONS
void set_user(const char *db_user)
#define SHA1_AS_ARGS(sha1)
Definition: sha1.h:56
bool session_is_queryid_idle(THREAD_ENTRY *thread_p, const QUERY_ID query_id, QUERY_ID *max_query_id_uses)
Definition: session.c:2647
TZ_REGION * session_get_session_tz_region(THREAD_ENTRY *thread_p)
Definition: session.c:2950
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
QFILE_LIST_ID * list_id
Definition: session.c:99
void port_close_memstream(FILE *fp, char **ptr, size_t *sizeloc)
Definition: porting.c:2220
int session_set_load_session(THREAD_ENTRY *thread_p, load_session *load_session_p)
Definition: session.c:3113
SESSION_VARIABLE * next
Definition: session.c:82
static DB_VALUE * db_value_alloc_and_copy(const DB_VALUE *src)
Definition: session.c:1172
DB_DATA data
Definition: dbtype_def.h:1083
manager * get_manager(void)
static cubthread::daemon * session_Control_daemon
Definition: session.c:228
PREPARED_STATEMENT * next
Definition: session.c:93
int css_get_session_ids_for_active_connections(SESSION_ID **session_ids, int *count)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
static void session_dump_prepared_statement(PREPARED_STATEMENT *stmt_p)
Definition: session.c:2303
#define SESSIONS_HASH_SIZE
Definition: session.c:66
int session_get_load_session(THREAD_ENTRY *thread_p, REFPTR(load_session, load_session_ref_ptr))
Definition: session.c:3129
#define DB_MAX_NUMERIC_PRECISION
Definition: dbtype_def.h:522
session_hashmap_type states_hashmap
Definition: session.c:180
#define assert(x)
void end_tran(cubthread::entry *thread_p)
int session_get_prepared_statement(THREAD_ENTRY *thread_p, const char *name, char **info, int *info_len, xasl_cache_ent **xasl_entry)
Definition: session.c:1786
int prm_get_integer_value(PARAM_ID prm_id)
T * find(cubthread::entry *thread_p, Key &key)
static void sentry_to_qentry(const SESSION_QUERY_ENTRY *sentry_p, QMGR_QUERY_ENTRY *qentry_p)
Definition: session.c:2416
QMGR_QUERY_STATUS query_status
bool erase_locked(cubthread::entry *thread_p, Key &key, T *&t)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define REFPTR(T, name)
Definition: porting.h:1089
#define START_SHARED_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:74
QUERY_FLAG query_flag
int row_count
Definition: session.c:122
#define pthread_mutex_unlock(a)
Definition: session.c:62
int intl_identifier_casecmp(const char *str1, const char *str2)
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
void session_states_dump(THREAD_ENTRY *thread_p)
Definition: session.c:2208
void session_states_init(THREAD_ENTRY *thread_p)
Definition: session.c:582
UINT64 del_id
Definition: session.c:115
#define TP_IS_NUMERIC_TYPE(typeid)
DB_VALUE last_insert_id
Definition: session.c:121
char * name
Definition: session.c:80
int session_get_session_parameters(THREAD_ENTRY *thread_p, SESSION_PARAM **session_parameters_ptr)
Definition: session.c:1613
void thread_set_clear_trace(cubthread::entry *thread_p, bool clear)
#define MAX_SESSION_VARIABLES_COUNT
Definition: session.c:67
#define ER_SES_TOO_MANY_VARIABLES
Definition: error_code.h:1339
xasl_cache_ent * xasl_ent
static void session_control_daemon_destroy()
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
int session_get_trace_stats(THREAD_ENTRY *thread_p, DB_VALUE *result)
Definition: session.c:2798
char * er_msg
bool insert(cubthread::entry *thread_p, Key &key, T *&t)
#define NULL
Definition: freelistheap.h:34
void file_temp_preserve(THREAD_ENTRY *thread_p, const VFID *vfid)
DB_CHAR ch
Definition: dbtype_def.h:1070
int session_set_trace_stats(THREAD_ENTRY *thread_p, char *stats, int format)
Definition: session.c:2888
int pgbuf_assign_private_lru(THREAD_ENTRY *thread_p, bool is_vacuum, const int id)
int session_get_private_lru_idx(const void *session_p)
Definition: session.c:3084
XASL_ID xasl_id
static int success()
void init(lf_tran_system &transys, int entry_idx, int hash_size, int freelist_block_size, int freelist_block_count, lf_entry_descriptor &edesc)
#define pthread_mutex_init(a, b)
Definition: session.c:58
#define err(fd,...)
Definition: porting.h:431
#define DB_EMPTY_SESSION
Definition: dbtype_def.h:483
int count
Definition: session.c:74
int session_get_variable_no_copy(THREAD_ENTRY *thread_p, const DB_VALUE *name, DB_VALUE **result)
Definition: session.c:2069
PREPARED_STATEMENT * statements
Definition: session.c:124
bool is_holdable
need_clear_type need_clear
Definition: dbtype_def.h:1084
CLIENTIDS client
Definition: log_impl.h:484
int pr_clear_value(DB_VALUE *value)
QMGR_TEMP_FILE * temp_file
Definition: session.c:100
int session_define_variable(THREAD_ENTRY *thread_p, DB_VALUE *name, DB_VALUE *value, DB_VALUE *result)
Definition: session.c:1970
DB_DOMAIN * db_type_to_db_domain(const DB_TYPE type)
Definition: db_macro.c:1710
static void session_dump_variable(SESSION_VARIABLE *var)
Definition: session.c:2275
CSS_CONN_ENTRY * css_Active_conn_anchor
static ACTIVE_SESSIONS sessions
Definition: session.c:195
#define pthread_mutex_destroy(a)
Definition: session.c:59
QMGR_TEMP_FILE * temp_vfid
void sysprm_free_session_parameters(SESSION_PARAM **session_parameters_ptr)
QUERY_ID query_id
const char * envvar_get(const char *name)
static void error(const char *msg)
Definition: gencat.c:331
QUERY_ID query_id
Definition: session.c:98
int session_set_tran_auto_commit(THREAD_ENTRY *thread_p, bool auto_commit)
Definition: session.c:3097
int trace_format
Definition: session.c:130
void qfile_free_list_id(QFILE_LIST_ID *list_id_p)
Definition: list_file.c:563
#define LOG_FIND_THREAD_TRAN_INDEX(thrd)
Definition: perf_monitor.h:158
char * plan_string
Definition: session.c:129
int session_set_row_count(THREAD_ENTRY *thread_p, const int row_count)
Definition: session.c:1586
bool is_trigger_involved
Definition: session.c:117
bool is_last_insert_id_generated
Definition: session.c:118
int session_get_number_of_holdable_cursors(void)
Definition: session.c:3070
#define ARG_FILE_LINE
Definition: error_manager.h:44
void destroy_daemon(daemon *&daemon_arg)
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
SESSION_ID db_Session_id
Definition: db_macro.c:79
char * trace_stats
Definition: session.c:128
int db_make_varbit(DB_VALUE *value, const int max_bit_length, DB_CONST_C_BIT bit_str, const int bit_str_bit_size)
pthread_mutex_t mutex
Definition: session.c:114
int num_holdable_cursors
Definition: session.c:182
QMGR_TEMP_FILE * next
Definition: query_manager.h:78
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
int session_create_prepared_statement(THREAD_ENTRY *thread_p, char *name, char *alias_print, SHA1Hash *sha1, char *info, int info_len)
Definition: session.c:1674
int db_value_precision(const DB_VALUE *value)
static int session_dump_session(SESSION_STATE *session)
Definition: session.c:2231
unsigned int SESSION_ID
Definition: dbtype_def.h:480
static void session_free_prepared_statement(PREPARED_STATEMENT *stmt_p)
Definition: session.c:506
int session_get_session_id(THREAD_ENTRY *thread_p, SESSION_ID *id)
Definition: session.c:1347
bool prm_get_bool_value(PARAM_ID prm_id)
int session_set_trigger_state(THREAD_ENTRY *thread_p, bool in_trigger)
Definition: session.c:1534
#define QSTR_IS_ANY_CHAR_OR_BIT(s)
Definition: string_opfunc.h:47
DB_VALUE * value
Definition: session.c:81
int db_get_string_size(const DB_VALUE *value)
int db_make_varnchar(DB_VALUE *value, const int max_nchar_length, DB_CONST_C_NCHAR str, const int nchar_str_byte_size, const int codeset, const int collation_id)
#define TP_FLOATING_PRECISION_VALUE
int total_count
Definition: session.c:102
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
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
int session_set_cur_insert_id(THREAD_ENTRY *thread_p, const DB_VALUE *value, bool force)
Definition: session.c:1414
void session_store_query_entry_info(THREAD_ENTRY *thread_p, QMGR_QUERY_ENTRY *qentry_p)
Definition: session.c:2440
int db_make_null(DB_VALUE *value)
void qfile_close_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:1263
#define DB_IS_NULL(value)
Definition: dbtype.h:63
static int session_key_increment(void *key, void *existing)
Definition: session.c:484
int session_get_row_count(THREAD_ENTRY *thread_p, int *row_count)
Definition: session.c:1562
static void update_session_variable(SESSION_VARIABLE *var, const DB_VALUE *new_value)
Definition: session.c:1276
char * strdup(const char *str)
Definition: porting.c:901
static void session_set_conn_entry_data(THREAD_ENTRY *thread_p, SESSION_STATE *session_p)
Definition: session.c:2685
int QUERY_FLAG
Definition: query_list.h:585
static int session_key_copy(void *src, void *dest)
Definition: session.c:410
int session_begin_insert_values(THREAD_ENTRY *thread_p)
Definition: session.c:1506
SESSION_STATE * stack
Definition: session.c:112
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int session_delete_prepared_statement(THREAD_ENTRY *thread_p, const char *name)
Definition: session.c:1865
#define EXPIRED_SESSION_BUFFER_SIZE
session_hashmap_type::iterator session_hashmap_iterator
Definition: session.c:175
int db_make_char(DB_VALUE *value, const int char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
static int rv
Definition: session.c:63
CSS_CONN_ENTRY * next
SESSION_ID id
Definition: session.c:111
static void session_control_daemon_init()
static int session_preserve_temporary_files(THREAD_ENTRY *thread_p, SESSION_QUERY_ENTRY *q_entry)
Definition: session.c:2365
int sysprm_get_session_parameters_count(void)
daemon * create_daemon(const looper &looper_arg, entry_task *exec_p, const char *daemon_name="", entry_manager *context_manager=NULL)
time_t active_time
Definition: session.c:126
#define ER_IT_PREPARED_NAME_NOT_FOUND
Definition: error_code.h:1246
void logtb_set_current_user_active(THREAD_ENTRY *thread_p, bool is_user_active)
int total_count
load_session * load_session_p
Definition: session.c:135
#define ER_SES_SESSION_EXPIRED
Definition: error_code.h:1331
#define XASL_ID_SET_NULL(X)
Definition: xasl.h:546
callable_task< entry > entry_callable_task
TZ_REGION session_tz_region
Definition: session.c:132
int db_make_bit(DB_VALUE *value, const int bit_length, DB_CONST_C_BIT bit_str, const int bit_str_bit_size)
int pgbuf_release_private_lru(THREAD_ENTRY *thread_p, const int private_idx)
#define LF_EM_USING_MUTEX
Definition: lock_free.h:60
int db_get_string_codeset(const DB_VALUE *value)
static int session_state_free(void *st)
Definition: session.c:267
SESSION_ID session_id
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
struct db_char::@54 medium
int db_make_nchar(DB_VALUE *value, const int nchar_length, DB_CONST_C_NCHAR str, const int nchar_str_byte_size, const int codeset, const int collation_id)
SESSION_STATE * next
Definition: session.c:113
#define ER_SES_TOO_MANY_STATEMENTS
Definition: error_code.h:1336
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
FILE * port_open_memstream(char **ptr, size_t *sizeloc)
Definition: porting.c:2198
int session_set_session_variables(THREAD_ENTRY *thread_p, DB_VALUE *values, const int count)
Definition: session.c:1939
int session_state_destroy(THREAD_ENTRY *thread_p, const SESSION_ID id)
Definition: session.c:741
void session_stop_attached_threads(void *session_arg)
Definition: session.c:3150