CUBRID Engine  latest
query_method.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * query_method.c - Method calls in queries
21  */
22 
23 #ident "$Id$"
24 
25 #include "query_method.h"
26 
27 #include "authenticate.h"
28 #include "config.h"
29 #include "db.h"
30 #include "dbtype.h"
31 #include "jsp_cl.h"
32 #include "method_def.hpp"
33 #include "network.h"
34 #include "network_interface_cl.h"
35 #include "object_accessor.h"
36 #include "object_primitive.h"
37 #include "object_representation.h"
38 #include "query_list.h"
39 #include "regu_var.hpp"
40 
41 static int method_initialize_vacomm_buffer (VACOMM_BUFFER * vacomm_buffer, unsigned int rc, char *host,
42  char *server_name);
46 static void methid_sig_freemem (method_sig_node * meth_sig);
47 
48 /*
49  * method_clear_vacomm_buffer () - Clears the comm buffer
50  * return:
51  * vacomm_buffer(in) : Transmission buffer
52  */
53 static void
55 {
56  if (vacomm_buffer_p)
57  {
58  free_and_init (vacomm_buffer_p->area);
59  free_and_init (vacomm_buffer_p->host);
60  free_and_init (vacomm_buffer_p->server_name);
61  }
62 }
63 
64 /*
65  * method_initialize_vacomm_buffer () - Initializes the comm buffer
66  * return:
67  * vacomm_buffer(in) :
68  * rc(in) : client transmission request ID
69  * host(in) :
70  * server_name(in) :
71  */
72 static int
73 method_initialize_vacomm_buffer (VACOMM_BUFFER * vacomm_buffer_p, unsigned int rc, char *host_p, char *server_name_p)
74 {
75  vacomm_buffer_p->rc = rc;
76  vacomm_buffer_p->server_name = NULL;
77  vacomm_buffer_p->area = NULL;
78 
79  vacomm_buffer_p->host = strdup (host_p);
80  if (vacomm_buffer_p->host == NULL)
81  {
82  method_clear_vacomm_buffer (vacomm_buffer_p);
85  }
86 
87  vacomm_buffer_p->server_name = strdup (server_name_p);
88  if (vacomm_buffer_p->server_name == NULL)
89  {
90  method_clear_vacomm_buffer (vacomm_buffer_p);
91  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) (strlen (server_name_p) + 1));
93  }
94 
95  vacomm_buffer_p->area = (char *) malloc (VACOMM_BUFFER_SIZE);
96  if (vacomm_buffer_p->area == NULL)
97  {
98  method_clear_vacomm_buffer (vacomm_buffer_p);
101  }
102 
103  vacomm_buffer_p->buffer = vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_SIZE;
104  vacomm_buffer_p->num_vals = 0;
105  vacomm_buffer_p->cur_pos = 0;
107  vacomm_buffer_p->action = VACOMM_BUFFER_SEND;
108 
109  return NO_ERROR;
110 }
111 
112 /*
113  * method_send_value_to_server () -
114  * return:
115  * dbval(in) : value
116  * vacomm_buffer(in) : Transmission buffer
117  *
118  * Note: If the db_value will fit into the transmission buffer,
119  * pack it into the buffer. Otherwise, if the buffer is empty,
120  * expand it, else send the buffer to the server and then pack
121  * the value into the buffer.
122  */
123 static int
124 method_send_value_to_server (DB_VALUE * dbval_p, VACOMM_BUFFER * vacomm_buffer_p)
125 {
126  int dbval_length;
127  char *new_area_p, *p;
128  int error = 0;
129  int length;
130  int action;
131 
132  dbval_length = OR_VALUE_ALIGNED_SIZE (dbval_p);
133  while ((vacomm_buffer_p->cur_pos + dbval_length) > vacomm_buffer_p->size)
134  {
135  if (vacomm_buffer_p->cur_pos == 0)
136  {
137  new_area_p = (char *) realloc (vacomm_buffer_p->area, dbval_length + VACOMM_BUFFER_HEADER_SIZE);
138  if (new_area_p == NULL)
139  {
141  (size_t) (dbval_length + VACOMM_BUFFER_HEADER_SIZE));
143  }
144 
145  vacomm_buffer_p->area = new_area_p;
146  vacomm_buffer_p->buffer = (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_SIZE);
147  vacomm_buffer_p->size = dbval_length;
148  }
149  else
150  {
151  if (vacomm_buffer_p->action == VACOMM_BUFFER_SEND)
152  {
153  length = vacomm_buffer_p->cur_pos + VACOMM_BUFFER_HEADER_SIZE;
154  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_LENGTH_OFFSET, length);
155  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_STATUS_OFFSET, (int) METHOD_SUCCESS);
156  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_NO_VALS_OFFSET, vacomm_buffer_p->num_vals);
157  error =
158  net_client_send_data (vacomm_buffer_p->host, vacomm_buffer_p->rc, vacomm_buffer_p->area,
159  vacomm_buffer_p->cur_pos + VACOMM_BUFFER_HEADER_SIZE);
160  if (error != NO_ERROR)
161  {
162  return ER_FAILED;
163  }
164 
165  error = net_client_receive_action (vacomm_buffer_p->rc, &action);
166  if (error)
167  {
168  return ER_FAILED;
169  }
170 
171  vacomm_buffer_p->action = action;
172  if (vacomm_buffer_p->action != VACOMM_BUFFER_SEND)
173  {
174  return ER_FAILED;
175  }
176  }
177  vacomm_buffer_p->cur_pos = 0;
178  vacomm_buffer_p->num_vals = 0;
179  }
180  }
181 
182  ++vacomm_buffer_p->num_vals;
183  p = or_pack_db_value (vacomm_buffer_p->buffer + vacomm_buffer_p->cur_pos, dbval_p);
184 
185 #if !defined(NDEBUG)
186  /* suppress valgrind UMW error */
187  do
188  {
189  char *new_pos = vacomm_buffer_p->buffer + vacomm_buffer_p->cur_pos + dbval_length;
190 
191  if (new_pos > p)
192  {
193  memset (p, 0, new_pos - p);
194  }
195  }
196  while (0);
197 #endif
198 
199  vacomm_buffer_p->cur_pos += dbval_length;
200  return NO_ERROR;
201 }
202 
203 /*
204  * method_send_eof_to_server () -
205  * return:
206  * vacomm_buffer(in) : Transmission buffer
207  *
208  * Note: Send the transmission buffer to the server and indicate EOF.
209  */
210 static int
212 {
213  int length, error;
214  char *p;
215 
216  length = vacomm_buffer_p->cur_pos + VACOMM_BUFFER_HEADER_SIZE;
217  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_LENGTH_OFFSET, length);
218  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_STATUS_OFFSET, (int) METHOD_EOF);
219  p = or_pack_int (vacomm_buffer_p->area + VACOMM_BUFFER_HEADER_NO_VALS_OFFSET, vacomm_buffer_p->num_vals);
220 
221  error =
222  net_client_send_data (vacomm_buffer_p->host, vacomm_buffer_p->rc, vacomm_buffer_p->area,
223  vacomm_buffer_p->cur_pos + VACOMM_BUFFER_HEADER_SIZE);
224 
225  if (error != NO_ERROR)
226  {
227  return ER_FAILED;
228  }
229 
230  return NO_ERROR;
231 }
232 
233 /*
234  * method_send_error_to_server () - Send an error indication to the server
235  * return:
236  * rc(in) : enquiry return code
237  * host(in) : host name
238  * server_name(in) : server name
239  */
240 int
241 method_send_error_to_server (unsigned int rc, char *host_p, char *server_name_p)
242 {
243  char *p;
245  int error;
246 
250 
251  error = net_client_send_data (host_p, rc, area, VACOMM_BUFFER_HEADER_SIZE);
252 
253  if (error != NO_ERROR)
254  {
255  return ER_FAILED;
256  }
257 
258  return NO_ERROR;
259 }
260 
261 /*
262  * method_invoke_for_server () -
263  * return: int
264  * rc(in) :
265  * host(in) :
266  * server_name(in) :
267  * list_id(in) : List ID for objects & arguments
268  * method_sig_list(in): Method signatures
269  */
270 int
271 method_invoke_for_server (unsigned int rc, char *host_p, char *server_name_p, qfile_list_id * list_id_p,
272  method_sig_list * method_sig_list_p)
273 {
274  DB_VALUE *val_list_p = NULL;
275  DB_VALUE **values_p;
276  int *oid_cols;
278  int turn_on_auth = 1;
279  int cursor_result;
280  int num_method;
281  int num_args;
282  int pos;
283  int arg;
284  int value_count;
285  DB_VALUE value;
286  METHOD_SIG *meth_sig_p;
287  int error = NO_ERROR;
289  int count;
290  DB_VALUE *value_p;
291 
292  db_make_null (&value);
293 
294  if (method_initialize_vacomm_buffer (&vacomm_buffer, rc, host_p, server_name_p) != NO_ERROR)
295  {
296  return ER_FAILED;
297  }
298 
299  meth_sig_p = method_sig_list_p->method_sig;
300  value_count = 0;
301 
302  for (num_method = 0; num_method < method_sig_list_p->num_methods; num_method++)
303  {
304  value_count += meth_sig_p->num_method_args + 1;
305  meth_sig_p = meth_sig_p->next;
306  }
307 
308  if (list_id_p->type_list.type_cnt > value_count)
309  {
310  value_count = list_id_p->type_list.type_cnt;
311  }
312 
313  val_list_p = (DB_VALUE *) malloc (sizeof (DB_VALUE) * value_count);
314  if (val_list_p == NULL)
315  {
317  method_clear_vacomm_buffer (&vacomm_buffer);
318  return ER_FAILED;
319  }
320 
321  for (count = 0, value_p = val_list_p; count < value_count; count++, value_p++)
322  {
323  db_make_null (value_p);
324  }
325 
326  values_p = (DB_VALUE **) malloc (sizeof (DB_VALUE *) * (value_count + 1));
327  if (values_p == NULL)
328  {
329  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (DB_VALUE *) * (value_count + 1));
330  method_clear_vacomm_buffer (&vacomm_buffer);
331  free_and_init (val_list_p);
332  return ER_FAILED;
333  }
334 
335  oid_cols = (int *) malloc (sizeof (int) * method_sig_list_p->num_methods);
336  if (oid_cols == NULL)
337  {
339  sizeof (int) * method_sig_list_p->num_methods);
340  method_clear_vacomm_buffer (&vacomm_buffer);
341  free_and_init (val_list_p);
342  free_and_init (values_p);
343  return ER_FAILED;
344  }
345 
346  meth_sig_p = method_sig_list_p->method_sig;
347  for (num_method = 0; num_method < method_sig_list_p->num_methods; num_method++)
348  {
349  oid_cols[num_method] = meth_sig_p->method_arg_pos[0];
350  meth_sig_p = meth_sig_p->next;
351  }
352 
353  if (!cursor_open (&cursor_id, list_id_p, false, false))
354  {
355  method_clear_vacomm_buffer (&vacomm_buffer);
356  free_and_init (values_p);
357  free_and_init (val_list_p);
358  free_and_init (oid_cols);
359  return ER_FAILED;
360  }
361 
362  /* tfile_vfid pointer as query id for method scan */
363  cursor_id.query_id = (QUERY_ID) list_id_p->tfile_vfid;
364 
365  cursor_set_oid_columns (&cursor_id, oid_cols, method_sig_list_p->num_methods);
366 
367  while (true)
368  {
369  cursor_result = cursor_next_tuple (&cursor_id);
370  if (cursor_result != DB_CURSOR_SUCCESS)
371  {
372  break;
373  }
374 
375  if (cursor_get_tuple_value_list (&cursor_id, list_id_p->type_list.type_cnt, val_list_p) != NO_ERROR)
376  {
377  cursor_result = -1;
378  goto end;
379  }
380 
381  for (num_method = 0, meth_sig_p = method_sig_list_p->method_sig; num_method < method_sig_list_p->num_methods;
382  ++num_method, meth_sig_p = meth_sig_p->next)
383  {
384  /* The first position # is for the object ID */
385  num_args = meth_sig_p->num_method_args + 1;
386  for (arg = 0; arg < num_args; ++arg)
387  {
388  pos = meth_sig_p->method_arg_pos[arg];
389  values_p[arg] = &val_list_p[pos];
390  }
391 
392  values_p[num_args] = (DB_VALUE *) 0;
393  db_make_null (&value);
394 
395  if (meth_sig_p->class_name != NULL)
396  {
397  /* Don't call the method if the object is NULL or it has been deleted. A method call on a NULL object is
398  * NULL. */
399  if (!DB_IS_NULL (values_p[0]))
400  {
401  error = db_is_any_class (db_get_object (values_p[0]));
402  if (error == 0)
403  {
404  error = db_is_instance (db_get_object (values_p[0]));
405  }
406  }
407  if (error == ER_HEAP_UNKNOWN_OBJECT)
408  {
409  error = NO_ERROR;
410  }
411  else if (error > 0)
412  {
413  /* methods must run with authorization turned on and database modifications turned off. */
414  turn_on_auth = 0;
415  AU_ENABLE (turn_on_auth);
417  error = obj_send_array (db_get_object (values_p[0]), meth_sig_p->method_name, &value, &values_p[1]);
419  AU_DISABLE (turn_on_auth);
420  }
421  }
422  else
423  {
424  /* java stored procedure call */
425  turn_on_auth = 0;
426  AU_ENABLE (turn_on_auth);
428  error = jsp_call_from_server (&value, values_p, meth_sig_p->method_name, meth_sig_p->num_method_args);
430  AU_DISABLE (turn_on_auth);
431  }
432 
433  if (error != NO_ERROR)
434  {
435  cursor_result = -1;
436  goto end;
437  }
438 
439  if (DB_VALUE_TYPE (&value) == DB_TYPE_ERROR)
440  {
441  if (er_errid () == NO_ERROR) /* caller has not set an error */
442  {
444  }
445  cursor_result = -1;
446  goto end;
447  }
448 
449  error = method_send_value_to_server (&value, &vacomm_buffer);
450  if (error != NO_ERROR)
451  {
452  if (vacomm_buffer.action == VACOMM_BUFFER_ABORT)
453  {
454  cursor_result = DB_CURSOR_END;
455  }
456  else
457  {
458  cursor_result = -1;
459  }
460  goto end;
461  }
462 
463  pr_clear_value (&value);
464  }
465 
466  for (count = 0, value_p = val_list_p; count < value_count; count++, value_p++)
467  {
468  pr_clear_value (value_p);
469  }
470  }
471 
472 end:
473  cursor_close (&cursor_id);
474  free_and_init (values_p);
475 
476  pr_clear_value (&value);
477  for (count = 0, value_p = val_list_p; count < value_count; count++, value_p++)
478  {
479  pr_clear_value (value_p);
480  }
481 
482  free_and_init (val_list_p);
483  free_and_init (oid_cols);
484 
485  if (cursor_result == DB_CURSOR_END)
486  {
487  error = method_send_eof_to_server (&vacomm_buffer);
488  method_clear_vacomm_buffer (&vacomm_buffer);
489  return error;
490  }
491  else
492  {
493  method_clear_vacomm_buffer (&vacomm_buffer);
494  return ER_FAILED;
495  }
496 }
497 
498 /*
499  * methid_sig_freemem () -
500  * return:
501  * method_sig(in) : pointer to a method_sig
502  *
503  * Note: Free function for METHOD_SIG using free_and_init.
504  */
505 static void
507 {
508  if (method_sig != NULL)
509  {
510  methid_sig_freemem (method_sig->next);
514  db_private_free_and_init (NULL, method_sig);
515  }
516 }
517 
518 /*
519  * method_sig_list_freemem () -
520  * return:
521  * meth_sig_list(in) : pointer to a meth_sig_list
522  *
523  * Note: Free function for METHOD_SIG_LIST using free_and_init.
524  */
525 void
527 {
528  if (meth_sig_list != NULL)
529  {
530  methid_sig_freemem (meth_sig_list->method_sig);
531  db_private_free_and_init (NULL, meth_sig_list);
532  }
533 }
#define NO_ERROR
Definition: error_code.h:46
#define AU_DISABLE(save)
Definition: authenticate.h:106
int jsp_call_from_server(DB_VALUE *returnval, DB_VALUE **argarray, const char *name, const int arg_cnt)
Definition: jsp_cl.c:2999
static int method_send_value_to_server(DB_VALUE *dbval, VACOMM_BUFFER *vacomm_buffer)
Definition: query_method.c:124
struct qmgr_temp_file * tfile_vfid
Definition: query_list.h:440
QFILE_TUPLE_VALUE_TYPE_LIST type_list
Definition: query_list.h:428
METHOD_SIG * method_sig
Definition: method_def.hpp:69
char * method_name
Definition: method_def.hpp:57
#define VACOMM_BUFFER_SIZE
Definition: query_method.h:34
#define ER_FAILED
Definition: error_code.h:47
char * or_pack_db_value(char *buffer, DB_VALUE *var)
int cursor_next_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1482
int db_is_instance(MOP obj)
Definition: db_info.c:394
static int method_initialize_vacomm_buffer(VACOMM_BUFFER *vacomm_buffer, unsigned int rc, char *host, char *server_name)
Definition: query_method.c:73
int db_is_any_class(MOP obj)
Definition: db_info.c:356
int er_errid(void)
#define VACOMM_BUFFER_HEADER_LENGTH_OFFSET
Definition: method_def.hpp:40
#define VACOMM_BUFFER_HEADER_ERROR_OFFSET
Definition: method_def.hpp:43
METHOD_SIG * next
Definition: method_def.hpp:56
int net_client_send_data(char *host, unsigned int rc, char *databuf, int datasize)
Definition: network_cl.c:4010
int method_invoke_for_server(unsigned int rc, char *host_p, char *server_name_p, qfile_list_id *list_id_p, method_sig_list *method_sig_list_p)
Definition: query_method.c:271
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define OR_VALUE_ALIGNED_SIZE(value)
int obj_send_array(MOP obj, const char *name, DB_VALUE *returnval, DB_VALUE **argarray)
int * method_arg_pos
Definition: method_def.hpp:61
int cursor_set_oid_columns(CURSOR_ID *cursor_id_p, int *oid_col_no_p, int oid_col_no_cnt)
Definition: cursor.c:1322
DB_OBJECT * db_get_object(const DB_VALUE *value)
QUERY_ID query_id
Definition: cursor.h:54
#define NULL
Definition: freelistheap.h:34
int db_enable_modification(void)
Definition: db_admin.c:1015
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
static void method_clear_vacomm_buffer(VACOMM_BUFFER *vacomm_buffer)
Definition: query_method.c:54
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int pr_clear_value(DB_VALUE *value)
int net_client_receive_action(int rc, int *action)
Definition: network_cl.c:4037
char * server_name
Definition: query_method.h:40
static void error(const char *msg)
Definition: gencat.c:331
static int rc
Definition: serial.c:50
char * or_pack_int(char *ptr, int number)
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define AU_ENABLE(save)
Definition: authenticate.h:113
int db_disable_modification(void)
Definition: db_admin.c:1001
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
#define VACOMM_BUFFER_HEADER_NO_VALS_OFFSET
Definition: method_def.hpp:42
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
int method_send_error_to_server(unsigned int rc, char *host_p, char *server_name_p)
Definition: query_method.c:241
static int method_send_eof_to_server(VACOMM_BUFFER *vacomm_buffer)
Definition: query_method.c:211
void cursor_close(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1381
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int db_make_null(DB_VALUE *value)
static void methid_sig_freemem(method_sig_node *meth_sig)
Definition: query_method.c:506
#define DB_IS_NULL(value)
Definition: dbtype.h:63
void method_sig_list_freemem(method_sig_list *meth_sig_list)
Definition: query_method.c:526
char * strdup(const char *str)
Definition: porting.c:901
#define VACOMM_BUFFER_HEADER_SIZE
Definition: method_def.hpp:39
#define VACOMM_BUFFER_HEADER_STATUS_OFFSET
Definition: method_def.hpp:41
static char * host
#define DB_CURSOR_END
Definition: dbtype_def.h:167
bool cursor_open(CURSOR_ID *cursor_id_p, QFILE_LIST_ID *list_id_p, bool updatable, bool is_oid_included)
Definition: cursor.c:1194
const char ** p
Definition: dynamic_load.c:945
int cursor_get_tuple_value_list(CURSOR_ID *cursor_id_p, int size, DB_VALUE *value_list_p)
Definition: cursor.c:1778