CUBRID Engine  latest
xasl_stream.cpp
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 // XASL stream - common interface for xasl_to_stream and stream_to_xasl
21 //
22 
23 #include "xasl_stream.hpp"
24 
25 #include "memory_alloc.h"
26 #include "object_representation.h"
27 #include "xasl.h"
28 #include "xasl_unpack_info.hpp"
29 
30 #if !defined(SERVER_MODE)
32 #endif /* !SERVER_MODE */
33 
34 /*
35  * stx_get_xasl_errcode () -
36  * return:
37  */
38 int
40 {
41 #if defined(SERVER_MODE)
42  return thread_p->xasl_errcode;
43 #else /* SERVER_MODE */
44  return stx_Xasl_errcode;
45 #endif /* SERVER_MODE */
46 }
47 
48 /*
49  * stx_set_xasl_errcode () -
50  * return:
51  * errcode(in) :
52  */
53 void
54 stx_set_xasl_errcode (THREAD_ENTRY *thread_p, int errcode)
55 {
56 #if defined(SERVER_MODE)
57  thread_p->xasl_errcode = errcode;
58 #else /* SERVER_MODE */
59  stx_Xasl_errcode = errcode;
60 #endif /* SERVER_MODE */
61 }
62 
63 /*
64  * stx_init_xasl_unpack_info () -
65  * return:
66  * xasl_stream(in) : pointer to xasl stream
67  * xasl_stream_size(in) :
68  *
69  * Note: initialize the xasl pack information.
70  */
71 int
72 stx_init_xasl_unpack_info (THREAD_ENTRY *thread_p, char *xasl_stream, int xasl_stream_size)
73 {
74  size_t n;
75  XASL_UNPACK_INFO *unpack_info;
76  int head_offset, body_offset;
77 
78 #define UNPACK_SCALE 3 /* TODO: assume */
79 
80  head_offset = sizeof (XASL_UNPACK_INFO);
81  head_offset = xasl_stream_make_align (head_offset);
82  body_offset = xasl_stream_size * UNPACK_SCALE;
83  body_offset = xasl_stream_make_align (body_offset);
84  unpack_info = (XASL_UNPACK_INFO *) db_private_alloc (thread_p, head_offset + body_offset);
85  set_xasl_unpack_info_ptr (thread_p, unpack_info);
86  if (unpack_info == NULL)
87  {
88  return ER_FAILED;
89  }
90  unpack_info->packed_xasl = xasl_stream;
91  unpack_info->packed_size = xasl_stream_size;
92  for (n = 0; n < MAX_PTR_BLOCKS; ++n)
93  {
94  unpack_info->ptr_blocks[n] = (STX_VISITED_PTR *) 0;
95  unpack_info->ptr_lwm[n] = 0;
96  unpack_info->ptr_max[n] = 0;
97  }
98  unpack_info->alloc_size = xasl_stream_size * UNPACK_SCALE;
99  unpack_info->alloc_buf = (char *) unpack_info + head_offset;
100  unpack_info->additional_buffers = NULL;
101  unpack_info->track_allocated_bufers = 0;
102 #if defined (SERVER_MODE)
103  unpack_info->thrd = thread_p;
104 #endif /* SERVER_MODE */
105 
106  return NO_ERROR;
107 }
108 
109 /*
110  * stx_mark_struct_visited () -
111  * return: if successful, return NO_ERROR, otherwise
112  * ER_FAILED and error code is set to xasl_errcode
113  * ptr(in) : pointer constant to be marked visited
114  * str(in) : where the struct pointed by 'ptr' is stored
115  *
116  * Note: mark the given pointer constant as visited to avoid
117  * duplicated storage of a struct which is pointed by more than one node
118  */
119 int
120 stx_mark_struct_visited (THREAD_ENTRY *thread_p, const void *ptr, void *str)
121 {
122  int new_lwm;
123  int block_no;
125 
126  block_no = xasl_stream_get_ptr_block (ptr);
127  new_lwm = xasl_unpack_info->ptr_lwm[block_no];
128 
129  if (xasl_unpack_info->ptr_max[block_no] == 0)
130  {
131  xasl_unpack_info->ptr_max[block_no] = START_PTR_PER_BLOCK;
132  xasl_unpack_info->ptr_blocks[block_no] =
133  (STX_VISITED_PTR *) db_private_alloc (thread_p, sizeof (STX_VISITED_PTR) * xasl_unpack_info->ptr_max[block_no]);
134  }
135  else if (xasl_unpack_info->ptr_max[block_no] <= new_lwm)
136  {
137  xasl_unpack_info->ptr_max[block_no] *= 2;
138  xasl_unpack_info->ptr_blocks[block_no] =
139  (STX_VISITED_PTR *) db_private_realloc (thread_p, xasl_unpack_info->ptr_blocks[block_no],
140  sizeof (STX_VISITED_PTR) * xasl_unpack_info->ptr_max[block_no]);
141  }
142 
143  if (xasl_unpack_info->ptr_blocks[block_no] == (STX_VISITED_PTR *) NULL)
144  {
146  return ER_FAILED;
147  }
148 
149  xasl_unpack_info->ptr_blocks[block_no][new_lwm].ptr = ptr;
150  xasl_unpack_info->ptr_blocks[block_no][new_lwm].str = str;
151 
152  xasl_unpack_info->ptr_lwm[block_no]++;
153 
154  return NO_ERROR;
155 }
156 
157 /*
158  * stx_get_struct_visited_ptr () -
159  * return: if the ptr is already visited, the offset of
160  * position where the node pointed by 'ptr' is stored,
161  * otherwise, ER_FAILED (xasl_errcode is NOT set)
162  * ptr(in) : pointer constant to be checked if visited or not
163  *
164  * Note: check if the node pointed by `ptr` is already stored or
165  * not to avoid multiple store of the same node
166  */
167 void *
168 stx_get_struct_visited_ptr (THREAD_ENTRY *thread_p, const void *ptr)
169 {
170  int block_no;
171  int element_no;
173 
174  block_no = xasl_stream_get_ptr_block (ptr);
175 
176  if (xasl_unpack_info->ptr_lwm[block_no] <= 0)
177  {
178  return NULL;
179  }
180 
181  for (element_no = 0; element_no < xasl_unpack_info->ptr_lwm[block_no]; element_no++)
182  {
183  if (ptr == xasl_unpack_info->ptr_blocks[block_no][element_no].ptr)
184  {
185  return (xasl_unpack_info->ptr_blocks[block_no][element_no].str);
186  }
187  }
188 
189  return NULL;
190 }
191 
192 /*
193  * stx_free_visited_ptrs () -
194  * return:
195  *
196  * Note: free memory allocated to manage visited ptr constants
197  */
198 void
200 {
202 
203  for (size_t i = 0; i < MAX_PTR_BLOCKS; i++)
204  {
205  xasl_unpack_info->ptr_lwm[i] = 0;
206  xasl_unpack_info->ptr_max[i] = 0;
207  if (xasl_unpack_info->ptr_blocks[i])
208  {
209  db_private_free_and_init (thread_p, xasl_unpack_info->ptr_blocks[i]);
210  xasl_unpack_info->ptr_blocks[i] = (STX_VISITED_PTR *) 0;
211  }
212  }
213 }
214 
215 /*
216  * stx_alloc_struct () -
217  * return:
218  * size(in) : # of bytes of the node
219  *
220  * Note: allocate storage for structures pointed to from the xasl tree.
221  */
222 char *
223 stx_alloc_struct (THREAD_ENTRY *thread_p, int size)
224 {
225  char *ptr;
227 
228  if (!size)
229  {
230  return NULL;
231  }
232 
233  size = xasl_stream_make_align (size); /* alignment */
234  if (size > xasl_unpack_info->alloc_size)
235  {
236  /* need to alloc */
237  int p_size;
238 
239  p_size = MAX (size, xasl_unpack_info->packed_size);
240  p_size = xasl_stream_make_align (p_size); /* alignment */
241  ptr = (char *) db_private_alloc (thread_p, p_size);
242  if (ptr == NULL)
243  {
244  return NULL; /* error */
245  }
246  xasl_unpack_info->alloc_size = p_size;
247  xasl_unpack_info->alloc_buf = ptr;
248  if (xasl_unpack_info->track_allocated_bufers)
249  {
250  UNPACK_EXTRA_BUF *add_buff = NULL;
251  add_buff = (UNPACK_EXTRA_BUF *) db_private_alloc (thread_p, sizeof (UNPACK_EXTRA_BUF));
252  if (add_buff == NULL)
253  {
254  db_private_free_and_init (thread_p, ptr);
255  return NULL;
256  }
257  add_buff->buff = ptr;
258  add_buff->next = NULL;
259 
260  if (xasl_unpack_info->additional_buffers == NULL)
261  {
262  xasl_unpack_info->additional_buffers = add_buff;
263  }
264  else
265  {
266  add_buff->next = xasl_unpack_info->additional_buffers;
267  xasl_unpack_info->additional_buffers = add_buff;
268  }
269  }
270  }
271 
272  /* consume alloced buffer */
273  ptr = xasl_unpack_info->alloc_buf;
274  xasl_unpack_info->alloc_size -= size;
275  xasl_unpack_info->alloc_buf += size;
276 
277  return ptr;
278 }
279 
280 char *
281 stx_build_db_value (THREAD_ENTRY *thread_p, char *ptr, DB_VALUE *value)
282 {
283  ptr = or_unpack_db_value (ptr, value);
284 
285  return ptr;
286 }
287 
288 char *
289 stx_build_string (THREAD_ENTRY *thread_p, char *ptr, char *string)
290 {
291  int offset;
292 
293  ptr = or_unpack_int (ptr, &offset);
294  assert_release (offset > 0);
295 
296  (void) memcpy (string, ptr, offset);
297  ptr += offset;
298 
299  return ptr;
300 }
301 
302 char *
303 stx_restore_string (THREAD_ENTRY *thread_p, char *&ptr)
304 {
305 #if !defined (CS_MODE)
306  char *string;
307  int length;
308  int offset = 0;
309 
310  ptr = or_unpack_int (ptr, &offset);
311  if (offset == 0)
312  {
313  return NULL;
314  }
315 
316  char *bufptr = &get_xasl_unpack_info_ptr (thread_p)->packed_xasl[offset];
317  if (ptr == NULL)
318  {
319  return NULL;
320  }
321 
322  string = (char *) stx_get_struct_visited_ptr (thread_p, bufptr);
323  if (string != NULL)
324  {
325  return string;
326  }
327 
328  length = OR_GET_INT (bufptr);
329 
330  if (length == -1)
331  {
332  /* unpack null-string */
333  assert (string == NULL);
334  }
335  else
336  {
337  assert_release (length > 0);
338 
339  string = (char *) stx_alloc_struct (thread_p, length);
340  if (string == NULL)
341  {
343  return NULL;
344  }
345 
346  if (stx_mark_struct_visited (thread_p, bufptr, string) == ER_FAILED
347  || stx_build_string (thread_p, bufptr, string) == NULL)
348  {
349  return NULL;
350  }
351  }
352 
353  return string;
354 #else // CS_MODE
355  int dummy;
356  ptr = or_unpack_int (ptr, &dummy);
357  return NULL;
358 #endif // CS_MODE
359 }
360 
361 char *
363 {
364  int temp_int;
366 
367  ptr = or_unpack_int (ptr, &temp_int);
368  jtc.m_function = (json_table_column_function) temp_int;
369 
370  stx_restore (thread_p, ptr, jtc.m_output_value_pointer);
371 
373  {
375  return ptr;
376  }
377 
378  ptr = or_unpack_domain (ptr, &jtc.m_domain, NULL);
379 
380  jtc.m_path = stx_restore_string (thread_p, ptr);
381  jtc.m_column_name = stx_restore_string (thread_p, ptr);
382 
383  if (jtc.m_function == JSON_TABLE_EXISTS)
384  {
385  return ptr;
386  }
387 
388  ptr = stx_unpack (thread_p, ptr, jtc.m_on_error);
389  ptr = stx_unpack (thread_p, ptr, jtc.m_on_empty);
390 
391  return ptr;
392 }
393 
394 char *
396 {
397  int temp_int = 0;
398 
399  jtn.m_iterator = nullptr;
400 
401  jtn.m_path = stx_restore_string (thread_p, ptr);
402 
403  ptr = or_unpack_int (ptr, &temp_int);
404  jtn.m_output_columns_size = (size_t) temp_int;
405  if (jtn.m_output_columns_size > 0)
406  {
407  jtn.m_output_columns =
408  (json_table_column *) stx_alloc_struct (thread_p, (int) (sizeof (json_table_column) * jtn.m_output_columns_size));
409  for (size_t i = 0; i < jtn.m_output_columns_size; ++i)
410  {
411  jtn.m_output_columns[i].init ();
412  ptr = stx_build (thread_p, ptr, jtn.m_output_columns[i]);
413  }
414  }
415 
416  ptr = or_unpack_int (ptr, &temp_int);
417  jtn.m_nested_nodes_size = (size_t) temp_int;
418  if (jtn.m_nested_nodes_size > 0)
419  {
420  jtn.m_nested_nodes =
421  (json_table_node *) stx_alloc_struct (thread_p, (int) (sizeof (json_table_node) * jtn.m_nested_nodes_size));
422  for (size_t i = 0; i < jtn.m_nested_nodes_size; ++i)
423  {
424  jtn.m_nested_nodes[i].init ();
425  ptr = stx_build (thread_p, ptr, jtn.m_nested_nodes[i]);
426  }
427  }
428 
429  ptr = or_unpack_int (ptr, &temp_int);
430  jtn.m_id = (size_t) temp_int;
431 
432  ptr = or_unpack_int (ptr, &temp_int);
433  jtn.m_is_iterable_node = (bool) temp_int;
434 
435  return ptr;
436 }
437 
438 char *
439 stx_build (THREAD_ENTRY *thread_p, char *ptr, cubxasl::json_table::spec_node &json_table_spec)
440 {
441  json_table_spec.init ();
442 
443  int node_count;
444  ptr = or_unpack_int (ptr, &node_count);
445  json_table_spec.m_node_count = (size_t) (node_count);
446 
447  stx_restore (thread_p, ptr, json_table_spec.m_json_reguvar);
448 
449  stx_alloc (thread_p, json_table_spec.m_root_node);
450  assert (json_table_spec.m_root_node != NULL);
451 
452  json_table_spec.m_root_node->init ();
453  ptr = stx_build (thread_p, ptr, *json_table_spec.m_root_node);
454 
455  return ptr;
456 }
457 
458 char *
459 stx_build (THREAD_ENTRY *thread_p, char *ptr, db_value &val)
460 {
461  return stx_build_db_value (thread_p, ptr, &val);
462 }
463 
464 char *
465 stx_unpack (THREAD_ENTRY *thread_p, char *ptr, json_table_column_behavior &behavior)
466 {
467  int temp;
468 
469  ptr = or_unpack_int (ptr, &temp);
471 
472  if (behavior.m_behavior == JSON_TABLE_DEFAULT_VALUE)
473  {
474  behavior.m_default_value = (DB_VALUE *) stx_alloc_struct (thread_p, sizeof (DB_VALUE));
475  ptr = stx_build (thread_p, ptr, *behavior.m_default_value);
476  }
477 
478  return ptr;
479 }
480 
481 bool
483 {
484  if (first.m_function != second.m_function)
485  {
486  return false;
487  }
488 
489  return true;
490 }
491 
492 bool
494 {
495  if (first.m_output_columns_size != second.m_output_columns_size)
496  {
497  return false;
498  }
499 
500  if (first.m_nested_nodes_size != second.m_nested_nodes_size)
501  {
502  return false;
503  }
504 
505  if (first.m_id != second.m_id)
506  {
507  return false;
508  }
509 
510  if (first.m_is_iterable_node != second.m_is_iterable_node)
511  {
512  return false;
513  }
514 
515  return true;
516 }
517 
518 bool
520 {
521  if (first.m_node_count != second.m_node_count)
522  {
523  return false;
524  }
525  return true;
526 }
char * stx_alloc_struct(THREAD_ENTRY *thread_p, int size)
int stx_init_xasl_unpack_info(THREAD_ENTRY *thread_p, char *xasl_stream, int xasl_stream_size)
Definition: xasl_stream.cpp:72
#define UNPACK_SCALE
#define NO_ERROR
Definition: error_code.h:46
int stx_get_xasl_errcode(THREAD_ENTRY *thread_p)
Definition: xasl_stream.cpp:39
struct db_value * m_default_value
regu_variable_node * m_json_reguvar
UNPACK_EXTRA_BUF * additional_buffers
json_table_column_behavior m_on_empty
cubxasl::json_table::node json_table_node
#define ER_FAILED
Definition: error_code.h:47
char * stx_build_string(THREAD_ENTRY *thread_p, char *ptr, char *string)
#define assert_release(e)
Definition: error_manager.h:96
XASL_UNPACK_INFO * get_xasl_unpack_info_ptr(THREAD_ENTRY *thread_p)
TP_DOMAIN tp_Integer_domain
STX_VISITED_PTR * ptr_blocks[MAX_PTR_BLOCKS]
#define bool
Definition: dbi_compat.h:31
json_table_column_behavior m_on_error
char * stx_restore_string(THREAD_ENTRY *thread_p, char *&ptr)
void THREAD_ENTRY
int xasl_stream_make_align(int x)
const size_t START_PTR_PER_BLOCK
Definition: xasl_stream.hpp:47
json_table_column_behavior_type
void * stx_get_struct_visited_ptr(THREAD_ENTRY *thread_p, const void *ptr)
#define assert(x)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
json_table_column_function m_function
int stx_mark_struct_visited(THREAD_ENTRY *thread_p, const void *ptr, void *str)
int ptr_lwm[MAX_PTR_BLOCKS]
#define NULL
Definition: freelistheap.h:34
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
char * or_unpack_int(char *ptr, int *number)
json_table_column_function
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
void stx_restore(THREAD_ENTRY *thread_p, char *&ptr, T *&target)
void stx_alloc(THREAD_ENTRY *thread_p, T *&ptr)
struct xasl_unpack_info XASL_UNPACK_INFO
Definition: xasl.h:57
#define OR_GET_INT(ptr)
void set_xasl_unpack_info_ptr(THREAD_ENTRY *thread_p, XASL_UNPACK_INFO *ptr)
enum json_table_column_behavior_type m_behavior
void stx_free_visited_ptrs(THREAD_ENTRY *thread_p)
int i
Definition: dynamic_load.c:954
int ptr_max[MAX_PTR_BLOCKS]
const size_t MAX_PTR_BLOCKS
char * stx_unpack(THREAD_ENTRY *thread_p, char *ptr, json_table_column_behavior &behavior)
const void * ptr
void stx_set_xasl_errcode(THREAD_ENTRY *thread_p, int errcode)
Definition: xasl_stream.cpp:54
char * stx_build(THREAD_ENTRY *thread_p, char *ptr, cubxasl::json_table::column &jtc)
static int stx_Xasl_errcode
Definition: xasl_stream.cpp:31
char * or_unpack_domain(char *ptr, struct tp_domain **domain_ptr, int *is_null)
#define db_private_realloc(thrd, ptr, size)
Definition: memory_alloc.h:231
int xasl_stream_get_ptr_block(const void *ptr)
bool xasl_stream_compare(const cubxasl::json_table::column &first, const cubxasl::json_table::column &second)
cubxasl::json_table::column json_table_column
char * or_unpack_db_value(char *buffer, DB_VALUE *val)
UNPACK_EXTRA_BUF * next
char * stx_build_db_value(THREAD_ENTRY *thread_p, char *ptr, DB_VALUE *value)