CUBRID Engine  latest
db_virt.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  * db_virt.c - API functions related to virtual class.
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <ctype.h>
31 #include <assert.h>
32 
33 #include "authenticate.h"
34 #include "system_parameter.h"
35 #include "storage_common.h"
36 #include "db.h"
37 #include "class_object.h"
38 #include "object_print.h"
39 #include "server_interface.h"
40 #include "boot_cl.h"
41 #include "locator_cl.h"
42 #include "schema_manager.h"
43 #include "schema_template.h"
44 #include "object_accessor.h"
45 #include "object_primitive.h"
46 #include "set_object.h"
47 #include "virtual_object.h"
48 #include "parser.h"
49 #include "view_transform.h"
50 
51 #define ERROR_SET(error, code) \
52  do { \
53  error = code; \
54  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, code, 0); \
55  } while (0)
56 
57 
58 /*
59  * NAMELIST SUPPORT
60  */
61 
62 /*
63  * db_namelist_free() - This function frees a list of names that was returned
64  * by one of the other db_ functions. The links in the list and the strings
65  * themselves are both freed to it is not wise to cache pointers to the
66  * strings in the list.
67  * return : none
68  * list(in): a list of names (strings)
69  */
70 void
72 {
73  nlist_free (list);
74 }
75 
76 /*
77  * db_namelist_add() - This function adds the name to the list if it is not
78  * already present. The position that the name is added is undefined
79  * return : true if the element was added, false if it existed.
80  * list(in): a pointer to a list pointer.
81  * name(in): the name to add
82  */
83 int
84 db_namelist_add (DB_NAMELIST ** list, const char *name)
85 {
86  int error;
87  int status;
88 
90  CHECK_2ARGS_ZERO (list, name);
91 
92  error = nlist_add (list, name, NULL, &status);
93  if (!error)
94  {
95  status = false;
96  }
97  return status;
98 }
99 
100 /*
101  * db_namelist_append() - This function appends the name to the list if it
102  * isn't already present. The name will be placed at the end of the list
103  * return : true if the name was added, false if it existed
104  * list(in): pointer to pointer to list
105  * name(in): name to add
106  */
107 int
108 db_namelist_append (DB_NAMELIST ** list, const char *name)
109 {
110  int error;
111  int status;
112 
114  CHECK_2ARGS_ZERO (list, name);
115 
116  error = nlist_append (list, name, NULL, &status);
117  if (!error)
118  {
119  status = false;
120  }
121  return status;
122 }
123 
124 /*
125  * VCLASS CREATION
126  */
127 
128 /*
129  * db_create_vclass() - This function creates and returns a new virtual class
130  * with the given name. Initially, the virtual class is created with no
131  * definition. that is, it has no attributes, methods, or query
132  * specifications.
133  * If the name specified has already been used by an existing class in the
134  * database, NULL is returned. In this case, the system sets the global
135  * error status to indicate the exact nature of the error.
136  * return : new virtual class object
137  * name(in): the name of a virtual class
138  */
139 DB_OBJECT *
140 db_create_vclass (const char *name)
141 {
142  int error = NO_ERROR;
143  SM_TEMPLATE *def;
144  DB_OBJECT *virtual_class;
145  PR_TYPE *type;
146  OID class_oid = OID_INITIALIZER;
147 
150 
151  virtual_class = NULL;
152  if (name != NULL)
153  {
154  type = pr_find_type (name);
155  if (type != NULL || pt_is_reserved_word (name))
156  {
159  }
160  else
161  {
162  def = smt_def_typed_class (name, SM_VCLASS_CT);
163  if (def == NULL)
164  {
165  assert (er_errid () != NO_ERROR);
166  error = er_errid ();
167  }
168  else
169  {
170  if (locator_reserve_class_name (def->name, &class_oid) != LC_CLASSNAME_RESERVED)
171  {
172  assert_release (false);
173  smt_quit (def);
174  }
175  else
176  {
177  error = sm_update_class (def, &virtual_class);
178  if (error)
179  {
180  smt_quit (def);
181  }
182  }
183  }
184  }
185  }
186 
187  return (virtual_class);
188 }
189 
190 /*
191  * db_get_vclass_ldb_name() - This function returns the name of the ldb used
192  * with a virtual class. It simply makes a copy of the ldb name.
193  * return : ldb name used with virtual class
194  * op(in): class pointer
195  *
196  * note : The returned string must later be freed with db_string_free.
197  */
198 char *
200 {
201  return NULL;
202 }
203 
204 /*
205  * db_is_real_instance() - This function is used to determine whether an object
206  * is an instance of a class (real instance) or an instance of a virtual
207  * class (derived instance).
208  * returns: non-zero if the object is a real object, zero if the object is
209  * virtual class or an instance of a virtual class
210  * obj(in): object pointer
211  */
212 int
214 {
215  int retval;
216 
218  CHECK_1ARG_ZERO (obj);
219 
220  if (locator_is_class (obj, DB_FETCH_READ) > 0)
221  {
222  return 1;
223  }
224 
225  if (obj->is_vid)
226  {
227  retval = vid_is_base_instance (obj) ? 1 : 0;
228  return (retval);
229  }
230  else
231  {
232  return 1;
233  }
234 
235 }
236 
237 /*
238  * db_real_instance() - This function returns the object itself if the given
239  * object is a base object, or the real object derived from the given
240  * virtual object. A derived instance of a virtual class can only be
241  * associated with a single real instance. NULL is returned when the derived
242  * instance is not updatable. This is an identity function on real objects.
243  * return : the real object
244  * obj(in): virtual class instance
245  */
246 DB_OBJECT *
248 {
249  DB_OBJECT *retval;
250 
252  CHECK_1ARG_NULL (obj);
253 
254  if (db_is_real_instance (obj))
255  {
256  return obj;
257  }
258 
259  if (obj->is_vid)
260  {
261  retval = vid_base_instance (obj);
262  return (retval);
263  }
264  else
265  {
266  return (DB_OBJECT *) 0;
267  }
268 
269 }
270 
271 /*
272  * db_instance_equal() - This function returns a non-zero value if the given
273  * objects are equal. Two objects are equal if both are updatable and they
274  * represent the same object, or if both are non-updatable but their
275  * attributes are equal. If the objects are not equal, 0 is returned.
276  * return : < 0 if error, > 0 if obj1 is equal to obj2, 0 otherwise
277  * obj1(in): an object
278  * obj2(in): an object
279  */
280 int
282 {
283  int retval;
284  int obj1_is_updatable, obj2_is_updatable;
285  int is_class = 0;
286 
288  CHECK_2ARGS_ZERO (obj1, obj2);
289 
290  if (obj1 == obj2)
291  {
292  return 1;
293  }
294 
295  is_class = locator_is_class (obj1, DB_FETCH_READ);
296  if (is_class < 0)
297  {
298  return is_class;
299  }
300  if (is_class)
301  {
302  /* We have already checked obj1 pointer vs obj2 pointer. The classes cannot be equal if they are not the same
303  * MOP. */
304  return 0;
305  }
306  is_class = locator_is_class (obj2, DB_FETCH_READ);
307  if (is_class < 0)
308  {
309  return is_class;
310  }
311  if (is_class)
312  {
313  /* We have already checked obj1 pointer vs obj2 pointer. The classes cannot be equal if they are not the same
314  * MOP. */
315  return 0;
316  }
317 
318  obj1_is_updatable = db_is_updatable_object (obj1);
319  obj2_is_updatable = db_is_updatable_object (obj2);
320 
321  if (obj1_is_updatable && obj2_is_updatable)
322  {
323  retval = db_real_instance (obj1) == db_real_instance (obj2);
324  return (retval);
325  }
326  else if ((!obj1_is_updatable) && (!obj2_is_updatable))
327  {
328  retval = vid_compare_non_updatable_objects (obj1, obj2) ? 1 : 0;
329  return (retval);
330  }
331  return 0;
332 
333 }
334 
335 /*
336  * db_is_updatable_object() - This function returns non-zero if the given
337  * object is updatable.
338  * return : non-zero if object is updatable
339  * obj(in): A class, virtual class or instance object
340  */
341 int
343 {
344  int retval;
345  int error = NO_ERROR;
346  SM_CLASS *class_;
347 
349  CHECK_1ARG_ZERO (obj);
350 
351  if (locator_is_class (obj, DB_FETCH_READ) > 0)
352  {
353  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
354  {
355  switch (class_->class_type)
356  {
357  case SM_CLASS_CT:
358  return 1;
359  case SM_VCLASS_CT:
360  retval = (int) mq_is_updatable (obj);
361  return (retval);
362  default:
363  break;
364  }
365  }
366  else
367  {
369  return 0;
370  }
371  }
372  else
373  {
374  if (obj->is_vid)
375  {
376  retval = (int) vid_is_updatable (obj);
377  return (retval);
378  }
379  else
380  {
381  return 1;
382  }
383  }
384  return 0;
385 }
386 
387 /*
388  * db_is_updatable_attribute() - This function returns a non-zero value if the
389  * class or instance is updatable and if the attribute is updatable.
390  * return : non-zero if both the class and the attribute are updatable
391  * obj(in): An instance
392  * attr_name(in): An attribute name
393  */
394 int
395 db_is_updatable_attribute (DB_OBJECT * obj, const char *attr_name)
396 {
397  int retval;
398  int error = NO_ERROR;
399  SM_CLASS *class_;
400  DB_OBJECT *class_obj = NULL;
401  DB_OBJECT *real_obj = NULL;
402  DB_OBJECT *real_class_obj = NULL;
403 
405  CHECK_1ARG_ZERO (obj);
406 
407  if (locator_is_class (obj, DB_FETCH_WRITE) > 0)
408  {
410  return 0;
411  }
412  if (db_get_attribute_type (obj, attr_name) == DB_TYPE_NULL)
413  {
414  return 0;
415  }
416  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
417  {
418  switch (class_->class_type)
419  {
420  case SM_CLASS_CT:
421  return 1;
422  case SM_VCLASS_CT:
423  class_obj = db_get_class (obj);
424  real_obj = db_real_instance (obj);
425  if (real_obj)
426  {
427  real_class_obj = db_get_class (real_obj);
428  }
429  if (class_obj && real_class_obj)
430  {
431  retval = mq_is_updatable_attribute (class_obj, attr_name, real_class_obj) ? 1 : 0;
432  return (retval);
433  }
434  else
435  {
436  return 0;
437  }
438  break;
439  default:
440  break;
441  }
442  }
443  else
444  {
446  return 0;
447  }
448  return 0;
449 }
450 
451 /*
452  * db_add_query_spec() - This function adds a query to a virtual class.
453  * return : error code
454  * class(in): vrtual class
455  * query(in): query string
456  */
457 int
458 db_add_query_spec (MOP vclass, const char *query)
459 {
460  int error = NO_ERROR;
461  SM_TEMPLATE *def;
462  MOP newmop;
463 
466 
467  if ((vclass == NULL) || (query == NULL))
468  {
470  }
471  else
472  {
473  def = smt_edit_class_mop (vclass, AU_ALTER);
474  if (def == NULL)
475  {
476  assert (er_errid () != NO_ERROR);
477  error = er_errid ();
478  }
479  else
480  {
481  error = smt_add_query_spec (def, query);
482  if (error)
483  {
484  smt_quit (def);
485  }
486  else
487  {
488  error = sm_update_class (def, &newmop);
489  if (error)
490  {
491  smt_quit (def);
492  }
493  }
494  }
495  }
496 
497  return (error);
498 }
499 
500 /*
501  * db_drop_query_spec() -
502  * return:
503  * vclass(in) :
504  * query_no(in) :
505  */
506 int
507 db_drop_query_spec (DB_OBJECT * vclass, const int query_no)
508 {
509  int error = NO_ERROR;
510  SM_TEMPLATE *def;
511  MOP newmop;
512 
515 
516  if (vclass == NULL)
517  {
519  }
520  else
521  {
522  def = smt_edit_class_mop (vclass, AU_ALTER);
523  if (def == NULL)
524  {
525  assert (er_errid () != NO_ERROR);
526  error = er_errid ();
527  }
528  else
529  {
530  error = smt_drop_query_spec (def, query_no);
531  if (error)
532  {
533  smt_quit (def);
534  }
535  else
536  {
537  error = sm_update_class (def, &newmop);
538  if (error)
539  {
540  smt_quit (def);
541  }
542  }
543  }
544  }
545 
546  return (error);
547 }
548 
549 
550 /*
551  * db_change_query_spec() -
552  * return:
553  * vclass(in) :
554  * new_query(in) :
555  * query_no(in) :
556  */
557 int
558 db_change_query_spec (DB_OBJECT * vclass, const char *new_query, const int query_no)
559 {
560 
561  int error = NO_ERROR;
562  SM_TEMPLATE *def;
563  MOP newmop;
564 
567 
568  if (vclass == NULL)
569  {
571  }
572  else
573  {
574  def = smt_edit_class_mop (vclass, AU_ALTER);
575  if (def == NULL)
576  {
577  assert (er_errid () != NO_ERROR);
578  error = er_errid ();
579  }
580  else
581  {
582  error = smt_change_query_spec (def, new_query, query_no);
583  if (error)
584  {
585  smt_quit (def);
586  }
587  else
588  {
589  error = sm_update_class (def, &newmop);
590  if (error)
591  {
592  smt_quit (def);
593  }
594  }
595  }
596  }
597 
598  return (error);
599 }
600 
601 /*
602  * db_get_query_specs() - This function returns a list of query_spec
603  * descriptors for a virtual class.
604  * return : list of query specifications
605  * obj(in): class or instance
606  */
609 {
610  SM_QUERY_SPEC *query_spec;
611  SM_CLASS *class_;
612 
614 
615  query_spec = NULL;
616 
617  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
618  {
619  query_spec = class_->query_spec;
620  }
621 
622  return ((DB_QUERY_SPEC *) query_spec);
623 }
624 
625 /*
626  * db_query_spec_next() - This function returns the next query_spec descriptor
627  * in the list or NULL if you're at the end of the list.
628  * return : query_spec descriptor
629  * query_spec(in): query_spec descriptor
630  */
633 {
634  DB_QUERY_SPEC *next = NULL;
635 
636  if (query_spec != NULL)
637  {
638  next = query_spec->next;
639  }
640 
641  return (next);
642 }
643 
644 /*
645  * db_query_spec_string() - This function returns the string defining the
646  * virtual query
647  * return : query specification string
648  * query_spec(in): query_spec descriptor
649  */
650 const char *
652 {
653  const char *spec = NULL;
654 
655  if (query_spec != NULL)
656  {
657  spec = query_spec->specification;
658  }
659 
660  return (spec);
661 }
662 
663 /*
664  * db_get_object_id() - This function gets object_id for the vclass on ldb
665  * return : odject id name list
666  * class(in): virtual class
667  */
668 DB_NAMELIST *
670 {
671  return NULL;
672 }
673 
674 /*
675  * db_is_vclass() - This function returns a > 0 value if and only if the
676  * object is a virtual class.
677  * return : < 0 if error, > 0 if the object is a virtual class, = 0 otherwise
678  * op(in): class pointer
679  */
680 int
682 {
683  SM_CLASS *class_ = NULL;
684  int error = 0;
685 
687 
688  if (op == NULL)
689  {
690  return 0;
691  }
692  error = locator_is_class (op, DB_FETCH_READ);
693  if (error <= 0)
694  {
695  return error;
696  }
697  error = au_fetch_class_force (op, &class_, AU_FETCH_READ);
698  if (error < 0)
699  {
700  return error;
701  }
702  if (sm_get_class_type (class_) != SM_VCLASS_CT)
703  {
704  return 0;
705  }
706  return 1;
707 }
#define OID_INITIALIZER
Definition: oid.h:36
#define CHECK_MODIFICATION_ERROR()
Definition: db.h:121
#define NO_ERROR
Definition: error_code.h:46
#define CHECK_CONNECT_FALSE()
Definition: db.h:103
int smt_quit(SM_TEMPLATE *template_)
int db_namelist_add(DB_NAMELIST **list, const char *name)
Definition: db_virt.c:84
DB_OBJECT * db_real_instance(DB_OBJECT *obj)
Definition: db_virt.c:247
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
bool vid_compare_non_updatable_objects(MOP mop1, MOP mop2)
char * db_get_vclass_ldb_name(DB_OBJECT *op)
Definition: db_virt.c:199
void db_namelist_free(DB_NAMELIST *list)
Definition: db_virt.c:71
void nlist_free(DB_NAMELIST *list)
Definition: work_space.c:4344
#define assert_release(e)
Definition: error_manager.h:96
int db_add_query_spec(MOP vclass, const char *query)
Definition: db_virt.c:458
SM_CLASS_TYPE sm_get_class_type(SM_CLASS *class_)
#define ER_WS_NO_CLASS_FOR_INSTANCE
Definition: error_code.h:403
DB_OBJECT * db_create_vclass(const char *name)
Definition: db_virt.c:140
int er_errid(void)
bool pt_is_reserved_word(const char *text)
Definition: keyword.c:697
#define AU_ALTER
Definition: authenticate.h:73
#define CHECK_2ARGS_ZERO(obj1, obj2)
Definition: db.h:207
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
#define CHECK_1ARG_ZERO(obj)
Definition: db.h:201
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
bool mq_is_updatable_attribute(DB_OBJECT *vclass_object, const char *attr_name, DB_OBJECT *real_class_object)
#define assert(x)
int smt_drop_query_spec(SM_TEMPLATE *def, const int index)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
int db_change_query_spec(DB_OBJECT *vclass, const char *new_query, const int query_no)
Definition: db_virt.c:558
#define CHECK_MODIFICATION_NULL()
Definition: db.h:124
DB_NAMELIST * db_get_object_id(MOP vclass)
Definition: db_virt.c:669
struct sm_query_spec * next
Definition: class_object.h:683
int db_is_updatable_attribute(DB_OBJECT *obj, const char *attr_name)
Definition: db_virt.c:395
bool vid_is_base_instance(MOP mop)
#define CHECK_1ARG_NULL(obj)
Definition: db.h:171
const char * db_query_spec_string(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:651
DB_TYPE db_get_attribute_type(MOP obj, const char *name)
Definition: db_old.c:647
int smt_change_query_spec(SM_TEMPLATE *def, const char *query, const int index)
bool mq_is_updatable(DB_OBJECT *class_object)
#define NULL
Definition: freelistheap.h:34
DB_OBJECT * db_get_class(MOP obj)
Definition: db_info.c:589
int db_is_real_instance(DB_OBJECT *obj)
Definition: db_virt.c:213
SM_TEMPLATE * smt_edit_class_mop(MOP op, DB_AUTH db_auth_type)
int nlist_append(DB_NAMELIST **list, const char *name, NLSEARCHER fcn, int *added_ptr)
Definition: work_space.c:4198
int db_is_updatable_object(DB_OBJECT *obj)
Definition: db_virt.c:342
SM_QUERY_SPEC * query_spec
Definition: class_object.h:745
int db_drop_query_spec(DB_OBJECT *vclass, const int query_no)
Definition: db_virt.c:507
static void error(const char *msg)
Definition: gencat.c:331
bool vid_is_updatable(MOP mop)
PR_TYPE * pr_find_type(const char *name)
#define AU_SELECT
Definition: authenticate.h:69
#define CHECK_CONNECT_NULL()
Definition: db.h:91
#define ARG_FILE_LINE
Definition: error_manager.h:44
const char * name
Definition: class_object.h:787
int nlist_add(DB_NAMELIST **list, const char *name, NLSEARCHER fcn, int *added_ptr)
Definition: work_space.c:4147
#define ER_SM_CLASS_WITH_PRIM_NAME
Definition: error_code.h:305
LC_FIND_CLASSNAME locator_reserve_class_name(const char *class_name, OID *class_oid)
Definition: locator_cl.c:179
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
int smt_add_query_spec(SM_TEMPLATE *template_, const char *specification)
SM_CLASS_TYPE class_type
Definition: class_object.h:713
#define CHECK_CONNECT_ZERO()
Definition: db.h:94
const char * specification
Definition: class_object.h:685
MOP vid_base_instance(MOP mop)
DB_QUERY_SPEC * db_get_query_specs(DB_OBJECT *obj)
Definition: db_virt.c:608
SM_TEMPLATE * smt_def_typed_class(const char *name, SM_CLASS_TYPE ct)
#define ERROR_SET(error, code)
Definition: db_virt.c:51
int db_instance_equal(DB_OBJECT *obj1, DB_OBJECT *obj2)
Definition: db_virt.c:281
int locator_is_class(MOP mop, DB_FETCH_MODE hint_purpose)
Definition: locator_cl.c:239
int db_namelist_append(DB_NAMELIST **list, const char *name)
Definition: db_virt.c:108
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
#define CHECK_CONNECT_ERROR()
Definition: db.h:88
unsigned is_vid
Definition: work_space.h:148
int sm_update_class(SM_TEMPLATE *template_, MOP *classmop)
DB_QUERY_SPEC * db_query_spec_next(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:632