CUBRID Engine  latest
object_accessor.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  * object_accessor.c - Object accessor module.
21  *
22  * This contains code for attribute and method access, instance creation
23  * and deletion, and misc utilitities related to instances.
24  */
25 
26 #ident "$Id$"
27 
28 #include "config.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <assert.h>
35 
36 #include "chartype.h"
37 #include "error_manager.h"
38 #include "system_parameter.h"
39 #include "server_interface.h"
40 #include "dbtype.h"
41 #include "work_space.h"
42 #include "object_domain.h"
43 #include "object_primitive.h"
44 #include "object_representation.h"
45 #include "set_object.h"
46 #include "class_object.h"
47 #include "schema_manager.h"
48 #include "object_accessor.h"
49 #include "authenticate.h"
50 #include "db.h"
51 #include "locator_cl.h"
52 #include "virtual_object.h"
53 #include "parser.h"
54 #include "transaction_cl.h"
55 #include "trigger_manager.h"
56 #include "view_transform.h"
57 #include "network_interface_cl.h"
58 
59 #include "dbtype.h"
60 
61 /*
62  * OBJ_MAX_ARGS
63  *
64  * Note :
65  * This is the maximum number of arguments currently supported
66  * This should be unlimited when we have full support for overflow
67  * argument lists.
68  *
69  */
70 
71 #define OBJ_MAX_ARGS 32
72 #define MAX_DOMAIN_NAME 128
73 
74 typedef enum
75 {
80 
81 /*
82  * argstate
83  *
84  * Note :
85  * This structure is built during the processing of a method call.
86  * It contains the cannonical internal representation of the method
87  * argument lists and other associated information.
88  * There are several functions that invoke methods, each with its own
89  * style of argument passing (stack, va_list, DB_VALUE_LIST, etc). All
90  * of these will translate their arguments into this form for further
91  * processing.
92  *
93  */
94 
95 typedef struct argstate
96 {
101  int nargs;
104 } ARGSTATE;
105 
107 
108 static int forge_flag_pat = 0;
109 static int obj_Method_call_level = 0;
110 
112  AU_FETCHMODE fetchmode);
113 
114 static int find_attribute (SM_CLASS ** classp, SM_ATTRIBUTE ** attp, MOP op, const char *name, int for_write);
115 static int find_shared_attribute (SM_CLASS ** classp, SM_ATTRIBUTE ** attp, MOP op, const char *name, int for_write);
116 static int assign_null_value (MOP op, SM_ATTRIBUTE * att, char *mem);
117 static int assign_set_value (MOP op, SM_ATTRIBUTE * att, char *mem, SETREF * setref);
118 
119 static int obj_set_att (MOP op, SM_CLASS * class_, SM_ATTRIBUTE * att, DB_VALUE * value, SM_VALIDATION * valid);
120 
121 static int get_object_value (MOP op, SM_ATTRIBUTE * att, char *mem, DB_VALUE * source, DB_VALUE * dest);
122 static int get_set_value (MOP op, SM_ATTRIBUTE * att, char *mem, DB_VALUE * source, DB_VALUE * dest);
123 
124 
125 static int obj_get_temp (DB_OBJECT * obj, SM_CLASS * class_, SM_ATTRIBUTE * att, DB_VALUE * value);
126 static int obj_set_temp (DB_OBJECT * obj, SM_ATTRIBUTE * att, DB_VALUE * value);
127 
128 static void argstate_from_list (ARGSTATE * state, DB_VALUE_LIST * arglist);
129 static void argstate_from_array (ARGSTATE * state, DB_VALUE ** argarray);
130 static void argstate_from_va (ARGSTATE * state, va_list args, int nargs);
131 static void cleanup_argstate (ARGSTATE * state);
132 static int call_method (METHOD_FUNCTION method, MOP obj, DB_VALUE * returnval, int nargs, DB_VALUE ** values,
133  DB_VALUE_LIST * overow);
134 static int check_args (SM_METHOD * method, ARGSTATE * state);
135 static int obj_send_method_va (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval, va_list args);
136 
137 static int obj_send_method_list (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval,
138  DB_VALUE_LIST * arglist);
139 
140 static int obj_send_method_array (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval,
141  DB_VALUE ** argarray);
142 
143 static MOP find_unique (MOP classop, SM_ATTRIBUTE * att, DB_VALUE * value, AU_FETCHMODE fetchmode);
144 static int flush_temporary_OID (MOP classop, DB_VALUE * key);
145 
146 static DB_VALUE *obj_make_key_value (DB_VALUE * key, const DB_VALUE * values[], int size);
147 
148 /* ATTRIBUTE LOCATION */
149 
150 /*
151  * find_attribute - This is the primary attriubte lookup function
152  * for object operations.
153  * return: error code
154  * classp(out): class pointer (returned)
155  * attp(out): pointer to attribute descriptor (returned())
156  * op(in): class or object pointer
157  * name(in): attribute name
158  * for_write(in): flag set if intention is for update/alter
159  *
160  * Note:
161  * It will fetch the class with the proper mode and find the named
162  * attribute.
163  * Compare this with the new function sm_get_att_desc() and
164  * try to merge where possible.
165  */
166 static int
167 find_attribute (SM_CLASS ** classp, SM_ATTRIBUTE ** attp, MOP op, const char *name, int for_write)
168 {
169  int error = NO_ERROR, is_class = 0;
170  SM_CLASS *class_;
171  SM_ATTRIBUTE *att;
172  DB_FETCH_MODE class_purpose;
173  bool find_class_attribute = false;
174 
175  class_ = NULL;
176  att = NULL;
177 
178  if (!op->is_temp)
179  {
180  class_purpose = ((for_write) ? DB_FETCH_WRITE : DB_FETCH_READ);
181 
182  is_class = locator_is_class (op, class_purpose);
183 
184  if (is_class < 0)
185  {
186  return is_class;
187  }
188  find_class_attribute = (is_class > 0 ? true : false);
189  }
190 
191  if (find_class_attribute)
192  {
193  /* looking for class attribute */
194  if (for_write)
195  {
196  error = au_fetch_class (op, &class_, AU_FETCH_UPDATE, AU_ALTER);
197  }
198  else
199  {
200  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
201  }
202  if (error == NO_ERROR)
203  {
204  att = classobj_find_attribute (class_, name, 1);
205  }
206  }
207  else
208  {
209  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
210  if (error == NO_ERROR)
211  {
212  att = classobj_find_attribute (class_, name, 0);
213  if (att != NULL)
214  {
216  {
217  /*
218  * sigh, we didn't know that this was going to be a shared attribute
219  * when we checked class authorization above, we must now upgrade
220  * the lock and check for alter access.
221  *
222  * Since this is logically in the name_space of the instance,
223  * should we use simple AU_UPDATE authorization rather than AU_ALTER
224  * even though we're technically modifying the class ?
225  */
226  if (for_write)
227  {
228  error = au_fetch_class (op, &class_, AU_FETCH_UPDATE, AU_ALTER);
229  }
230  }
231  }
232  }
233  }
234 
235  if (error == NO_ERROR && att == NULL)
236  {
237  ERROR1 (error, ER_OBJ_INVALID_ATTRIBUTE, name);
238  }
239 
240  *classp = class_;
241  *attp = att;
242  return error;
243 }
244 
245 /*
246  * find_shared_attribute - Used only to find a shared attribute given
247  * a class or instance.
248  * return: error
249  * classp(out): class pointer (returned)
250  * attp(out): pointer to pointer to attribute for shared attribute
251  * op(in): class or instance
252  * name(in): attribute name
253  * for_write(in):flag indicating that an update is intended
254  *
255  * Note:
256  * This is necessary because the behavior of find_attribute given a
257  * class object is to search for class attribute NOT shared attributes
258  * Because of this, when the user wants a shared attribute from a class
259  * object, they must specifically signal this intent by using the
260  * obj_get_shared (or obj_set_shared) interface functions.
261  */
262 
263 static int
264 find_shared_attribute (SM_CLASS ** classp, SM_ATTRIBUTE ** attp, MOP op, const char *name, int for_write)
265 {
266  int error = NO_ERROR;
267  SM_CLASS *class_;
268  SM_ATTRIBUTE *att;
269 
270  att = NULL;
271  if (for_write)
272  {
273  error = au_fetch_class (op, &class_, AU_FETCH_UPDATE, AU_ALTER);
274  }
275  else
276  {
277  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
278  }
279 
280  if (error == NO_ERROR)
281  {
282 
283  if (for_write)
284  {
285  /* must call this when updating instances - is this necessary here ? */
287  }
288 
289  att = classobj_find_attribute (class_, name, 0);
290  if (att == NULL || att->header.name_space != ID_SHARED_ATTRIBUTE)
291  {
292  ERROR1 (error, ER_OBJ_INVALID_ATTRIBUTE, name);
293  }
294  }
295 
296  *classp = class_;
297  *attp = att;
298  return error;
299 }
300 
301 /*
302  * obj_locate_attribute -
303  * return: error code
304  * op(in): class or object pointer
305  * attid(in): id
306  * for_write(in):flag set if intention is for update/alter
307  * memp(out): pointer to instance memory block (returned)
308  * attp(out): pointer to attribute descriptor (returned)
309  *
310  * Note:
311  * This is an attribute lookup routine used when the attribute id
312  * is known. Since id ranges are unique across all attribute types,
313  * this can be used for normal, shared and class attributes.
314  * This is made public so that it can be used by the set module to
315  * locate set valued attributes for a set reference MOP.
316  * Similar to find_attribute() except that it also fetches the instance
317  * and returns the memory offset, consider merging the two.
318  */
319 
320 int
321 obj_locate_attribute (MOP op, int attid, int for_write, char **memp, SM_ATTRIBUTE ** attp)
322 {
323  int error = NO_ERROR, is_class = 0;
324  SM_CLASS *class_;
325  SM_ATTRIBUTE *att, *found;
326  MOBJ obj;
327  char *memory;
328  DB_FETCH_MODE class_purpose;
329 
330  found = NULL;
331  memory = NULL;
332 
333  /* need to handle this case */
334  if (op->is_temp)
335  {
337  return error;
338  }
339 
340  class_purpose = ((for_write) ? DB_FETCH_WRITE : DB_FETCH_READ);
341 
342  is_class = locator_is_class (op, class_purpose);
343  if (is_class < 0)
344  {
345  return is_class;
346  }
347  if (is_class)
348  {
349  if (for_write)
350  {
351  error = au_fetch_class (op, &class_, AU_FETCH_UPDATE, AU_ALTER);
352  }
353  else
354  {
355  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
356  }
357 
358  if (error == NO_ERROR)
359  {
360  found = NULL;
361  for (att = class_->class_attributes; att != NULL && found == NULL; att = (SM_ATTRIBUTE *) att->header.next)
362  {
363  if (att->id == attid)
364  {
365  found = att;
366  }
367  }
368  }
369  }
370  else
371  {
372  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
373  if (error == NO_ERROR)
374  {
375  if (for_write)
376  {
378  }
379  else
380  {
382  }
383 
384  if (error == NO_ERROR)
385  {
386  if (for_write)
387  {
388  /* must call this when updating instances */
390  }
391 
392  found = NULL;
393  for (att = class_->attributes; att != NULL && found == NULL; att = (SM_ATTRIBUTE *) att->header.next)
394  {
395  if (att->id == attid)
396  {
397  found = att;
398  }
399  }
400 
401  if (found != NULL)
402  {
403  memory = (char *) (((char *) obj) + found->offset);
404  }
405 
406  else
407  {
408  for (att = class_->shared; att != NULL && found == NULL; att = (SM_ATTRIBUTE *) att->header.next)
409  {
410  if (att->id == attid)
411  {
412  found = att;
413  }
414  }
415 
416  if (found != NULL)
417  {
418 
419  if (for_write)
420  {
421  error = au_fetch_class (op, &class_, AU_FETCH_UPDATE, AU_ALTER);
422  }
423  }
424  }
425  }
426  }
427  }
428 
429  if (error == NO_ERROR && found == NULL)
430  {
431  ERROR1 (error, ER_OBJ_INVALID_ATTRIBUTE, "???");
432  }
433 
434  if (attp != NULL)
435  {
436  *attp = found;
437  }
438  *memp = memory;
439 
440  return error;
441 }
442 
443 
444 /* VALUE ASSIGNMENT */
445 
446 /*
447  * assign_null_value - Work function for assign_value.
448  * return: error
449  * op(in): class or instance pointer
450  * att(in):attribute descriptor
451  * mem(in):pointer to instance memory (only if instance attribute)
452  *
453  * Note:
454  * This is used to set the value of an attribute to NULL.
455  */
456 static int
457 assign_null_value (MOP op, SM_ATTRIBUTE * att, char *mem)
458 {
459  /*
460  * the mr_ functions are responsible for initializing/freeing the
461  * value if NULL is passed in
462  */
463 
464  MOBJ object = NULL;
465 
466  if (mem == NULL)
467  {
469  }
470  else
471  {
472  if (att->domain->type->setmem (mem, att->domain, NULL))
473  {
474  assert (er_errid () != NO_ERROR);
475  return er_errid ();
476  }
477  else
478  {
479  if (!att->domain->type->variable_p)
480  {
481  if ((ws_find (op, &object) == WS_FIND_MOP_DELETED) || object == NULL)
482  {
484  }
485  OBJ_CLEAR_BOUND_BIT (object, att->storage_order);
486  }
487  }
488  }
489 
490  return NO_ERROR;
491 }
492 
493 /*
494  * assign_set_value - Work function for assign_value
495  * return: error
496  * op(in): class or instance pointer
497  * att(in): attribute descriptor
498  * mem(in): pointer to instance memory (for instance attributes only)
499  * setref(in): set pointer to assign
500  *
501  * Note:
502  * This is used to assign a set value to an attribute. Sets have extra
503  * overhead in assignment to maintain the ownership information in the
504  * set descriptor. Unlike strings, sets are not freed when they are
505  * replaced in an assignment. They will be subject to gargabe collection.
506  *
507  * Make sure the set is checked for compliance with the attribute domain
508  * if the set currently has no domain specification.
509  */
510 
511 static int
512 assign_set_value (MOP op, SM_ATTRIBUTE * att, char *mem, SETREF * setref)
513 {
514  int error = NO_ERROR, is_class = 0;
515  MOP owner;
516  SETREF *new_set, *current_set;
517  DB_VALUE val;
518 
519  /* change ownership of the set, copy if necessary */
520  if (setref == NULL)
521  {
522  new_set = NULL;
523  }
524  else
525  {
526  owner = op;
527  if (mem == NULL)
528  {
529  is_class = locator_is_class (op, DB_FETCH_WRITE);
530  if (is_class < 0)
531  {
532  return is_class;
533  }
534  if (!is_class)
535  {
536  owner = ws_class_mop (op);
537  }
538  }
539 
540  new_set = set_change_owner (setref, owner, att->id, att->domain);
541  if (new_set == NULL)
542  {
543  assert (er_errid () != NO_ERROR);
544  error = er_errid ();
545  }
546  }
547 
548  if (error == NO_ERROR)
549  {
550  /* assign the value */
551  if (mem != NULL)
552  {
553  switch (TP_DOMAIN_TYPE (att->domain))
554  {
555  case DB_TYPE_SET:
556  default:
557  db_make_set (&val, new_set);
558  break;
559 
560  case DB_TYPE_MULTISET:
561  db_make_multiset (&val, new_set);
562  break;
563 
564  case DB_TYPE_SEQUENCE:
565  db_make_sequence (&val, new_set);
566  break;
567  }
568 
569  error = att->domain->type->setmem (mem, att->domain, &val);
570  db_value_put_null (&val);
571 
572  if (error == NO_ERROR)
573  {
574  if (new_set != NULL && new_set != setref)
575  {
576  set_free (new_set);
577  }
578  }
579  }
580  else
581  {
582  /*
583  * remove ownership information in the current set,
584  * need to be able to free this !!!
585  */
586  current_set = db_get_set (&att->default_value.value);
587  if (current_set != NULL)
588  {
589  error = set_disconnect (current_set);
590  }
591 
592  if (error == NO_ERROR)
593  {
594 
595  /* set the new value */
596  if (new_set != NULL)
597  {
598  switch (TP_DOMAIN_TYPE (att->domain))
599  {
600  case DB_TYPE_SET:
601  default:
602  db_make_set (&att->default_value.value, new_set);
603  break;
604 
605  case DB_TYPE_MULTISET:
606  db_make_multiset (&att->default_value.value, new_set);
607  break;
608 
609  case DB_TYPE_SEQUENCE:
610  db_make_sequence (&att->default_value.value, new_set);
611  break;
612  }
613  }
614  else
615  {
617  }
618 
619  if (new_set != NULL)
620  {
621  new_set->ref_count++;
622  }
623  }
624  }
625  }
626 
627  return error;
628 }
629 
630 /*
631  * obj_assign_value - This is a generic value assignment function.
632  * return: error code
633  * op(in): class or instance pointer
634  * att(in): attribute descriptor
635  * mem(in): instance memory pointer (instance attribute only)
636  * value(in): value to assign
637  *
638  * Note:
639  * It will check the type of the value and call one of the specialized
640  * assignment functions as necessary.
641  * This is called by obj_set and by the template assignment function.
642  */
643 
644 int
645 obj_assign_value (MOP op, SM_ATTRIBUTE * att, char *mem, DB_VALUE * value)
646 {
647  int error = NO_ERROR;
648  MOP mop;
649  MOBJ object = NULL;
650 
651  if (op == NULL || att == NULL)
652  {
655  }
656 
657  if (DB_IS_NULL (value))
658  {
659  error = assign_null_value (op, att, mem);
660  }
661  else
662  {
663  if (TP_IS_SET_TYPE (TP_DOMAIN_TYPE (att->domain)))
664  {
665  error = assign_set_value (op, att, mem, db_get_set (value));
666  }
667  else
668  {
669  if (att->domain->type == tp_Type_object && !op->is_vid && (mop = db_get_object (value))
670  && WS_MOP_IS_NULL (mop))
671  {
672  error = assign_null_value (op, att, mem);
673  }
674  else
675  {
676  /* uncomplicated assignment, use the primitive type macros */
677  if (mem != NULL)
678  {
679  error = att->domain->type->setmem (mem, att->domain, value);
680  if (!error && !att->domain->type->variable_p)
681  {
682  if (ws_find (op, &object) == WS_FIND_MOP_DELETED || object == NULL)
683  {
685  }
686  OBJ_SET_BOUND_BIT (object, att->storage_order);
687  }
688  }
689  else
690  {
692  pr_clone_value (value, &att->default_value.value);
693  }
694  }
695  }
696  }
697 
698  return error;
699 }
700 
701 /*
702  * DIRECT ATTRIBUTE ASSIGNMENT
703  */
704 
705 /*
706  * obj_set_att -
707  * return: error code
708  * op(in): object
709  * class(in): class structure
710  * att(in): attribute structure
711  * value(in): value to assign
712  * valid(in):
713  *
714  * Note:
715  * This is the common assignment function shared by obj_set() and
716  * obj_desc_set(). At this point we have direct pointers to the
717  * class & attribute structures and we can assume that the appropriate
718  * locks have been obtained.
719  */
720 static int
721 obj_set_att (MOP op, SM_CLASS * class_, SM_ATTRIBUTE * att, DB_VALUE * value, SM_VALIDATION * valid)
722 {
723  int error = NO_ERROR, is_class = 0;
724  char *mem;
725  int opin, cpin;
726  MOP ref_mop;
727  DB_VALUE *actual;
728  DB_VALUE base_value;
729  const char *base_name;
730  int save, trigstate;
731  OBJ_TEMPLATE *temp;
732  MOBJ obj, ref_obj;
733  MOP class_mop = NULL;
734 
735  db_make_null (&base_value);
736 
737  if (op->is_temp)
738  {
739  error = obj_set_temp (op, att, value);
740  }
741  else
742  {
743  /* Check for the presence of triggers or unique constraints, use templates in those cases. */
744 
745  if (class_->triggers != NULL)
746  {
747  is_class = locator_is_class (op, DB_FETCH_WRITE);
748  if (is_class < 0)
749  {
750  return is_class;
751  }
752  if (is_class)
753  {
754  class_mop = op;
755  }
756  else
757  {
758  class_mop = ws_class_mop (op);
759  }
760  }
761 
762  trigstate = sm_active_triggers (class_mop, class_, TR_EVENT_ALL);
763  if (trigstate < 0)
764  {
765  assert (er_errid () != NO_ERROR);
766  return er_errid ();
767  }
768  if (trigstate || classobj_has_unique_constraint (att->constraints))
769  {
770  /* use templates to avoid duplicating trigger code */
771  temp = obt_edit_object (op);
772  if (temp == NULL)
773  {
774  assert (er_errid () != NO_ERROR);
775  error = er_errid ();
776  }
777  else
778  {
779  error = obt_assign (temp, att, 0, value, NULL);
780  if (error == NO_ERROR)
781  {
782  error = obt_update (temp, NULL);
783  }
784  else
785  {
786  obt_quit (temp);
787  }
788  }
789  }
790  else
791  {
792  /*
793  * simple, single valued update without triggers,
794  * avoid template overhead
795  */
796  if (op->is_vid)
797  {
798  if (class_->class_type == SM_VCLASS_CT)
799  {
800  if (vid_is_updatable (op))
801  {
802  ref_mop = vid_get_referenced_mop (op);
803  if (ref_mop)
804  {
805  /*
806  * lock the object for update, this also ensures the class
807  * gets cached in the MOP which is important for the
808  * following usage of ref_mop->class
809  */
811  NO_ERROR)
812  {
813  assert (er_errid () != NO_ERROR);
814  return er_errid ();
815  }
816 
817  /*
818  * some attributes may not be updatable
819  * even if the instance itself is updatable.
820  */
821  if (db_is_updatable_attribute (op, att->header.name))
822  {
823  /* could have att/descriptor versions of these */
824  error =
825  mq_update_attribute (ws_class_mop (op), att->header.name, ws_class_mop (ref_mop), value,
826  &base_value, &base_name, DB_AUTH_UPDATE);
827  if (error != NO_ERROR)
828  {
829  return error;
830  }
831  else
832  {
833  AU_DISABLE (save);
834  /* could use att/descriptor interface here */
835  error = obj_set (ref_mop, base_name, &base_value);
836  AU_ENABLE (save);
837 
838  return error;
839  }
840  }
841  else
842  {
843  error = ER_IT_ATTR_NOT_UPDATABLE;
845  }
846  }
847  else
848  {
849  error = ER_HEAP_UNKNOWN_OBJECT;
851  }
852  }
853  else
854  {
855  error = ER_IT_NOT_UPDATABLE_STMT;
857  }
858 
859  return error;
860  }
861  }
862 
863  /* assume class locks are good, get memory offset */
864  mem = NULL;
865  if (att->header.name_space == ID_ATTRIBUTE)
866  {
868  {
869  assert (er_errid () != NO_ERROR);
870  return er_errid ();
871  }
872 
873  /* must call this when updating instances */
875  mem = (char *) (((char *) obj) + att->offset);
876  }
877 
878  /*
879  * now that we have a memory pointer into the object, must pin it
880  * to prevent workspace flush from destroying it
881  */
882  ws_pin_instance_and_class (op, &opin, &cpin);
883 
884  if (error == NO_ERROR)
885  {
886  actual = obt_check_assignment (att, value, valid, 0);
887  if (actual == NULL)
888  {
889  assert (er_errid () != NO_ERROR);
890  error = er_errid ();
891  }
892  else
893  {
894  error = obj_assign_value (op, att, mem, actual);
895  if (actual != value)
896  {
897  pr_free_ext_value (actual);
898  }
899 
900 #if defined(ENABLE_UNUSED_FUNCTION)
901  if ((error == NO_ERROR) && (op->is_vid))
902  {
903  error = vid_record_update (op, class_, att);
904  }
905 #endif
906  }
907  }
908 
909  ws_restore_pin (op, opin, cpin);
910  }
911  }
912 
913  return error;
914 }
915 
916 /*
917  * obj_set - This is the external function for assigning the value of an attribute.
918  * return: error code
919  * op(in): class or instance pointer
920  * name(in): attribute
921  * value(in):value to assign
922  *
923  * Note:
924  * It will locate the attribute, perform type validation, and make
925  * the assignment if everything looks ok. If the op argument is a class
926  * object, it will assign a value to a class attribute. If the op
927  * argument is an instance object, it will assign a value to either
928  * a normal or shared attribute.
929  */
930 int
931 obj_set (MOP op, const char *name, DB_VALUE * value)
932 {
933  int error = NO_ERROR;
934  SM_ATTRIBUTE *att;
935  SM_CLASS *class_;
936 
937  if ((op == NULL) || (name == NULL) || ((value != NULL) && (DB_VALUE_TYPE (value) > DB_TYPE_LAST)))
938  {
940  }
941  else
942  {
943  error = find_attribute (&class_, &att, op, name, 1);
944  if (error == NO_ERROR)
945  {
946  error = obj_set_att (op, class_, att, value, NULL);
947  }
948  }
949 
950  return (error);
951 }
952 
953 /*
954  * obj_desc_set - This is similar to obj_set() excpet that the attribute is
955  * identified with a descriptor rather than a name.
956  * return: error code
957  * op(in): object
958  * desc(in): attribute descriptor
959  * value(in): value to assign
960  *
961  * Note:
962  * Once the actual class & attribute structures are located, it calls
963  * obj_set_att() to do the work.
964  */
965 
966 int
967 obj_desc_set (MOP op, SM_DESCRIPTOR * desc, DB_VALUE * value)
968 {
969  int error = NO_ERROR;
970  SM_ATTRIBUTE *att;
971  SM_CLASS *class_;
972 
973  if ((op == NULL) || (desc == NULL) || ((value != NULL) && (DB_VALUE_TYPE (value) > DB_TYPE_LAST)))
974  {
976  }
977  else
978  {
979  /* map the descriptor into an actual pair of class/attribute structures */
980  if (sm_get_descriptor_component (op, desc, 1, &class_, (SM_COMPONENT **) (&att)))
981  {
982  assert (er_errid () != NO_ERROR);
983  return er_errid ();
984  }
985 
986  error = obj_set_att (op, class_, att, value, desc->valid);
987  }
988 
989  return error;
990 }
991 
992 /*
993  * obj_set_shared - This is like obj_set except that it only looks
994  * for shared attributes.
995  * return: error code
996  * op(in): class or instance pointer
997  * name(in): shared attribute name
998  * value(in): value to assign
999  *
1000  * Note:
1001  * This is only necessary for setting shared attributes when given only
1002  * a class object. obj_set when given a class object will only assign
1003  * values to class attributes, if you need to assign a shared attribute
1004  * value instead, you must call this function.
1005  * Triggers are not active here.
1006  * I'm not sure what the behavior of this should be since we aren't
1007  * invoking the update on any particular instance.
1008  * We don't have a descriptor interface for this since obj_desc_set()
1009  */
1010 
1011 int
1012 obj_set_shared (MOP op, const char *name, DB_VALUE * value)
1013 {
1014  int error = NO_ERROR;
1015  SM_CLASS *class_;
1016  SM_ATTRIBUTE *att;
1017  DB_VALUE *actual;
1018 
1019  /* misc arg checking, need to have optomized versions of this for the interpreter */
1020 
1021  if ((op == NULL) || (name == NULL) || ((value != NULL) && (DB_VALUE_TYPE (value) > DB_TYPE_LAST)))
1022  {
1024  }
1025  else
1026  {
1027  /* since classes are implicitly pinned, don't have to worry about losing the class here, */
1028  error = find_shared_attribute (&class_, &att, op, name, 1);
1029  if (error == NO_ERROR)
1030  {
1031  actual = obt_check_assignment (att, value, NULL, 0);
1032  if (actual == NULL)
1033  {
1034  assert (er_errid () != NO_ERROR);
1035  error = er_errid ();
1036  }
1037  else
1038  {
1039  error = obj_assign_value (op, att, NULL, value);
1040  if (actual != value)
1041  {
1042  (void) pr_free_ext_value (actual);
1043  }
1044  }
1045  }
1046  }
1047  return (error);
1048 }
1049 
1050 /*
1051  * VALUE ACCESSORS
1052  */
1053 
1054 /*
1055  * get_object_value - Work function for obj_get_value.
1056  * return: int
1057  * op(in): class or instance pointer
1058  * att(in): attribute descriptor
1059  * mem(in): instance memory pointer (only if instance attribute)
1060  * source(out): source value container
1061  * dest(out): destination value container
1062  *
1063  * Note:
1064  * This is the primitive accessor for "object" valued attributes.
1065  * The main addition here over other attribute types is that it
1066  * will check for deleted object references and convert these to
1067  * NULL for return.
1068  */
1069 
1070 static int
1071 get_object_value (MOP op, SM_ATTRIBUTE * att, char *mem, DB_VALUE * source, DB_VALUE * dest)
1072 {
1073  MOP current;
1074  DB_VALUE curval;
1075  int status;
1076  MOBJ object;
1077  int rc = NO_ERROR;
1078 
1079  /* use class/shared value if alternate source isn't provided */
1080  if (mem == NULL && source == NULL)
1081  {
1082  source = &att->default_value.value;
1083  }
1084 
1085  current = NULL;
1086  if (mem != NULL)
1087  {
1088  db_make_object (&curval, NULL);
1089  if (att->domain->type->getmem (mem, att->domain, &curval))
1090  {
1091  ASSERT_ERROR_AND_SET (rc);
1092  return rc;
1093  }
1094  current = db_get_object (&curval);
1095  }
1096  else if (TP_DOMAIN_TYPE (att->domain) == DB_VALUE_TYPE (source))
1097  {
1098  current = db_get_object (source);
1099  }
1100 
1101  /* check for existence of the object this is expensive so only do this if enabled by a parameter. */
1102  if (current != NULL && current->object == NULL && !WS_IS_DELETED (current))
1103  {
1104  if (WS_ISVID (current))
1105  {
1106  /* Check that this operation is not coming from vid workspace management. This context implies that the
1107  * object will not be passed directly to an application. An operation being done may be an object flush, and
1108  * it is undesirable for a side effect of flushing to be fetching more objects, particularly when fetching an
1109  * object can cause flushing and then infinite recursion. */
1111  {
1113  }
1114  /*
1115  * do NOT mark current as deleted because the fetch may
1116  * have encountered an error which needs to be returned!
1117  */
1118  }
1119  else
1120  {
1121  status = locator_does_exist_object (current, DB_FETCH_READ);
1122  if (status == LC_DOESNOT_EXIST)
1123  {
1124  WS_SET_DELETED (current);
1125  }
1126  else if (status == LC_ERROR)
1127  {
1128  ASSERT_ERROR_AND_SET (rc);
1129  return rc;
1130  }
1131  }
1132  }
1133 
1134  if (current != NULL && WS_IS_DELETED (current))
1135  {
1136  /* convert deleted MOPs to NULL values */
1137  db_make_null (dest);
1138 
1139  /*
1140  * set the attribute value so we don't hit this condition again,
1141  * note that this doesn't dirty the object
1142  */
1143 
1144  /* A comm error might cause a fetch error on an existing object. */
1145  if (!WS_ISVID (current))
1146  {
1147  if (mem != NULL)
1148  {
1149  if (att->domain->type->setmem (mem, att->domain, NULL))
1150  {
1151  ASSERT_ERROR_AND_SET (rc);
1152  return rc;
1153  }
1155  }
1156  else
1157  {
1158  db_make_null (source);
1159  }
1160  }
1161  }
1162  else
1163  {
1164  if (current != NULL)
1165  {
1166  db_make_object (dest, current);
1167  }
1168  else
1169  {
1170  db_make_null (dest);
1171  }
1172  }
1173 
1174  return rc;
1175 }
1176 
1177 /*
1178  * get_set_value - Work function for obj_get_value.
1179  * return: int
1180  * op(in): class or instance pointer
1181  * att(in): attirubte descriptor
1182  * mem(in): instance memory pointer (only for instance attribute)
1183  * source(out): source value container
1184  * dest(out): destination value container
1185  *
1186  * Note:
1187  * This is the primitive accessor for set valued attributes.
1188  * This will make sure the set structure is stamped with the MOP of the
1189  * owning object and the attribute id of the attribute that points to
1190  * it. This is so we can get back to this attribute if someone tries
1191  * to do destructive operations to the set descriptor.
1192  */
1193 
1194 static int
1195 get_set_value (MOP op, SM_ATTRIBUTE * att, char *mem, DB_VALUE * source, DB_VALUE * dest)
1196 {
1197  SETREF *set;
1198  DB_VALUE setval;
1199  MOP owner;
1200 
1201  if (op == NULL || att == NULL)
1202  {
1204  return ER_OBJ_INVALID_ARGUMENTS;
1205  }
1206 
1207  /* use class/shared value if alternate source isn't provided */
1208  if (mem == NULL && source == NULL)
1209  {
1210  source = &att->default_value.value;
1211  }
1212 
1213  /* get owner and current value */
1214  set = NULL;
1215  owner = op;
1216  if (mem != NULL)
1217  {
1219  if (att->domain->type->getmem (mem, att->domain, &setval))
1220  {
1221  assert (er_errid () != NO_ERROR);
1222  return er_errid ();
1223  }
1224  set = db_get_set (&setval);
1225  db_value_put_null (&setval);
1226  }
1227  else
1228  {
1230 
1231  if (is_class < 0)
1232  {
1233  return is_class;
1234  }
1235  /* note, we may have a temporary OP here ! */
1236  if (!is_class)
1237  {
1238  owner = ws_class_mop (op); /* shared attribute, owner is class */
1239  }
1240  if (TP_DOMAIN_TYPE (att->domain) == DB_VALUE_TYPE (source))
1241  {
1242  set = db_get_set (source);
1243  /* KLUDGE: shouldn't be doing this at this level */
1244  if (set != NULL)
1245  {
1246  set->ref_count++;
1247  }
1248  }
1249  }
1250 
1251  /*
1252  * make sure set has proper ownership tags, this shouldn't happen
1253  * in normal circumstances
1254  */
1255  if (set != NULL && !ws_is_same_object (set->owner, owner))
1256  {
1257  if (set_connect (set, owner, att->id, att->domain))
1258  {
1259  assert (er_errid () != NO_ERROR);
1260  return er_errid ();
1261  }
1262  }
1263 
1264  /* convert NULL sets to DB_TYPE_NULL */
1265  if (set == NULL)
1266  {
1267  db_make_null (dest);
1268  }
1269  else
1270  {
1271  switch (TP_DOMAIN_TYPE (att->domain))
1272  {
1273  case DB_TYPE_SET:
1274  default:
1275  db_make_set (dest, set);
1276  break;
1277 
1278  case DB_TYPE_MULTISET:
1279  db_make_multiset (dest, set);
1280  break;
1281 
1282  case DB_TYPE_SEQUENCE:
1283  db_make_sequence (dest, set);
1284  break;
1285  }
1286  }
1287 
1288  return NO_ERROR;
1289 }
1290 
1291 /*
1292  * obj_get_value -
1293  * return: int
1294  * op(in): class or instance pointer
1295  * att(in): attribute descriptor
1296  * mem(in): instance memory pointer (only for instance attribute)
1297  * source(out): alternate source value (optional)
1298  * dest(out): destionation value container
1299  *
1300  * Note:
1301  * This is the basic generic function for accessing an attribute
1302  * value. It will call one of the specialized accessor functions above
1303  * as necessary.
1304  */
1305 
1306 int
1307 obj_get_value (MOP op, SM_ATTRIBUTE * att, void *mem, DB_VALUE * source, DB_VALUE * dest)
1308 {
1309  int error = NO_ERROR;
1310  MOBJ object = NULL;
1311 
1312  if (op == NULL || att == NULL)
1313  {
1315  return ER_OBJ_INVALID_ARGUMENTS;
1316  }
1317 
1318  /* use class/shared value if alternate source isn't provided */
1319  if (mem == NULL && source == NULL)
1320  {
1321  source = &att->default_value.value;
1322  }
1323 
1324  if ((ws_find (op, &object) == WS_FIND_MOP_DELETED) || object == NULL)
1325  {
1327  return ER_OBJ_INVALID_ARGUMENTS;
1328  }
1329 
1330  /* first check the bound bits */
1331  if (!att->domain->type->variable_p && mem != NULL && OBJ_GET_BOUND_BIT (object, att->storage_order) == 0)
1332  {
1333  db_make_null (dest);
1334  }
1335  else
1336  {
1337  if (TP_IS_SET_TYPE (TP_DOMAIN_TYPE (att->domain)))
1338  {
1339  error = get_set_value (op, att, (char *) mem, source, dest);
1340  }
1341  else if (att->domain->type == tp_Type_object)
1342  {
1343  error = get_object_value (op, att, (char *) mem, source, dest);
1344  }
1345  else
1346  {
1347  if (mem != NULL)
1348  {
1349  error = att->domain->type->getmem (mem, att->domain, dest);
1350  }
1351  else
1352  {
1353  error = pr_clone_value (source, dest);
1354  }
1355 
1356  if (error == NO_ERROR)
1357  {
1358  if (DB_VALUE_TYPE (dest) == DB_TYPE_STRING && db_get_string (dest) == NULL)
1359  {
1360  db_make_null (dest);
1361  }
1362  }
1363  }
1364  }
1365 
1366  return error;
1367 }
1368 
1369 /*
1370  * obj_get_att - This is a common attribute retriveal function shared by
1371  * obj_get & obj_desc_get.
1372  * return: error code
1373  * op(in): object
1374  * class(in): class structure
1375  * att(in): attribute structure
1376  * value(out): value container(output)
1377  *
1378  * Note:
1379  * It operates assuming that we now
1380  * have direct pointers to the class & attribute structures and that
1381  * the appropriate locks have been obtained.
1382  * It handles the difference between temporary, virtual, and normal
1383  * instnace MOPs.
1384  */
1385 
1386 int
1387 obj_get_att (MOP op, SM_CLASS * class_, SM_ATTRIBUTE * att, DB_VALUE * value)
1388 {
1389  int error = NO_ERROR;
1390  SM_CLASS *ref_class;
1391  char *mem;
1392  int opin, cpin;
1393  MOP ref_mop;
1394  MOBJ obj;
1395 
1396  if (op->is_temp)
1397  {
1398  error = obj_get_temp (op, class_, att, value);
1399  }
1400  else
1401  {
1402  if (op->is_vid)
1403  {
1404  if (class_->class_type == SM_VCLASS_CT)
1405  {
1406  if (vid_is_updatable (op))
1407  {
1408  ref_mop = vid_get_referenced_mop (op);
1409  if (ref_mop)
1410  {
1411  error = au_fetch_class_force (ref_mop, &ref_class, AU_FETCH_READ);
1412  if (error == NO_ERROR)
1413  {
1414  return mq_get_attribute (ws_class_mop (op), att->header.name, ws_class_mop (ref_mop), value,
1415  ref_mop);
1416  }
1417  else
1418  {
1419  return error;
1420  }
1421  }
1422  else
1423  {
1424  error = ER_HEAP_UNKNOWN_OBJECT;
1425  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1426  return error;
1427  }
1428  }
1429  else
1430  {
1431  /* fall through to "normal" fetch for non-updatable */
1432  }
1433  }
1434  }
1435 
1436  /* fetch the instance if necessary */
1437  mem = NULL;
1438  if (att->header.name_space == ID_ATTRIBUTE)
1439  {
1440  /* fetch the instance and caluclate memory offset */
1442  {
1443  assert (er_errid () != NO_ERROR);
1444  return er_errid ();
1445  }
1446  mem = (char *) (((char *) obj) + att->offset);
1447  }
1448 
1449  ws_pin_instance_and_class (op, &opin, &cpin);
1450  error = obj_get_value (op, att, mem, NULL, value);
1451  ws_restore_pin (op, opin, cpin);
1452  }
1453 
1454  return error;
1455 }
1456 
1457 /*
1458  * obj_desc_get - This retrieves the value of an attribute using a
1459  * descriptor rather than an attribute name.
1460  * return:
1461  * op(in): object
1462  * desc(in): attribute descriptor
1463  * value(out): value container (returned)
1464  *
1465  * Note:
1466  * Descriptors are good for repetitive access to the same attribute.
1467  */
1468 
1469 int
1471 {
1472  int error = NO_ERROR;
1473  SM_CLASS *class_;
1474  SM_ATTRIBUTE *att;
1475 
1476  if ((op == NULL) || (desc == NULL) || (value == NULL))
1477  {
1479  }
1480  else
1481  {
1482  /* map the descriptor into an actual pair of class/attribute structures */
1483  if (sm_get_descriptor_component (op, desc, 0, &class_, (SM_COMPONENT **) (&att)) != NO_ERROR)
1484  {
1485  assert (er_errid () != NO_ERROR);
1486  return er_errid ();
1487  }
1488 
1489  error = obj_get_att (op, class_, att, value);
1490  }
1491 
1492  return error;
1493 }
1494 
1495 /*
1496  * obj_get - This is the external function for accessing attribute values.
1497  * return: error code
1498  * op(in): class or instance pointer
1499  * name(in): attribute name
1500  * value(out): destination value container
1501  *
1502  * Note:
1503  * If the named attribute is found, the value is returned through the
1504  * supplied value container.
1505  */
1506 
1507 int
1508 obj_get (MOP op, const char *name, DB_VALUE * value)
1509 {
1510  int error = NO_ERROR;
1511  SM_ATTRIBUTE *att;
1512  SM_CLASS *class_;
1513 
1514  if ((op == NULL) || (name == NULL) || (value == NULL))
1515  {
1517  }
1518  else
1519  {
1520  error = find_attribute (&class_, &att, op, name, 0);
1521  if (error == NO_ERROR)
1522  {
1523  error = obj_get_att (op, class_, att, value);
1524  }
1525  }
1526 
1527  return error;
1528 }
1529 
1530 /*
1531  * obj_get_shared - This is used to access the value of a shared attribute only.
1532  * return: error code
1533  * op(in): class or instance pointer
1534  * name(in): shared attribute name
1535  * value(out): destination value container
1536  *
1537  * Note :
1538  * This is used only in cases where you have the MOP of a class and you want
1539  * to get the value of a shared attribute. Since the default behavior
1540  * of obj_get is to look for class attributes when given a class mop, you
1541  * must use this function to get shared attribute values from a class
1542  * mop.
1543  * Note that there is no need to have a descriptor version of this
1544  * function, obj_desc_get() will work for shared attributes provided
1545  * that a shared attribute descriptor is being used.
1546  */
1547 
1548 int
1549 obj_get_shared (MOP op, const char *name, DB_VALUE * value)
1550 {
1551  int error = NO_ERROR;
1552  SM_ATTRIBUTE *att;
1553  SM_CLASS *class_;
1554 
1555  if ((op == NULL) || (name == NULL) || (value == NULL))
1556  {
1558  }
1559  else
1560  {
1561  error = find_shared_attribute (&class_, &att, op, name, 0);
1562  if (error == NO_ERROR)
1563  {
1564  obj_get_value (op, att, NULL, NULL, value);
1565  }
1566  }
1567 
1568  return error;
1569 }
1570 
1571 /*
1572  *
1573  * OBJECT ACCESS WITH PSEUDO PATH EXPRESSION
1574  *
1575  *
1576  */
1577 
1578 /*
1579  * obj_get_path -
1580  * return: error
1581  * object(in): class or instance
1582  * attpath(in): a simple attribute name or path expression
1583  * value(out): value container to hold the returned value
1584  *
1585  */
1586 
1587 int
1588 obj_get_path (DB_OBJECT * object, const char *attpath, DB_VALUE * value)
1589 {
1590  int error;
1591  char buf[512];
1592  char *token, *end;
1593  char delimiter, nextdelim;
1594  DB_VALUE temp_value;
1595  int index;
1596 
1597  error = NO_ERROR;
1598  (void) strcpy (&buf[0], attpath);
1599  delimiter = '.'; /* start with implicit dot */
1600  db_make_object (&temp_value, object);
1601  for (token = &buf[0]; char_isspace (*token) && *token != '\0'; token++);
1602  end = token;
1603 
1604  while (delimiter != '\0' && error == NO_ERROR)
1605  {
1606  nextdelim = '\0';
1607  if (delimiter == '.')
1608  {
1609  if (DB_VALUE_TYPE (&temp_value) != DB_TYPE_OBJECT)
1610  {
1612  }
1613  else
1614  {
1615  for (end = token; !char_isspace (*end) && *end != '\0';)
1616  {
1617  if ((*end != '.') && (*end != '['))
1618  {
1619  end++;
1620  }
1621  else
1622  {
1623  nextdelim = *end;
1624  *end = '\0';
1625  }
1626  }
1627 
1628  if (token == end)
1629  {
1631  }
1632  else
1633  {
1634  error = obj_get (db_get_object (&temp_value), token, &temp_value);
1635  }
1636  }
1637  }
1638  else if (delimiter == '[')
1639  {
1640  DB_TYPE temp_type;
1641 
1642  temp_type = DB_VALUE_TYPE (&temp_value);
1643  if (!TP_IS_SET_TYPE (temp_type))
1644  {
1646  }
1647  else
1648  {
1649  for (end = token; char_isdigit (*end) && *end != '\0'; end++)
1650  ;
1651 
1652  nextdelim = *end;
1653  *end = '\0';
1654  if (end == token)
1655  {
1657  }
1658  else
1659  {
1660  index = atoi (token);
1661  if (temp_type == DB_TYPE_SEQUENCE)
1662  {
1663  error = db_seq_get (db_get_set (&temp_value), index, &temp_value);
1664  }
1665  else
1666  {
1667  error = db_set_get (db_get_set (&temp_value), index, &temp_value);
1668  }
1669 
1670  if (error == NO_ERROR)
1671  {
1672  for (++end; nextdelim != ']' && nextdelim != '\0'; nextdelim = *end++)
1673  ;
1674  if (nextdelim != '\0')
1675  {
1676  nextdelim = *end;
1677  }
1678  }
1679  }
1680  }
1681  }
1682  else
1683  {
1685  }
1686 
1687  /* next iteration */
1688  delimiter = nextdelim;
1689  token = end + 1;
1690  }
1691 
1692  if (error == NO_ERROR)
1693  {
1694  *value = temp_value;
1695  }
1696 
1697  return error;
1698 }
1699 
1700 /*
1701  *
1702  * TEMPORARY OBJECT ACCESS
1703  *
1704  *
1705  */
1706 
1707 
1708 /*
1709  * obj_get_temp - This is called by obj_get() after it is determined
1710  * that the MOP is really a temporary object MOP.
1711  * return: error code
1712  * obj(in): temporary MOP
1713  * class(in): class pointer
1714  * att(in): attribute structure
1715  * value(out): value container
1716  *
1717  * Note :
1718  * We get the associated template and look for an assignment that
1719  * matches the attribute name. If one is not found, we then
1720  * call obj_get() on the REAL object in order to get the current
1721  * attribute value.
1722  */
1723 static int
1724 obj_get_temp (DB_OBJECT * obj, SM_CLASS * class_, SM_ATTRIBUTE * att, DB_VALUE * value)
1725 {
1726  int error = NO_ERROR;
1727  OBJ_TEMPLATE *temp;
1728  OBJ_TEMPASSIGN *assignment;
1729  DB_VALUE *src;
1730  MOP object;
1731 
1732  if (obj->class_mop == NULL || obj->object == NULL)
1733  {
1735  }
1736  else
1737  {
1738  temp = (OBJ_TEMPLATE *) (obj->object);
1739 
1740  /* locate an assignment for this attribute in the template */
1741  assignment = temp->assignments[att->order];
1742  if (assignment != NULL)
1743  {
1744  /*
1745  * If this is a "new" object, return the assignment value, otherwise
1746  * return the saved value.
1747  */
1748  if (temp->is_old_template)
1749  {
1750  src = assignment->old_value;
1751  }
1752  else
1753  {
1754  src = assignment->variable;
1755  }
1756 
1757  /*
1758  * Note that for sets, the ownership may get tagged with
1759  * a temporary object
1760  */
1761 
1762  error = obj_get_value (obj, att, NULL, src, value);
1763  }
1764  else
1765  {
1766  /*
1767  * Couldn't find it in the template, get it out of the real object.
1768  * Since we've already done some of the work, could optimize
1769  * the value fetch a bit. Make sure we use the base object so
1770  * the value translation isn't performed.
1771  */
1772  object = OBT_BASE_OBJECT (temp);
1773  if (object != NULL)
1774  {
1775  error = obj_get_att (object, class_, att, value);
1776  }
1777  else
1778  {
1779  /*
1780  * there was no base object so we must be performing an insertion,
1781  * in this case, the value is considered to be NULL
1782  */
1783  db_make_null (value);
1784  }
1785  }
1786  }
1787 
1788  return error;
1789 }
1790 
1791 /*
1792  * obj_set_temp - This is used to change a value in a temporary object.
1793  * return: error code
1794  * obj(in): temporary object MOP
1795  * att(in): attribute name
1796  * value(out): value container
1797  *
1798  * Note:
1799  * It is called by obj_set() when a temporary MOP is passed.
1800  * This is available ONLY for the "new" object in a BEFORE INSERT or
1801  * BEFORE UPDATE trigger. In this case, the trigger action can
1802  * use db_put() to change the values in the template. Since this is
1803  * a straightforward template addition, we just call obt_assign() to
1804  * set the new value.
1805  * If this is not a "new" template an error is signalled because
1806  * it is not meaningful to change the values of "old" objects.
1807  */
1808 static int
1810 {
1811  int error = NO_ERROR;
1812  OBJ_TEMPLATE *temp;
1813 
1814  if (obj->class_mop == NULL || obj->object == NULL)
1815  {
1817  }
1818  else
1819  {
1820  temp = (OBJ_TEMPLATE *) (obj->object);
1821 
1822  if (temp->is_old_template)
1823  {
1824  /* can't update templates containing "old" state */
1826  }
1827  else
1828  {
1829  /*
1830  * Treat this like a normal template assignment. Remember,
1831  * this template may have been created on a virtual class and if
1832  * so, it is expecting attribute names on the virtual class rather
1833  * than the base class. Pass the "base_assignment" flag of non-zero
1834  * here so that obt_assign knows that we don't want to translate
1835  * the values.
1836  */
1837  error = obt_assign (temp, att, 1, value, NULL);
1838  }
1839  }
1840 
1841  return error;
1842 }
1843 
1844 /*
1845  *
1846  * OBJECT CREATION AND DELETION
1847  *
1848  *
1849  */
1850 
1851 /*
1852  * obj_alloc - Allocate and initialize storage for an instance block.
1853  * return: instance block
1854  * class(in): class structure
1855  * bound_bit_status(in): nitial state for bound bits
1856  *
1857  * Note:
1858  * The bit_status argument has the initial state for the bound bits.
1859  * If it is zero, all bits are off, if it is non-zero, all bits are
1860  * on.
1861  */
1862 char *
1863 obj_alloc (SM_CLASS * class_, int bound_bit_status)
1864 {
1865  WS_OBJECT_HEADER *header;
1866  SM_ATTRIBUTE *att;
1867  char *obj, *mem;
1868  unsigned int *bits;
1869  int nwords, i;
1870 
1871  obj = (char *) db_ws_alloc (class_->object_size);
1872 
1873  if (obj != NULL)
1874  {
1875  /* initialize system header fields */
1876  header = (WS_OBJECT_HEADER *) obj;
1877  header->chn = NULL_CHN;
1878 
1879  /* init the bound bit vector */
1880  if (class_->fixed_count)
1881  {
1882  bits = (unsigned int *) (obj + OBJ_HEADER_BOUND_BITS_OFFSET);
1883  nwords = OR_BOUND_BIT_WORDS (class_->fixed_count);
1884  for (i = 0; i < nwords; i++)
1885  {
1886  if (bound_bit_status)
1887  {
1888  bits[i] = 0xFFFFFFFF;
1889  }
1890  else
1891  {
1892  bits[i] = 0;
1893  }
1894  }
1895  }
1896 
1897  /* clear the object */
1898  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
1899  {
1900  mem = obj + att->offset;
1901  att->domain->type->initmem (mem, att->domain);
1902  }
1903  }
1904 
1905  return obj;
1906 }
1907 
1908 /*
1909  * obj_create - Creates a new instance of a class.
1910  * return: new object
1911  * classop(in): class or instance pointer
1912  *
1913  * Note:
1914  * Formerly, this allocated the instance and assigned the default
1915  * values directly into the object. Now that triggers and
1916  * virtual classes complicate things, we use an insert template
1917  * for all creations.
1918  */
1919 
1920 MOP
1921 obj_create (MOP classop)
1922 {
1924  MOP new_mop;
1925 
1926  new_mop = NULL;
1927 
1928  obj_template = obt_def_object (classop);
1929  if (obj_template != NULL)
1930  {
1931  /* remember to disable the NON NULL integrity constraint checking */
1932  if (obt_update_internal (obj_template, &new_mop, 0))
1933  {
1934  obt_quit (obj_template);
1935  }
1936  }
1937  return (new_mop);
1938 }
1939 
1940 
1941 /*
1942  * obj_create_by_name - Create an instance of a class given the class name.
1943  * return: new object
1944  * name(in): class name
1945  *
1946  */
1947 
1948 MOP
1949 obj_create_by_name (const char *name)
1950 {
1951  MOP class_mop, obj;
1952  obj = NULL;
1953 
1954  if (name != NULL)
1955  {
1956  class_mop = sm_find_class (name);
1957  if (class_mop != NULL)
1958  {
1959  obj = obj_create (class_mop);
1960  }
1961  }
1962 
1963  return (obj);
1964 }
1965 
1966 /*
1967  * obj_copy -
1968  * return: new object
1969  * op(in): object to copy
1970  *
1971  * Note:
1972  * Utility function to do a simple object copy. This only does a single
1973  * level copy.
1974  * Formerly, this did a rather low level optimized copy of the object.
1975  * Now with virtual objects & triggers etc., we simply create an insert
1976  * template with the current values of the object.
1977  * This isn't particularly effecient but not very many people use
1978  * object copy anyway.
1979  *
1980  */
1981 
1982 MOP
1984 {
1986  MOP new_mop;
1987  SM_CLASS *class_;
1988  SM_ATTRIBUTE *att;
1989  MOBJ src;
1990  DB_VALUE value;
1991 
1992  new_mop = NULL;
1993  db_make_null (&value);
1994 
1995  /* op must be an object */
1996  if (op != NULL)
1997  {
1999 
2000  if (is_class < 0)
2001  {
2002  return NULL;
2003  }
2004  if (is_class)
2005  {
2007  return NULL;
2008  }
2009  }
2010  else
2011  {
2013  return NULL;
2014  }
2015 
2016  if (au_fetch_class (op, &class_, AU_FETCH_READ, AU_INSERT) != NO_ERROR)
2017  return NULL;
2018 
2019  /* do this so that we make really sure that op->class is set up */
2021  return NULL;
2022 
2023  obj_template = obt_def_object (ws_class_mop (op));
2024  if (obj_template != NULL)
2025  {
2026  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
2027  {
2028  if (obj_get_att (op, class_, att, &value) != NO_ERROR)
2029  goto error;
2030 
2031  if (obt_assign (obj_template, att, 0, &value, NULL) != NO_ERROR)
2032  goto error;
2033 
2034  (void) pr_clear_value (&value);
2035  }
2036 
2037  /* leaves new NULL if error */
2038  if (obt_update_internal (obj_template, &new_mop, 0) != NO_ERROR)
2039  {
2040  obt_quit (obj_template);
2041  }
2042  }
2043 
2044  return new_mop;
2045 
2046 error:
2047  obt_quit (obj_template);
2048 
2049  return NULL;
2050 }
2051 
2052 /*
2053  * obj_free_memory - This frees all of the storage allocated for an object.
2054  * return: none
2055  * class(in):
2056  * obj(in): object pointer
2057  *
2058  * Note:
2059  * It will be called indirectly by the workspace manager when an
2060  * object is decached.
2061  */
2062 
2063 void
2065 {
2066  SM_ATTRIBUTE *att;
2067  char *mem;
2068 
2069  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
2070  {
2071  mem = ((char *) obj) + att->offset;
2072  att->domain->type->freemem (mem);
2073  }
2074 
2075  db_ws_free (obj);
2076 }
2077 
2078 /*
2079  * obj_delete - This is the external function for deleting an object.
2080  * return: error code
2081  * op(in): instance pointer
2082  *
2083  * Note:
2084  * You cannot delete classes with this function, only instances. This will
2085  * decache the instance and mark the MOP as deleted but will not free the
2086  * MOP since there may be references to it in the application. The mop will
2087  * be garbage collected later.
2088  */
2089 int
2091 {
2092  int error = NO_ERROR, is_class = 0;
2093  SM_CLASS *class_ = NULL;
2094  SM_CLASS *base_class = NULL;
2095  DB_OBJECT *base_op = NULL;
2096  char *obj = NULL;
2097  int pin = 0;
2098  int pin2 = 0;
2099  bool unpin_on_error = false;
2100  TR_STATE *trstate = NULL;
2101 
2102  /* op must be an object */
2103  if (op != NULL)
2104  {
2105  is_class = locator_is_class (op, DB_FETCH_WRITE);
2106  if (is_class < 0)
2107  {
2108  error = is_class;
2109  goto error_exit;
2110  }
2111  if (is_class > 0)
2112  {
2114  goto error_exit;
2115  }
2116  }
2117  else
2118  {
2120  goto error_exit;
2121  }
2122 
2123  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_DELETE);
2124  if (error != NO_ERROR)
2125  {
2126  goto error_exit;
2127  }
2128 
2130  if (error != NO_ERROR)
2131  {
2132  goto error_exit;
2133  }
2134 
2135  /*
2136  * Note that if "op" is a VMOP, au_fetch_instance () will have returned
2137  * "obj" as a pointer to the BASE INSTANCE memory which is not the instance
2138  * associated with "op". When this happens we need to get the base MOP so
2139  * that it can be passed down to other functions that need to look at the
2140  * "obj" instance memory block.
2141  */
2142  base_op = op;
2143  if (op->is_vid && class_->class_type == SM_VCLASS_CT)
2144  {
2145  /*
2146  * This is a view, get the base MOP.
2147  * What happens here if this is a non-updatable view?
2148  */
2149  base_op = vid_get_referenced_mop (op);
2150  if (base_op == NULL)
2151  {
2153  goto error_exit;
2154  }
2155  au_fetch_class (base_op, &base_class, AU_FETCH_READ, AU_DELETE);
2156  }
2157 
2158  /* We need to keep it pinned for the duration of trigger processing. */
2159  pin = ws_pin (op, 1);
2160  if (base_op != NULL && base_op != op)
2161  {
2162  pin2 = ws_pin (base_op, 1);
2163  }
2164  unpin_on_error = true;
2165 
2166  /* Run BEFORE triggers */
2167  if (base_class != NULL)
2168  {
2169  error = tr_prepare_class (&trstate, base_class->triggers, base_op, TR_EVENT_DELETE);
2170  if (error != NO_ERROR)
2171  {
2172  goto error_exit;
2173  }
2174  error = tr_before_object (trstate, base_op, NULL);
2175  if (error != NO_ERROR)
2176  {
2177  goto error_exit;
2178  }
2179 
2180  /* in some cases, the object has been decached in before trigger. we need fetch it again. */
2181  if (base_op->decached)
2182  {
2183  error = au_fetch_class (base_op, &base_class, AU_FETCH_READ, AU_DELETE);
2184  if (error != NO_ERROR)
2185  {
2186  goto error_exit;
2187  }
2188  }
2189  }
2190  else
2191  {
2192  error = tr_prepare_class (&trstate, class_->triggers, ws_class_mop (op), TR_EVENT_DELETE);
2193  if (error != NO_ERROR)
2194  {
2195  goto error_exit;
2196  }
2197  error = tr_before_object (trstate, op, NULL);
2198  if (error != NO_ERROR)
2199  {
2200  goto error_exit;
2201  }
2202 
2203  /* in some cases, the object has been decached in before trigger. we need fetch it again. */
2204  if (op->decached)
2205  {
2207  if (error != NO_ERROR)
2208  {
2209  goto error_exit;
2210  }
2211  }
2212  }
2213 
2214  /*
2215  * Unpin this now since the remaining operations will mark the instance as
2216  * deleted and it doesn't make much sense to have pinned & deleted objects.
2217  */
2218  (void) ws_pin (op, pin);
2219  if (base_op != NULL && base_op != op)
2220  {
2221  (void) ws_pin (base_op, pin2);
2222  }
2223  unpin_on_error = false;
2224 
2225  /*
2226  * We don't need to decache the object as it will be decached when the mop
2227  * is GC'd in the usual way.
2228  */
2229 
2230  if (op->is_vid)
2231  {
2232  vid_rem_instance (op);
2233  }
2234  else
2235  {
2237  }
2238 
2239  /* Run AFTER triggers */
2240  if (trstate != NULL)
2241  {
2242  error = tr_after_object (trstate, NULL, NULL);
2243  if (error != NO_ERROR)
2244  {
2245  goto error_exit;
2246  }
2247  }
2248 
2249  return error;
2250 
2251 error_exit:
2252  if (unpin_on_error)
2253  {
2254  /* trigger failure, remember to unpin */
2255  (void) ws_pin (op, pin);
2256  if (base_op != NULL && base_op != op)
2257  {
2258  (void) ws_pin (base_op, pin2);
2259  }
2260  unpin_on_error = false;
2261  }
2262  return error;
2263 }
2264 
2265 /*
2266  * METHOD CALL SUPPORT FUNCTIONS
2267  *
2268  */
2269 
2270 /*
2271  * argstate_from_list - Builds a cannonical argument state structure
2272  * from a DB_VALUE_LIST.
2273  * return: none
2274  * state(in): method argument state
2275  * arglist(in): argument list
2276  *
2277  */
2278 
2279 static void
2281 {
2282  DB_VALUE_LIST *arg;
2283  int i;
2284 
2285  for (i = 0, arg = arglist; arg != NULL && i < OBJ_MAX_ARGS; arg = arg->next, i++)
2286  {
2287  state->values[i] = &(arg->val);
2288  state->save[i] = NULL;
2289  }
2290 
2291  state->nargs = i;
2292  state->overflow = arg;
2293  state->free_overflow = 0;
2294  state->save_overflow = NULL;
2295  for (i = 0; arg != NULL; arg = arg->next, i++)
2296  ;
2297  state->noverflow = i;
2298 }
2299 
2300 /*
2301  * argstate_from_array - Builds a cannonical argument state
2302  * from an array of DB_VALUEs
2303  * return: none
2304  * state(in): method argument state
2305  * argarray(in): array of DB_VALUE pointers
2306  *
2307  */
2308 
2309 static void
2310 argstate_from_array (ARGSTATE * state, DB_VALUE ** argarray)
2311 {
2312  int i, j;
2313 
2314  state->overflow = NULL;
2315  state->noverflow = 0;
2316  state->save_overflow = NULL;
2317  state->free_overflow = 0;
2318  if (argarray == NULL)
2319  {
2320  state->nargs = 0;
2321  }
2322  else
2323  {
2324  for (i = 0; argarray[i] != NULL && i < OBJ_MAX_ARGS; i++)
2325  {
2326  state->values[i] = argarray[i];
2327  state->save[i] = NULL;
2328  }
2329  state->nargs = i;
2330  /* need to handle overflow arguments ! */
2331  for (j = 0; argarray[i] != NULL; i++, j++)
2332  ;
2333  state->noverflow = j;
2334  }
2335 }
2336 
2337 /*
2338  * argstate_from_va - Builds a cannonical argument state
2339  * from a va_list of arguments.
2340  * return: none
2341  * state(in): method argument state
2342  * args(in): va_list style argument list
2343  * nargs(in): expected number of arguments
2344  *
2345  */
2346 
2347 static void
2348 argstate_from_va (ARGSTATE * state, va_list args, int nargs)
2349 {
2350  int i;
2351 
2352  state->nargs = nargs;
2353  state->overflow = NULL;
2354  state->free_overflow = 0;
2355  state->save_overflow = NULL;
2356  for (i = 0; i < nargs && i < OBJ_MAX_ARGS; i++)
2357  {
2358  state->values[i] = va_arg (args, DB_VALUE *);
2359  state->save[i] = NULL;
2360  }
2361 
2362  /* need to handle overflow arguments ! */
2363  state->noverflow = nargs - i;
2364 }
2365 
2366 /*
2367  * cleanup_argstate -
2368  * return: none
2369  * state(in): method argument state
2370  *
2371  * Note:
2372  * This is called after an argstate structure is no longer needed.
2373  * It frees any additional resources that were required during the
2374  * processing of the method call.
2375  * Currently this will consist only of argument values that had to
2376  * be coerced from their original values.
2377  */
2378 
2379 static void
2381 {
2382  int i;
2383 
2384  /* free values for arguments that were coerced */
2385  for (i = 0; i < state->nargs; i++)
2386  {
2387  if (state->save[i] != NULL)
2388  {
2389  /* we have a coerced value in the corresponding value slot */
2390  (void) pr_free_ext_value (state->values[i]);
2391  state->values[i] = state->save[i];
2392  state->save[i] = NULL;
2393  }
2394  }
2395 
2396  /* free the overflow list if it was created from a "va" call */
2397 }
2398 
2399 /*
2400  * call_method - This makes the actual call to the method function and passes
2401  * the arguments.
2402  * The arguments are taken from the value array in the argument
2403  * state structure
2404  * return: int
2405  * method(in):method function pointer
2406  * obj(in):"self" object of the method
2407  * returnval(in):return value pointer
2408  * nargs(in):
2409  * values(in):
2410  * overflow(in):
2411  *
2412  * Note:
2413  *
2414  * Forcing NULL into the first 4 arguments was necessary at some
2415  * point because the old interpreter didn't do any argument checking.
2416  * It may not be necessary any more but be very careful before removing
2417  * it.
2418  *
2419  */
2420 static int
2421 call_method (METHOD_FUNCTION method, MOP obj, DB_VALUE * returnval, int nargs, DB_VALUE ** values,
2423 {
2424  int error = NO_ERROR;
2425 
2427  if (obj_Method_call_level == 1)
2428  { /* not nested method call */
2430  {
2432  }
2433  }
2434 
2435  if (!forge_flag_pat)
2436  {
2437  db_make_null (returnval);
2438  }
2439 
2440  switch (nargs)
2441  {
2442  case 0:
2443  ((METHOD_FUNC_ARG4) (*method)) (obj, returnval, NULL, NULL, NULL, NULL);
2444  break;
2445  case 1:
2446  ((METHOD_FUNC_ARG4) (*method)) (obj, returnval, values[0], NULL, NULL, NULL);
2447  break;
2448  case 2:
2449  ((METHOD_FUNC_ARG4) (*method)) (obj, returnval, values[0], values[1], NULL, NULL);
2450  break;
2451  case 3:
2452  ((METHOD_FUNC_ARG4) (*method)) (obj, returnval, values[0], values[1], values[2], NULL);
2453  break;
2454  case 4:
2455  ((METHOD_FUNC_ARG4) (*method)) (obj, returnval, values[0], values[1], values[2], values[3]);
2456  break;
2457  case 5:
2458  ((METHOD_FUNC_ARG5) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4]);
2459  break;
2460  case 6:
2461  ((METHOD_FUNC_ARG6) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5]);
2462  break;
2463  case 7:
2464  ((METHOD_FUNC_ARG7) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2465  values[6]);
2466  break;
2467  case 8:
2468  ((METHOD_FUNC_ARG8) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2469  values[6], values[7]);
2470  break;
2471  case 9:
2472  ((METHOD_FUNC_ARG9) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2473  values[6], values[7], values[8]);
2474  break;
2475  case 10:
2476  ((METHOD_FUNC_ARG10) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2477  values[6], values[7], values[8], values[9]);
2478  break;
2479  case 11:
2480  ((METHOD_FUNC_ARG11) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2481  values[6], values[7], values[8], values[9], values[10]);
2482  break;
2483  case 12:
2484  ((METHOD_FUNC_ARG12) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2485  values[6], values[7], values[8], values[9], values[10], values[11]);
2486  break;
2487  case 13:
2488  ((METHOD_FUNC_ARG13) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2489  values[6], values[7], values[8], values[9], values[10], values[11], values[12]);
2490  break;
2491  case 14:
2492  ((METHOD_FUNC_ARG14) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2493  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2494  values[13]);
2495  break;
2496  case 15:
2497  ((METHOD_FUNC_ARG15) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2498  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2499  values[13], values[14]);
2500  break;
2501  case 16:
2502  ((METHOD_FUNC_ARG16) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2503  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2504  values[13], values[14], values[15]);
2505  break;
2506  case 17:
2507  ((METHOD_FUNC_ARG17) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2508  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2509  values[13], values[14], values[15], values[16]);
2510  break;
2511  case 18:
2512  ((METHOD_FUNC_ARG18) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2513  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2514  values[13], values[14], values[15], values[16], values[17]);
2515  break;
2516  case 19:
2517  ((METHOD_FUNC_ARG19) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2518  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2519  values[13], values[14], values[15], values[16], values[17], values[18]);
2520  break;
2521  case 20:
2522  ((METHOD_FUNC_ARG20) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2523  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2524  values[13], values[14], values[15], values[16], values[17], values[18],
2525  values[19]);
2526  break;
2527  case 21:
2528  ((METHOD_FUNC_ARG21) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2529  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2530  values[13], values[14], values[15], values[16], values[17], values[18],
2531  values[19], values[20]);
2532  break;
2533  case 22:
2534  ((METHOD_FUNC_ARG22) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2535  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2536  values[13], values[14], values[15], values[16], values[17], values[18],
2537  values[19], values[20], values[21]);
2538  break;
2539  case 23:
2540  ((METHOD_FUNC_ARG23) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2541  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2542  values[13], values[14], values[15], values[16], values[17], values[18],
2543  values[19], values[20], values[21], values[22]);
2544  break;
2545  case 24:
2546  ((METHOD_FUNC_ARG24) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2547  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2548  values[13], values[14], values[15], values[16], values[17], values[18],
2549  values[19], values[20], values[21], values[22], values[23]);
2550  break;
2551  case 25:
2552  ((METHOD_FUNC_ARG25) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2553  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2554  values[13], values[14], values[15], values[16], values[17], values[18],
2555  values[19], values[20], values[21], values[22], values[23], values[24]);
2556  break;
2557  case 26:
2558  ((METHOD_FUNC_ARG26) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2559  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2560  values[13], values[14], values[15], values[16], values[17], values[18],
2561  values[19], values[20], values[21], values[22], values[23], values[24],
2562  values[25]);
2563  break;
2564  case 27:
2565  ((METHOD_FUNC_ARG27) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2566  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2567  values[13], values[14], values[15], values[16], values[17], values[18],
2568  values[19], values[20], values[21], values[22], values[23], values[24],
2569  values[25], values[26]);
2570  break;
2571  case 28:
2572  ((METHOD_FUNC_ARG28) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2573  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2574  values[13], values[14], values[15], values[16], values[17], values[18],
2575  values[19], values[20], values[21], values[22], values[23], values[24],
2576  values[25], values[26], values[27]);
2577  break;
2578  case 29:
2579  ((METHOD_FUNC_ARG29) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2580  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2581  values[13], values[14], values[15], values[16], values[17], values[18],
2582  values[19], values[20], values[21], values[22], values[23], values[24],
2583  values[25], values[26], values[27], values[28]);
2584  break;
2585  case 30:
2586  ((METHOD_FUNC_ARG30) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2587  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2588  values[13], values[14], values[15], values[16], values[17], values[18],
2589  values[19], values[20], values[21], values[22], values[23], values[24],
2590  values[25], values[26], values[27], values[28], values[29]);
2591  break;
2592  case 31:
2593  ((METHOD_FUNC_ARG31) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2594  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2595  values[13], values[14], values[15], values[16], values[17], values[18],
2596  values[19], values[20], values[21], values[22], values[23], values[24],
2597  values[25], values[26], values[27], values[28], values[29], values[30]);
2598  break;
2599  case 32:
2600  ((METHOD_FUNC_ARG32) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2601  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2602  values[13], values[14], values[15], values[16], values[17], values[18],
2603  values[19], values[20], values[21], values[22], values[23], values[24],
2604  values[25], values[26], values[27], values[28], values[29], values[30],
2605  values[31]);
2606  break;
2607  default:
2608  ((METHOD_FUNC_ARG33) (*method)) (obj, returnval, values[0], values[1], values[2], values[3], values[4], values[5],
2609  values[6], values[7], values[8], values[9], values[10], values[11], values[12],
2610  values[13], values[14], values[15], values[16], values[17], values[18],
2611  values[19], values[20], values[21], values[22], values[23], values[24],
2612  values[25], values[26], values[27], values[28], values[29], values[30],
2613  values[31], overflow);
2614  break;
2615  }
2616 
2618  if (!forge_flag_pat)
2619  if (DB_VALUE_TYPE (returnval) == DB_TYPE_ERROR)
2620  {
2621  error = db_get_error (returnval);
2622  if (error >= 0)
2623  {
2624  /* it's not a system error, it's a user error */
2626  error = er_errid ();
2627  }
2628  }
2629 
2630  return error;
2631 }
2632 
2633 /*
2634  * check_args - This performs argument validation prior to a method call.
2635  * return: error code
2636  * method(in): method
2637  * state(in): argument state
2638  *
2639  * Note :
2640  * If the method has no signature or if the argument list is NULL,
2641  * the values will be passed through unchecked.
2642  *
2643  * This needs to be changed in a number of ways for the next release.
2644  * First, there is no way currently of defining a method that must
2645  * accept NO arguments. The absense of an argument list is taken to
2646  * mean a "wildcard" argument list.
2647  * Second, there needs to be a more formal definition of when an argument
2648  * is passed by reference vs. passed by value. This is especially
2649  * important when set coercion is happening.
2650  * Third, the method argument lists should be stored in a packed array
2651  * for quick lookup.
2652  */
2653 static int
2654 check_args (SM_METHOD * method, ARGSTATE * state)
2655 {
2656  int error = NO_ERROR;
2657  SM_METHOD_SIGNATURE *sig;
2658  SM_METHOD_ARGUMENT *arg;
2659  DB_VALUE *value;
2660  int i;
2661  TP_DOMAIN_STATUS status;
2662  TP_DOMAIN *dom;
2663 
2664  /* assume only one signature */
2665  sig = method->signatures;
2666  if (sig != NULL && sig->args != NULL)
2667  {
2668 
2669  for (i = 0; i < state->nargs && error == NO_ERROR; i++)
2670  {
2671 
2672  /*
2673  * find the argument matching this value, this should be an array lookup !
2674  * remember the arg index is one based
2675  */
2676  for (arg = sig->args; arg != NULL && arg->index != i + 1; arg = arg->next);
2677  /*
2678  * if there is no definition for a particular argument, assume it
2679  * is a "wildcard" and will match any domain
2680  */
2681  if (arg != NULL)
2682  {
2683  /*
2684  * Try to use exact domain matching for method arguments !
2685  */
2686  dom = tp_domain_select (arg->domain, state->values[i], 0, TP_EXACT_MATCH);
2687  if (dom == NULL)
2688  {
2689  /*
2690  * We don't have an exact match, so try a "near" match, i.e.,
2691  * one where we can get what we want simply by changing a
2692  * string domain (without actually copying the string). This
2693  * is important for trying to keep "output parameters" working.
2694  */
2695  value = pr_make_ext_value ();
2696  if (value == NULL)
2697  {
2698  assert (er_errid () != NO_ERROR);
2699  return er_errid ();
2700  }
2701  dom = tp_domain_select (arg->domain, state->values[i], 0, TP_STR_MATCH);
2702  if (dom)
2703  {
2704  *value = *state->values[i];
2705  value->need_clear = false;
2706  status = tp_value_coerce (value, value, arg->domain);
2707  }
2708  else
2709  {
2710  status = tp_value_cast (state->values[i], value, arg->domain, 0);
2711  }
2712 
2713  if (status == DOMAIN_COMPATIBLE)
2714  {
2715  /* pass the coerced value but remember to free it later */
2716  state->save[i] = state->values[i];
2717  state->values[i] = value;
2718  }
2719  else
2720  {
2721  (void) pr_free_ext_value (value);
2722  }
2723  }
2724  else
2725  {
2726  status = DOMAIN_COMPATIBLE;
2727  }
2728 
2729  if (status != DOMAIN_COMPATIBLE)
2730  {
2731  char domain1[MAX_DOMAIN_NAME];
2732  char domain2[MAX_DOMAIN_NAME];
2733 
2734  switch (status)
2735  {
2736  case DOMAIN_ERROR:
2737  assert (er_errid () != NO_ERROR);
2738  error = er_errid ();
2739  break;
2740 
2741  case DOMAIN_OVERFLOW:
2742  case DOMAIN_INCOMPATIBLE:
2743  default:
2745  tp_domain_name (arg->domain, domain1, MAX_DOMAIN_NAME);
2746  tp_value_domain_name (state->values[i], domain2, MAX_DOMAIN_NAME);
2747  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 4, method->header.name, arg->index, domain1,
2748  domain2);
2749  break;
2750  }
2751  }
2752  }
2753  }
2754  }
2755 
2756  return (error);
2757 }
2758 
2759 /*
2760  * METHOD INVOCATION FUNCTIONS
2761  *
2762  */
2763 
2764 /*
2765  * These all do basically the same thing, the only difference is the
2766  * way in which the arguments are passed.
2767  */
2768 
2769 /*
2770  * obj_send_method_va - This invokes a method where the arguments are
2771  * supplied with a va_list.
2772  * return: error code
2773  * obj(in): object to receive the message
2774  * class(in): class structure
2775  * method(in): method structure
2776  * returnval(out): return value container
2777  * args(in): va_list with arguments
2778  *
2779  * Note:
2780  * It is called by both obj_send_va() and obj_desc_send_va().
2781  */
2782 static int
2783 obj_send_method_va (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval, va_list args)
2784 {
2785  ARGSTATE state;
2786  int error = NO_ERROR;
2787  SM_METHOD_SIGNATURE *sig;
2788  METHOD_FUNCTION func;
2789  int expected;
2790 
2791  func = method->function;
2792  if (func == NULL)
2793  {
2794  error = sm_link_method (class_, method);
2795  func = method->function;
2796  }
2797  if (func != NULL)
2798  {
2799  sig = method->signatures;
2800  /*
2801  * calculate the expected number of arguments
2802  * allow the case where the arg count is set but there are no
2803  * arg definitions, should be an error
2804  */
2805  expected = (sig != NULL && sig->num_args) ? sig->num_args : OBJ_MAX_ARGS;
2806  /* get the arguments into the cannonical array */
2807  argstate_from_va (&state, args, expected);
2808  /* need to handle this gracefully someday */
2809  if (state.noverflow)
2810  {
2811  ERROR3 (error, ER_OBJ_TOO_MANY_ARGUMENTS, method->header.name, state.nargs + state.noverflow, OBJ_MAX_ARGS);
2812  }
2813  else
2814  {
2815  /* check argument domains if there are any */
2816  if (sig != NULL && sig->args != NULL)
2817  error = check_args (method, &state);
2818  if (error == NO_ERROR)
2819  error = call_method (func, obj, returnval, state.nargs, state.values, state.overflow);
2820  }
2821 
2822  cleanup_argstate (&state);
2823  }
2824 
2825  return (error);
2826 }
2827 
2828 /*
2829  * obj_send_va - Call a method by name with arguments as a va_list
2830  * return: error code
2831  * obj(in): object
2832  * name(in): method name
2833  * returnval(out): return value container
2834  * args(in): argument list
2835  *
2836  */
2837 int
2838 obj_send_va (MOP obj, const char *name, DB_VALUE * returnval, va_list args)
2839 {
2840  int error = NO_ERROR;
2841  SM_CLASS *class_;
2842  SM_METHOD *method;
2843  bool class_method;
2844 
2845  if ((obj == NULL) || (name == NULL))
2846  {
2848  }
2849  else
2850  {
2851  error = au_fetch_class (obj, &class_, AU_FETCH_READ, AU_EXECUTE);
2852  if (error == NO_ERROR)
2853  {
2854  /* rare case when its ok to use this macro */
2855  class_method = (IS_CLASS_MOP (obj)) ? true : false;
2856  method = classobj_find_method (class_, name, class_method);
2857  if (method == NULL)
2858  {
2859  ERROR1 (error, ER_OBJ_INVALID_METHOD, name);
2860  }
2861  else
2862  {
2863  error = obj_send_method_va (obj, class_, method, returnval, args);
2864  }
2865  }
2866  }
2867 
2868  return error;
2869 }
2870 
2871 /*
2872  * obj_desc_send_va - Call a method using a descritor with arguments
2873  * as a va_list.
2874  * return: error code
2875  * obj(in): object
2876  * desc(in): descriptor
2877  * returnval(out): return value container
2878  * args(in): argument list
2879  *
2880  */
2881 int
2882 obj_desc_send_va (MOP obj, SM_DESCRIPTOR * desc, DB_VALUE * returnval, va_list args)
2883 {
2884  int error = NO_ERROR;
2885  SM_CLASS *class_;
2886  SM_METHOD *method;
2887 
2888  if ((obj == NULL) || (desc == NULL))
2889  {
2891  }
2892  else
2893  {
2894  error = sm_get_descriptor_component (obj, desc, 0, &class_, (SM_COMPONENT **) (&method));
2895  if (error == NO_ERROR)
2896  {
2897  error = obj_send_method_va (obj, class_, method, returnval, args);
2898  }
2899  }
2900 
2901  return error;
2902 }
2903 
2904 #if defined(ENABLE_UNUSED_FUNCTION)
2905 /*
2906  * obj_send_stack - This invokes a method where the arguments are passed
2907  * directly on the stack
2908  *
2909  * return :error code
2910  * obj(in): object to receive the message
2911  * name(in): method name
2912  * returnval(out): return value container
2913  *
2914  * Note:
2915  * This invokes a method where the arguments are passed directly
2916  * on the stack. It calls obj_send_va to do the work after buidling
2917  * the va_list from the arguments passed to this function.
2918  *
2919  */
2920 int
2921 obj_send_stack (MOP obj, const char *name, DB_VALUE * returnval, ...)
2922 {
2923  int error = NO_ERROR;
2924  va_list args;
2925 
2926  va_start (args, returnval);
2927  error = obj_send_va (obj, name, returnval, args);
2928  va_end (args);
2929 
2930  return (error);
2931 }
2932 
2933 /*
2934  * obj_desc_send_stack - Call a method using a descritor with
2935  * arguments on the stack.
2936  *
2937  * return: error code
2938  * obj(in): object
2939  * desc(in): descriptor
2940  * returnval(out): return value container
2941  * args(in): argument list
2942  *
2943  * Note :
2944  * Call a method using a descritor with arguments on the stack.
2945  *
2946  */
2947 
2948 int
2949 obj_desc_send_stack (MOP obj, SM_DESCRIPTOR * desc, DB_VALUE * returnval, ...)
2950 {
2951  int error = NO_ERROR;
2952  va_list args;
2953  va_start (args, returnval);
2954  error = obj_desc_send_va (obj, desc, returnval, args);
2955  va_end (args);
2956  return (error);
2957 }
2958 #endif /* ENABLE_UNUSED_FUNCTION */
2959 
2960 /*
2961  * obj_send_method_list - This invokes a method where the arguments are
2962  * contained in a linked list of DB_VALUE_LIST structures.
2963  * return: error code
2964  * obj(in): object to receive message
2965  * class(in): class structure
2966  * method(in): method structure
2967  * returnval(in): return value container
2968  * arglist(in): argument list
2969  *
2970  * Note:
2971  * Used by both obj_send_list() and obj_desc_send_list().
2972  */
2973 static int
2974 obj_send_method_list (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval, DB_VALUE_LIST * arglist)
2975 {
2976  int error = NO_ERROR;
2977  ARGSTATE state;
2978  SM_METHOD_SIGNATURE *sig;
2979  METHOD_FUNCTION func;
2980  int expected;
2981 
2982  func = method->function;
2983  if (func == NULL)
2984  {
2985  error = sm_link_method (class_, method);
2986  func = method->function;
2987  }
2988 
2989  if (func != NULL)
2990  {
2991  sig = method->signatures;
2992 
2993  /*
2994  * calculate the expected number of arguments
2995  * allow the case where the arg count is set but there are no
2996  * arg definitions, should be an error
2997  */
2998  expected = ((sig != NULL && sig->num_args) ? sig->num_args : OBJ_MAX_ARGS);
2999 
3000  /* get the arguments into the cannonical array */
3001  argstate_from_list (&state, arglist);
3002 
3003  /* need to handle this gracefully someday */
3004  if (state.noverflow)
3005  {
3006  ERROR3 (error, ER_OBJ_TOO_MANY_ARGUMENTS, method->header.name, state.nargs + state.noverflow, OBJ_MAX_ARGS);
3007  }
3008  else
3009  {
3010  /*
3011  * what happens when the actual count doesn't match the expected
3012  * count and there is no domain definition ?
3013  * for now, assume the supplied args are correct
3014  */
3015 
3016  /* check argument domains if there are any */
3017  if (sig != NULL && sig->args != NULL)
3018  {
3019  error = check_args (method, &state);
3020  }
3021  if (error == NO_ERROR)
3022  {
3023  error = call_method (func, obj, returnval, state.nargs, state.values, state.overflow);
3024  }
3025  }
3026 
3027  cleanup_argstate (&state);
3028  }
3029 
3030  return (error);
3031 }
3032 
3033 /*
3034  * obj_send_list - Call a method using a name with arguments in a list.
3035  * return: error code
3036  * obj(in): object
3037  * name(in): method name
3038  * returnval(out): return value container
3039  * arglist(in): argument list
3040  *
3041  */
3042 int
3043 obj_send_list (MOP obj, const char *name, DB_VALUE * returnval, DB_VALUE_LIST * arglist)
3044 {
3045  int error = NO_ERROR;
3046  SM_CLASS *class_;
3047  SM_METHOD *method;
3048  bool class_method;
3049 
3050  if ((obj == NULL) || (name == NULL))
3051  {
3053  }
3054  else
3055  {
3056  error = au_fetch_class (obj, &class_, AU_FETCH_READ, AU_EXECUTE);
3057  if (error == NO_ERROR)
3058  {
3059  /* rare case when its ok to use this macro */
3060  class_method = (IS_CLASS_MOP (obj)) ? true : false;
3061  method = classobj_find_method (class_, name, class_method);
3062  if (method == NULL)
3063  {
3064  ERROR1 (error, ER_OBJ_INVALID_METHOD, name);
3065  }
3066  else
3067  {
3068  error = obj_send_method_list (obj, class_, method, returnval, arglist);
3069  }
3070  }
3071  }
3072 
3073  return error;
3074 }
3075 
3076 #if defined(ENABLE_UNUSED_FUNCTION)
3077 /* obsolete, some tests use this, need to change them */
3078 
3079 /*
3080  * obj_send -
3081  * return: error code
3082  * obj(in): object
3083  * name(in): method name
3084  * returnval(out): return value container
3085  * arglist(in): argument list
3086  *
3087  */
3088 int
3089 obj_send (MOP obj, const char *name, DB_VALUE * returnval, DB_VALUE_LIST * arglist)
3090 {
3091  return (obj_send_list (obj, name, returnval, arglist));
3092 }
3093 #endif /* ENABLE_UNUSED_FUNCTION */
3094 
3095 /*
3096  * obj_desc_send_list - Call a method using a descritor with arguments in a list
3097  * return: error code
3098  * obj(in): object
3099  * desc(in): descriptor
3100  * returnval(out): return value container
3101  * arglist(in): argument list
3102  *
3103  */
3104 int
3105 obj_desc_send_list (MOP obj, SM_DESCRIPTOR * desc, DB_VALUE * returnval, DB_VALUE_LIST * arglist)
3106 {
3107  int error = NO_ERROR;
3108  SM_CLASS *class_;
3109  SM_METHOD *method;
3110 
3111  if ((obj == NULL) || (desc == NULL))
3112  {
3114  }
3115  else
3116  {
3117  error = sm_get_descriptor_component (obj, desc, 0, &class_, (SM_COMPONENT **) (&method));
3118  if (error == NO_ERROR)
3119  {
3120  error = obj_send_method_list (obj, class_, method, returnval, arglist);
3121  }
3122  }
3123 
3124  return error;
3125 }
3126 
3127 /*
3128  * obj_send_method_array - This invokes a method where the arguments are
3129  * supplied in an array of DB_VALUE pointers.
3130  * Used by both obj_send_array() and
3131  * obj_desc_send_array().
3132  * return: error code
3133  * obj(in): object to receive message
3134  * class(in): class structure
3135  * method(in): method structure
3136  * returnval(out): return value container
3137  * argarray(in): array of argument values
3138  *
3139  */
3140 
3141 static int
3142 obj_send_method_array (MOP obj, SM_CLASS * class_, SM_METHOD * method, DB_VALUE * returnval, DB_VALUE ** argarray)
3143 {
3144  int error = NO_ERROR;
3145  ARGSTATE state;
3146  SM_METHOD_SIGNATURE *sig;
3147  METHOD_FUNCTION func;
3148  int expected;
3149 
3150  func = method->function;
3151  if (func == NULL)
3152  {
3153  error = sm_link_method (class_, method);
3154  func = method->function;
3155  }
3156 
3157  if (func != NULL)
3158  {
3159  sig = method->signatures;
3160 
3161  /*
3162  * calculate the expected number of arguments
3163  * allow the case where the arg count is set but there are no
3164  * arg definitions, should be an error
3165  */
3166  expected = ((sig != NULL && sig->num_args) ? sig->num_args : OBJ_MAX_ARGS);
3167 
3168  /* get the arguments into the cannonical array */
3169  argstate_from_array (&state, argarray);
3170 
3171  /* need to handle this gracefully someday */
3172  if (state.noverflow)
3173  {
3174  ERROR3 (error, ER_OBJ_TOO_MANY_ARGUMENTS, method->header.name, state.nargs + state.noverflow, OBJ_MAX_ARGS);
3175  }
3176  else
3177  {
3178  /*
3179  * what happens when the actual count doesn't match the expected
3180  * count and there is no domain definition ?
3181  * for now, assume the supplied args are correct
3182  */
3183 
3184  /* check argument domains if there are any */
3185  if (sig != NULL && sig->args != NULL)
3186  {
3187  error = check_args (method, &state);
3188  }
3189  if (error == NO_ERROR)
3190  {
3191  error = call_method (func, obj, returnval, state.nargs, state.values, state.overflow);
3192  }
3193  }
3194 
3195  cleanup_argstate (&state);
3196  }
3197 
3198  return (error);
3199 }
3200 
3201 /*
3202  * obj_send_array - Call a method using a name with arguments in an array.
3203  * return: error code
3204  * obj(in): object
3205  * name(in): method name
3206  * returnval(out): return value container
3207  * argarray(in): argument array
3208  *
3209  */
3210 int
3211 obj_send_array (MOP obj, const char *name, DB_VALUE * returnval, DB_VALUE ** argarray)
3212 {
3213  int error = NO_ERROR;
3214  SM_CLASS *class_;
3215  SM_METHOD *method;
3216  bool class_method;
3217 
3218  if ((obj == NULL) || (name == NULL))
3219  {
3221  }
3222  else
3223  {
3224  error = au_fetch_class (obj, &class_, AU_FETCH_READ, AU_EXECUTE);
3225  if (error == NO_ERROR)
3226  {
3227  /* rare case when its ok to use this macro */
3228  class_method = (IS_CLASS_MOP (obj)) ? true : false;
3229  method = classobj_find_method (class_, name, class_method);
3230  if (method == NULL)
3231  {
3232  ERROR1 (error, ER_OBJ_INVALID_METHOD, name);
3233  }
3234  else
3235  {
3236  error = obj_send_method_array (obj, class_, method, returnval, argarray);
3237  }
3238  }
3239  }
3240 
3241  return error;
3242 }
3243 
3244 /*
3245  * obj_desc_send_array - Call a method using a descritor with arguments in an array.
3246  * return: error code
3247  * obj(in): object
3248  * desc(in): descriptor
3249  * returnval(out): return value container
3250  * argarray(in): argument array
3251  *
3252  */
3253 int
3254 obj_desc_send_array (MOP obj, SM_DESCRIPTOR * desc, DB_VALUE * returnval, DB_VALUE ** argarray)
3255 {
3256  int error = NO_ERROR;
3257  SM_CLASS *class_;
3258  SM_METHOD *method;
3259 
3260  if ((obj == NULL) || (desc == NULL))
3261  {
3263  }
3264  else
3265  {
3266  error = sm_get_descriptor_component (obj, desc, 0, &class_, (SM_COMPONENT **) (&method));
3267  if (error == NO_ERROR)
3268  {
3269  error = obj_send_method_array (obj, class_, method, returnval, argarray);
3270  }
3271  }
3272 
3273  return error;
3274 }
3275 
3276 /*
3277  * obj_desc_send_array_quick - Call a method using a descritor
3278  * with arguments in an array.
3279  * return: error code
3280  * obj(in): object
3281  * desc(in): descriptor
3282  * returnval(out): return value container
3283  * nargs(in): number of arguments in array
3284  * argarray(in): argument array
3285  *
3286  * Note:
3287  * This is intended to be used by the parser to make repeated calls
3288  * to methods when the arguments have already been validated/coerced.
3289  * It simply gets the appropriate method from the descriptor and
3290  * passes the argument array directly to call_method() without doing
3291  * any type checking.
3292  */
3293 int
3294 obj_desc_send_array_quick (MOP obj, SM_DESCRIPTOR * desc, DB_VALUE * returnval, int nargs, DB_VALUE ** argarray)
3295 {
3296  int error = NO_ERROR;
3297  SM_CLASS *class_;
3298  SM_METHOD *method;
3299  METHOD_FUNCTION func;
3300 
3301  if ((obj == NULL) || (desc == NULL))
3302  {
3304  }
3305  else
3306  {
3307  error = sm_get_descriptor_component (obj, desc, 0, &class_, (SM_COMPONENT **) (&method));
3308  if (error == NO_ERROR)
3309  {
3310  func = method->function;
3311  if (func == NULL)
3312  {
3313  error = sm_link_method (class_, method);
3314  func = method->function;
3315  }
3316 
3317  if (func != NULL)
3318  {
3319  /* need to handle this gracefully someday */
3320  if (nargs > OBJ_MAX_ARGS)
3321  {
3322  ERROR3 (error, ER_OBJ_TOO_MANY_ARGUMENTS, method->header.name, nargs, OBJ_MAX_ARGS);
3323  }
3324  else
3325  {
3326  error = call_method (func, obj, returnval, nargs, argarray, NULL);
3327  }
3328  }
3329  }
3330  }
3331 
3332  return error;
3333 }
3334 
3335 /*
3336  * MISC OBJECT UTILITIES
3337  *
3338  */
3339 
3340 /*
3341  * find_unique - Internal function called by the various flavors of functions
3342  * that look for unique attribute values.
3343  * return: object pointer
3344  * classop(in):
3345  * att(in): attrubute descriptor
3346  * value(in): value to look for
3347  * fetchmode(in): access type AU_FETCH_READ
3348  * AU_FETCH_UPDATE
3349  *
3350  * Note:
3351  * This will try to find an object that has a particular value in either
3352  * a unique btree or a regular query btree.
3353  *
3354  * If the attribute is not associated with any index or other optimized
3355  * lookup structure, we will fabricate a select statement that attempts
3356  * to locate the object.
3357  *
3358  * The end result is that this function should try hard to locate the
3359  * object in the most effecient way possible, avoiding restrictive
3360  * class locks where possible.
3361  *
3362  * If NULL is returned an error will be set. The error set if the
3363  * object could not be found will be ER_OBJ_OBJECT_NOT_FOUND
3364  */
3365 static MOP
3366 find_unique (MOP classop, SM_ATTRIBUTE * att, DB_VALUE * value, AU_FETCHMODE fetchmode)
3367 {
3368  MOP found = NULL;
3369  OID unique_oid;
3370  BTID btid;
3371  DB_TYPE value_type;
3372  int r;
3373 
3374  /* make sure all dirtied objects have been flushed */
3375  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (classop) != NO_ERROR)
3376  {
3377  return NULL;
3378  }
3379 
3380  /*
3381  * Check to see if we have any sort of index we can search, if not,
3382  * then return an error indicating that the indexes do not exist rather than
3383  * the "object not found" error.
3384  */
3385 
3386  BTID_SET_NULL (&btid);
3387 
3388  /* look for a unique index on this attribute */
3390  if (r == 0)
3391  {
3392  /* look for a primary key on this attribute */
3394  if (r == 0)
3395  {
3396  /* look for a reverse unique index on this attribute */
3398  if (r == 0)
3399  {
3400  /* couldn't find one, check for a index */
3402  if (r == 0)
3403  {
3404  /* couldn't find one, check for a reverse index */
3406  if (r == 0)
3407  {
3408  /* couldn't find anything to search in */
3410  return NULL;
3411  }
3412  }
3413  }
3414  }
3415  }
3416 
3417  value_type = DB_VALUE_TYPE (value);
3418  if (value_type == DB_TYPE_NULL)
3419  {
3420  /*
3421  * We cannot search for a "null" value, though perhaps we could with some
3422  * additional effort.
3423  */
3424  goto notfound;
3425  }
3426  else if (value_type == DB_TYPE_OBJECT)
3427  {
3428  r = flush_temporary_OID (classop, value);
3429  if (r == TEMPOID_FLUSH_NOT_SUPPORT)
3430  {
3431  goto notfound;
3432  }
3433  else if (r == TEMPOID_FLUSH_FAIL)
3434  {
3435  return NULL;
3436  }
3437  }
3438 
3439  /* now search the index */
3440  if (btree_find_unique (&btid, value, ws_oid (classop), &unique_oid) == BTREE_KEY_FOUND)
3441  {
3442  found = ws_mop (&unique_oid, NULL);
3443  }
3444 
3445  /*
3446  * If we got an object, obtain an "S" lock before returning it, this
3447  * avoid problems peeking at objects that were created
3448  * by another transaction but which have not yet been committed.
3449  * We may suspend here.
3450  * Note that we're not getting an S lock on the class so we're still
3451  * not technically correct in terms of the usual index scan locking
3452  * model, but that's actually a desirable feature in this case.
3453  */
3454  if (found != NULL)
3455  {
3456  /* Using LC_FETCH_DIRTY_VERSION instead current version, is a quick fix. Thus, we need to avoid fetching current
3457  * version without any instance or shared/exclusive class lock, since btree_find_unique does not acquire locks in
3458  * all cases. */
3459  if (au_fetch_instance_force (found, NULL, fetchmode, LC_FETCH_DIRTY_VERSION) != NO_ERROR)
3460  {
3461  return NULL;
3462  }
3463  }
3464 
3465 notfound:
3466  /*
3467  * since this is a common case, set this as a warning so we don't clutter
3468  * up the error log.
3469  */
3470  if (found == NULL && er_errid () != ER_LK_UNILATERALLY_ABORTED)
3471  {
3473  }
3474 
3475  return found;
3476 }
3477 
3478 /*
3479  * flush_temporary_OID -
3480  * return: 0 : is not temporary OID or flushed
3481  * 1 : don't support
3482  * -1 : error occurs
3483  *
3484  * classop(in):
3485  * key(in): OID value to look for
3486  *
3487  * Note:
3488  * If the OID is temporary, we have something of a dilemma. It can't
3489  * possibly be in the index since it's never been flushed to the server.
3490  * That makes the index lookup useless, however, we could still have an
3491  * object in the workspace with an attribute pointing to this object.
3492  * The only reliable way to use the index is to first flush the class.
3493  * This is what a SELECT statement would do anyway so its no big deal.
3494  * If after flushing, the referenced object is still temporary, then it
3495  * can't possibly be referenced by this class.
3496  */
3497 static int
3499 {
3500  MOP mop;
3501 
3502  mop = db_get_object (key);
3503  if (mop == NULL || WS_ISVID (mop))
3504  {
3505  /* if this is a virtual object, we don't support that */
3507  }
3508  else if (OID_ISTEMP (WS_OID (mop)))
3509  {
3510  /* flush this class and see if the value remains temporary */
3511  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (classop) != NO_ERROR)
3512  {
3513  return TEMPOID_FLUSH_FAIL;
3514  }
3515  if (OID_ISTEMP (WS_OID (mop)))
3516  {
3518  }
3519  }
3520  return TEMPOID_FLUSH_OK;
3521 }
3522 
3523 /*
3524  * obj_desc_find_unique -This is used to find the object which has a particular
3525  * unique value.
3526  * return: object which has the value if any
3527  * op(in): class object
3528  * desc(in): attribute descriptor
3529  * value(in): value to look for
3530  * fetchmode(in): access type AU_FETCH_READ
3531  * AU_FETCH_UPDATE
3532  *
3533  * Note:
3534  * Calls find_unique to do the work after locating the proper
3535  * internal attribute structure
3536  *
3537  */
3538 MOP
3540 {
3541  SM_CLASS *class_;
3542  SM_ATTRIBUTE *att;
3543  MOP obj = NULL;
3544 
3545  if (op == NULL || desc == NULL || value == NULL)
3546  {
3548  }
3549  else
3550  {
3551  /* map the descriptor into an actual pair of class/attribute structures */
3552  if (sm_get_descriptor_component (op, desc, 0, &class_, (SM_COMPONENT **) (&att)) == NO_ERROR)
3553  {
3554  obj = find_unique (op, att, value, fetchmode);
3555  }
3556  }
3557 
3558  return obj;
3559 }
3560 
3561 /*
3562  * obj_find_unique - This is used to find the object which has a particular
3563  * unique value.
3564  * return: object which has the value if any
3565  * op(in): class object
3566  * attname(in): attribute name
3567  * value(in): value to look for
3568  * fetchmode(in): access type AU_FETCH_READ
3569  * AU_FETCH_UPDATE
3570  *
3571  * Note:
3572  * Calls find_unique to do the work after locating the proper internal
3573  * attribute structure.
3574  *
3575  */
3576 MOP
3577 obj_find_unique (MOP op, const char *attname, DB_VALUE * value, AU_FETCHMODE fetchmode)
3578 {
3579  SM_CLASS *class_;
3580  SM_ATTRIBUTE *att;
3581  MOP obj;
3582 
3583  obj = NULL;
3584  if (op == NULL || attname == NULL || value == NULL)
3585  {
3587  }
3588  else if (au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
3589  {
3590  att = classobj_find_attribute (class_, attname, 0);
3591  if (att == NULL)
3592  {
3594  }
3595  else
3596  {
3597  obj = find_unique (op, att, value, fetchmode);
3598  }
3599  }
3600 
3601  return obj;
3602 }
3603 
3604 /*
3605  * obj_make_key_value
3606  * return : object with the key value
3607  *
3608  * key(in):
3609  * values(in):
3610  * size(in):
3611  *
3612  */
3613 static DB_VALUE *
3614 obj_make_key_value (DB_VALUE * key, const DB_VALUE * values[], int size)
3615 {
3616  int i, nullcnt;
3617  DB_SEQ *mc_seq = NULL;
3618 
3619  if (size == 1)
3620  {
3621  if (DB_IS_NULL (values[0]))
3622  {
3624  return NULL;
3625  }
3626  *key = *values[0];
3627  }
3628  else
3629  {
3630  mc_seq = set_create_sequence (size);
3631  if (mc_seq == NULL)
3632  {
3633  return NULL;
3634  }
3635 
3636  for (i = 0, nullcnt = 0; i < size; i++)
3637  {
3638  if (values[i] == NULL || set_put_element (mc_seq, i, (DB_VALUE *) values[i]) != NO_ERROR)
3639  {
3640  set_free (mc_seq);
3641  return NULL;
3642  }
3643 
3644  if (DB_IS_NULL (values[i]))
3645  {
3646  nullcnt++;
3647  }
3648  }
3649 
3650  if (nullcnt >= size)
3651  {
3652  set_free (mc_seq);
3654  return NULL;
3655  }
3656 
3657  db_make_sequence (key, mc_seq);
3658  }
3659 
3660  return key;
3661 }
3662 
3663 /*
3664  * obj_find_multi_attr - This can be used to locate the instance whose key
3665  * has a particular unique value
3666  * return : object with the key value
3667  * op(in): class pointer
3668  * size(in): size of value array
3669  * attr_names(in): array of attribute names
3670  * values(in): array of value to look for
3671  * fetchmode(in): access type AU_FETCH_READ
3672  * AU_FETCH_UPDATE
3673  *
3674  */
3675 MOP
3676 obj_find_multi_attr (MOP op, int size, const char *attr_names[], const DB_VALUE * values[], AU_FETCHMODE fetchmode)
3677 {
3678  SM_CLASS *class_;
3679  SM_CLASS_CONSTRAINT *cons;
3680  MOP obj = NULL;
3681  DB_VALUE key;
3682  SM_ATTRIBUTE **attp;
3683  const char **namep;
3684  int i;
3685 
3686  if (op == NULL || attr_names == NULL || values == NULL || size < 1)
3687  {
3689  return NULL;
3690  }
3691 
3692  db_make_null (&key);
3693  if (obj_make_key_value (&key, values, size) == NULL)
3694  {
3695  return NULL;
3696  }
3697 
3698  if (au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
3699  {
3700  goto end_find;
3701  }
3702  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (op) != NO_ERROR)
3703  {
3704  goto end_find;
3705  }
3706 
3707  for (cons = class_->constraints; cons; cons = cons->next)
3708  {
3709  if (SM_IS_CONSTRAINT_INDEX_FAMILY (cons->type))
3710  {
3711  attp = cons->attributes;
3712  namep = attr_names;
3713  if (!attp || !namep)
3714  {
3715  continue;
3716  }
3717 
3718  i = 0;
3719  while (i < size && *attp && *namep && !SM_COMPARE_NAMES ((*attp)->header.name, *namep))
3720  {
3721  attp++;
3722  namep++;
3723  i++;
3724  }
3725  if (!*attp && i == size)
3726  {
3727  break;
3728  }
3729  }
3730  }
3731 
3732  if (cons == NULL)
3733  {
3735  goto end_find;
3736  }
3737 
3738  obj = obj_find_object_by_cons_and_key (op, cons, &key, fetchmode);
3739 
3740 end_find:
3741  if (size > 1) /* must clear a multi-column index key */
3742  pr_clear_value (&key);
3743 
3744  return obj;
3745 }
3746 
3747 /*
3748  * obj_find_multi_desc - This can be used to locate the instance whose key
3749  * has a particular unique value.
3750  *
3751  * return: object with the key value
3752  * op(in): class pointer
3753  * size(in): size of value array
3754  * desc(in): array of attribute descriptor
3755  * values(in): array of value to look for
3756  * fetchmode(in): access type AU_FETCH_READ
3757  * AU_FETCH_UPDATE
3758  *
3759  */
3760 MOP
3761 obj_find_multi_desc (MOP op, int size, const SM_DESCRIPTOR * desc[], const DB_VALUE * values[], AU_FETCHMODE fetchmode)
3762 {
3763  SM_CLASS *class_;
3764  SM_CLASS_CONSTRAINT *cons;
3765  SM_ATTRIBUTE **attp;
3766  SM_ATTRIBUTE **desc_comp = NULL;
3767  SM_ATTRIBUTE **descp = NULL;
3768  MOP obj = NULL;
3769  DB_VALUE key;
3770  int i;
3771  size_t malloc_size;
3772 
3773  if (op == NULL || desc == NULL || values == NULL || size < 1)
3774  {
3776  return NULL;
3777  }
3778 
3779  db_make_null (&key);
3780  if (obj_make_key_value (&key, values, size) == NULL)
3781  {
3782  return NULL;
3783  }
3784 
3785  if (au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
3786  {
3787  goto end_find;
3788  }
3789  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (op) != NO_ERROR)
3790  {
3791  goto end_find;
3792  }
3793 
3794  malloc_size = sizeof (SM_ATTRIBUTE *) * (size + 1);
3795  desc_comp = (SM_ATTRIBUTE **) malloc (malloc_size);
3796  if (desc_comp == NULL)
3797  {
3798  goto end_find;
3799  }
3800 
3801  for (i = 0; i < size; i++)
3802  {
3803  if (desc[i] == NULL
3804  || sm_get_descriptor_component (op, (SM_DESCRIPTOR *) desc[i], 0, &class_,
3805  (SM_COMPONENT **) (&desc_comp[i])) != NO_ERROR)
3806  {
3808  goto end_find;
3809  }
3810  }
3811  desc_comp[size] = NULL;
3812 
3813  for (cons = class_->constraints; cons; cons = cons->next)
3814  {
3815  if (SM_IS_CONSTRAINT_INDEX_FAMILY (cons->type))
3816  {
3817  attp = cons->attributes;
3818  descp = desc_comp;
3819  if (!attp || !descp)
3820  {
3821  continue;
3822  }
3823 
3824  i = 0;
3825  while (i < size && *attp && *descp && (*attp)->id == (*descp)->id)
3826  {
3827  attp++;
3828  descp++;
3829  i++;
3830  }
3831  if (!*attp && !*descp)
3832  {
3833  break;
3834  }
3835  }
3836  }
3837 
3838  if (cons == NULL)
3839  {
3841  goto end_find;
3842  }
3843 
3844  obj = obj_find_object_by_cons_and_key (op, cons, &key, fetchmode);
3845 
3846 end_find:
3847  if (desc_comp)
3848  {
3849  free_and_init (desc_comp);
3850  }
3851 
3852  if (size > 1) /* must clear a multi-column index key */
3853  {
3854  pr_clear_value (&key);
3855  }
3856 
3857  return obj;
3858 }
3859 
3860 /*
3861  * obj_find_object_by_cons_and_key - Internal function called by the various
3862  * flavors of functions that look for
3863  * unique attribute values
3864  * return: object pointer
3865  * classop(in): class pointer
3866  * cons(in): constraing
3867  * key(in): key value
3868  * fetchmode(in): access type AU_FETCH_READ
3869  * AU_FETCH_UPDATE
3870  *
3871  * Note:
3872  * This will try to find an object that has a particular value in either
3873  * a unique btree or a regular query btree.
3874  *
3875  * If the attribute is not associated with any index or other optimized
3876  * lookup structure, we will fabricate a select statement that attempts
3877  * to locate the object.
3878  *
3879  * The end result is that this function should try hard to locate the
3880  * object in the most effecient way possible, avoiding restrictive
3881  * class locks where possible.
3882  *
3883  * If NULL is returned an error will be set. The error set if the
3884  * object could not be found will be ER_OBJ_OBJECT_NOT_FOUND
3885  */
3886 static MOP
3888 {
3889  DB_TYPE value_type;
3890  int error;
3891  DB_VALUE key_element;
3892  DB_COLLECTION *keyset;
3893  SM_ATTRIBUTE **att;
3894  MOP obj;
3895  OID unique_oid;
3896  int r, i;
3897 
3898  value_type = DB_VALUE_TYPE (key);
3899  att = cons->attributes;
3900  if (att == NULL || att[0]->domain == NULL)
3901  {
3902  return NULL;
3903  }
3904 
3905  obj = NULL;
3906  error = ER_OBJ_OBJECT_NOT_FOUND;
3907  if (value_type != DB_TYPE_SEQUENCE)
3908  {
3909  /* 1 column */
3910  if (tp_domain_select (att[0]->domain, key, 1, TP_ANY_MATCH) == NULL)
3911  {
3912  error = ER_OBJ_INVALID_ARGUMENTS;
3913  goto error_return;
3914  }
3915 
3916  if (value_type == DB_TYPE_OBJECT)
3917  {
3918  r = flush_temporary_OID (classop, key);
3919  if (r == TEMPOID_FLUSH_NOT_SUPPORT)
3920  {
3921  error = ER_OBJ_INVALID_ARGUMENTS;
3922  goto error_return;
3923  }
3924  else if (r == TEMPOID_FLUSH_FAIL)
3925  {
3926  return NULL;
3927  }
3928  }
3929  }
3930  else
3931  {
3932  /* multi column */
3933  keyset = db_get_set (key);
3934  if (keyset == NULL)
3935  return NULL;
3936 
3937  for (i = 0; att[i]; i++)
3938  {
3939  if (set_get_element (keyset, i, &key_element) != NO_ERROR)
3940  {
3941  error = ER_OBJ_INVALID_ARGUMENTS;
3942  goto error_return;
3943  }
3944 
3945  value_type = DB_VALUE_TYPE (&key_element);
3946  if (tp_domain_select (att[i]->domain, &key_element, 1, TP_ANY_MATCH) == NULL)
3947  {
3948  pr_clear_value (&key_element);
3949  error = ER_OBJ_INVALID_ARGUMENTS;
3950  goto error_return;
3951  }
3952 
3953  if (value_type == DB_TYPE_OBJECT)
3954  {
3955  r = flush_temporary_OID (classop, &key_element);
3956  pr_clear_value (&key_element);
3957  if (r == TEMPOID_FLUSH_NOT_SUPPORT)
3958  {
3959  error = ER_OBJ_INVALID_ARGUMENTS;
3960  goto error_return;
3961  }
3962  else if (r == TEMPOID_FLUSH_FAIL)
3963  {
3964  return NULL;
3965  }
3966  }
3967  }
3968  }
3969 
3970  if (btree_find_unique (&cons->index_btid, key, ws_oid (classop), &unique_oid) == BTREE_KEY_FOUND)
3971  {
3972  obj = ws_mop (&unique_oid, NULL);
3973  /*
3974  * If we got an object, obtain an "S" lock before returning it, this
3975  * avoid problems peeking at objects that were created
3976  * by another transaction but which have not yet been committed.
3977  * We may suspend here.
3978  * Note that we're not getting an S lock on the class so we're still
3979  * not technically correct in terms of the usual index scan locking
3980  * model, but that's actually a desirable feature in this case.
3981  */
3982  if (obj != NULL)
3983  {
3984  /* Using LC_FETCH_DIRTY_VERSION instead current version, is a quick fix. Thus, we need to avoid fetching
3985  * current version without any instance or shared/exclusive class lock, since btree_find_unique does not
3986  * acquire locks in all cases. */
3987  if (au_fetch_instance_force (obj, NULL, fetchmode, LC_FETCH_DIRTY_VERSION) != NO_ERROR)
3988  {
3989  return NULL;
3990  }
3991  }
3992  }
3993 
3994 error_return:
3995  /*
3996  * since this is a common case, set this as a warning so we don't clutter
3997  * up the error log.
3998  */
3999  if (obj == NULL)
4000  {
4002  }
4003 
4004  return obj;
4005 }
4006 
4007 /*
4008  * obj_find_primary_key - This can be used to locate the instance whose
4009  * primary key has a particular unique value.
4010  * return: object with the primary key value
4011  * op(in): class pointer
4012  * values(in): list of value to look for
4013  * size(in): size of value list
4014  * fetchmode(in): access type AU_FETCH_READ
4015  * AU_FETCH_UPDATE
4016  *
4017  * Note:
4018  * This will only work for class that have been defined
4019  * with the PRIMARY KEY constraint
4020  */
4021 MOP
4022 obj_find_primary_key (MOP op, const DB_VALUE ** values, int size, AU_FETCHMODE fetchmode)
4023 {
4024  MOP obj = NULL;
4025  int i;
4026  DB_VALUE *key, tmp;
4027  DB_SEQ *mc_seq = NULL;
4028 
4029  if (op == NULL || values == NULL || size < 1)
4030  {
4032  return NULL;
4033  }
4034 
4035  if (size == 1)
4036  {
4037  key = (DB_VALUE *) (values[0]);
4038  }
4039  else
4040  {
4041  mc_seq = set_create_sequence (size);
4042  if (mc_seq == NULL)
4043  {
4044  goto notfound;
4045  }
4046 
4047  for (i = 0; i < size; i++)
4048  {
4049  if (set_put_element (mc_seq, i, (DB_VALUE *) (values[i])) != NO_ERROR)
4050  {
4051  goto notfound;
4052  }
4053  }
4054  db_make_sequence (&tmp, mc_seq);
4055  key = &tmp;
4056  }
4057 
4058  obj = obj_find_object_by_pkey (op, key, fetchmode);
4059 
4060 notfound:
4061  if (obj == NULL)
4062  {
4064  }
4065 
4066  if (mc_seq)
4067  {
4068  set_free (mc_seq);
4069  }
4070 
4071  return obj;
4072 }
4073 
4074 /*
4075  * obj_find_object_by_pkey - return the target object using the primary key.
4076  * return: MOP
4077  * classop(in): class pointer
4078  * key(in): key value
4079  * fetchmode(in): access type AU_FETCH_READ
4080  * AU_FETCH_UPDATE
4081  *
4082  */
4083 MOP
4085 {
4086  SM_CLASS *class_;
4087  SM_CLASS_CONSTRAINT *cons;
4088  MOP obj;
4089  OID unique_oid;
4090  DB_TYPE value_type;
4091  MOP mop;
4092  BTREE_SEARCH btree_search;
4093 
4095 
4096  obj = NULL;
4097 
4098  if (classop == NULL || key == NULL)
4099  {
4101  return NULL;
4102  }
4103 
4104  if (au_fetch_class (classop, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
4105  {
4106  return NULL;
4107  }
4108 
4109  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (classop) != NO_ERROR)
4110  {
4111  return NULL;
4112  }
4113 
4114  cons = classobj_find_class_primary_key (class_);
4115  if (cons == NULL)
4116  {
4117  goto notfound;
4118  }
4119 
4120  value_type = DB_VALUE_TYPE (key);
4121  if (value_type == DB_TYPE_NULL)
4122  {
4123  /*
4124  * We cannot search for a "null" value, though perhaps we could with some
4125  * additional effort.
4126  */
4127  goto notfound;
4128  }
4129  else if (value_type == DB_TYPE_OBJECT)
4130  {
4131  mop = db_get_object (key);
4132  if (mop == NULL || WS_ISVID (mop))
4133  {
4134  /* if this is a virtual object, we don't support that */
4135  goto notfound;
4136  }
4137  else if (OID_ISTEMP (WS_OID (mop)))
4138  {
4139  /* flush this class and see if the value remains temporary */
4140  if (!TM_TRAN_ASYNC_WS () && sm_flush_objects (classop) != NO_ERROR)
4141  {
4142  return NULL;
4143  }
4144  if (OID_ISTEMP (WS_OID (mop)))
4145  {
4146  goto notfound;
4147  }
4148  }
4149  }
4150 
4151  btree_search = btree_find_unique (&cons->index_btid, key, ws_oid (classop), &unique_oid);
4152  if (btree_search == BTREE_KEY_FOUND)
4153  {
4154  obj = ws_mop (&unique_oid, NULL);
4155  }
4156 
4157  /*
4158  * If we got an object, obtain an "S" lock before returning it, this
4159  * avoid problems peeking at objects that were created
4160  * by another transaction but which have not yet been committed.
4161  * We may suspend here.
4162  * Note that we're not getting an S lock on the class so we're still
4163  * not technically correct in terms of the usual index scan locking
4164  * model, but that's actually a desirable feature in this case.
4165  */
4166  if (obj != NULL)
4167  {
4168  /* Using LC_FETCH_DIRTY_VERSION instead current version, is a quick fix. Thus, we need to avoid fetching current
4169  * version without any instance or shared/exclusive class lock, since btree_find_unique does not acquire locks in
4170  * all cases. */
4171  if (au_fetch_instance_force (obj, NULL, fetchmode, LC_FETCH_DIRTY_VERSION) != NO_ERROR)
4172  {
4173  return NULL;
4174  }
4175  }
4176 
4177 notfound:
4178  /*
4179  * since this is a common case, set this as a warning so we don't clutter
4180  * up the error log.
4181  */
4182  if (obj == NULL)
4183  {
4185  }
4186 
4187  return obj;
4188 }
4189 
4190 #if defined(ENABLE_UNUSED_FUNCTION)
4191 /*
4192  * obj_isclass - Tests to see if an object is a class object.
4193  * return: non-zero if object is a class object
4194  * obj(in): object
4195  *
4196  */
4197 int
4198 obj_isclass (MOP obj)
4199 {
4200  int is_class = 0;
4201  int status;
4202 
4203  if (obj != NULL)
4204  {
4205  if (locator_is_class (obj, DB_FETCH_READ))
4206  {
4207  /* make sure it isn't deleted */
4208  if (!WS_IS_DELETED (obj))
4209  {
4210  status = locator_does_exist_object (obj, DB_FETCH_READ);
4211  if (status == LC_DOESNOT_EXIST)
4212  {
4213  WS_SET_DELETED (obj); /* remember this for later */
4214  }
4215  else if (status != LC_ERROR)
4216  {
4217  is_class = 1;
4218  }
4219  }
4220  }
4221  }
4222 
4223  return (is_class);
4224 }
4225 #endif /* ENABLE_UNUSED_FUNCTION */
4226 
4227 /*
4228  * obj_isinstance - Tests to see if an object is an instance object.
4229  * return: non-zero if object is an instance
4230  * obj(in): object
4231  *
4232  */
4233 
4234 int
4236 {
4237  int is_instance = 0;
4238  int status;
4239  MOBJ object;
4240 
4241  if (obj != NULL)
4242  {
4243  status = locator_is_class (obj, DB_FETCH_READ);
4244  if (status < 0)
4245  {
4246  return status;
4247  }
4248  if (!status)
4249  {
4250  if (obj->is_temp)
4251  {
4252  is_instance = 1;
4253  }
4254 
4255  /*
4256  * before declaring this an instance, we have to make sure it
4257  * isn't deleted
4258  */
4259  else if (!WS_IS_DELETED (obj))
4260  {
4261  if (WS_ISVID (obj))
4262  {
4264  NO_ERROR)
4265  {
4266  is_instance = 1;
4267  }
4268  }
4269  else
4270  {
4271  status = locator_does_exist_object (obj, DB_FETCH_READ);
4272  if (status == LC_DOESNOT_EXIST)
4273  {
4274  WS_SET_DELETED (obj); /* remember this for later */
4275  }
4276  else if (status != LC_ERROR)
4277  {
4278  is_instance = 1;
4279  }
4280  else
4281  {
4282  ASSERT_ERROR_AND_SET (is_instance);
4283  }
4284  }
4285  }
4286  }
4287  }
4288 
4289  return (is_instance);
4290 }
4291 
4292 /*
4293  * obj_is_instance_of - Tests to see if an instance belongs to
4294  * a particular class.
4295  * return: 1 if object is an instance
4296  * obj(in): instance
4297  * class(in): class
4298  *
4299  * Note:
4300  * Returns 0 if instance does not belong to class.
4301  * Returns 1 if instance belongs to class.
4302  * Returns -1 if error ocurred on instance access.
4303  */
4304 int
4305 obj_is_instance_of (MOP obj, MOP class_mop)
4306 {
4307  int status = 0;
4308  MOP object_class_mop;
4309 
4310  /*
4311  * is it possible for the obj->class field to be unset and yet still have
4312  * the class MOP in the workspace ?
4313  */
4314  object_class_mop = ws_class_mop (obj);
4315  if (object_class_mop == class_mop)
4316  {
4317  status = 1;
4318  }
4319  else
4320  {
4321  if (object_class_mop == NULL)
4322  {
4323  /* must force fetch of instance to get its class */
4325  {
4326  status = -1;
4327  }
4328  else
4329  {
4330  if (object_class_mop == class_mop)
4331  {
4332  status = 1;
4333  }
4334  }
4335  }
4336  }
4337 
4338  return (status);
4339 }
4340 
4341 /*
4342  * obj_lock - Simplified interface for obtaining the basic read/write locks
4343  * on an object.
4344  * return: error code
4345  * op(in): object to lock
4346  * for_write(in): non-zero to get a write lock
4347  * NOTE: This is a generic function can be used when a caller does not know
4348  * whether op is an instance or a class mop.
4349  */
4350 int
4351 obj_lock (MOP op, int for_write)
4352 {
4353  int is_class = 0;
4354  DB_FETCH_MODE class_purpose;
4355 
4356  if (op->is_temp)
4357  {
4358  /* if it is a temporary object, just ignore the request */
4359  return NO_ERROR;
4360  }
4361 
4362  class_purpose = ((for_write) ? DB_FETCH_CLREAD_INSTWRITE : DB_FETCH_CLREAD_INSTREAD);
4363  is_class = locator_is_class (op, class_purpose);
4364  if (is_class < 0)
4365  {
4366  return is_class;
4367  }
4368  if (is_class)
4369  {
4370  return obj_class_lock (op, for_write);
4371  }
4372  else
4373  {
4374  return obj_inst_lock (op, for_write);
4375  }
4376 }
4377 
4378 /*
4379  * obj_class_lock - Simplified interface for obtaining the basic read/write locks
4380  * on a class object.
4381  * return: error code
4382  * op(in): object to lock
4383  * for_write(in): non-zero to get a write lock
4384  * NOTE: Callers should know op is a class mop.
4385  */
4386 int
4387 obj_class_lock (MOP op, int for_write)
4388 {
4389  int error = NO_ERROR;
4390 
4391  if (op->is_temp)
4392  {
4393  /* if it is a temporary object, just ignore the request */
4394  return NO_ERROR;
4395  }
4396 
4397  if (for_write)
4398  {
4399  error = au_fetch_class (op, NULL, AU_FETCH_UPDATE, AU_ALTER);
4400  }
4401  else
4402  {
4403  error = au_fetch_class (op, NULL, AU_FETCH_READ, AU_SELECT);
4404  }
4405 
4406  return error;
4407 }
4408 
4409 /*
4410  * obj_inst_lock - Simplified interface for obtaining the basic read/write locks
4411  * on an instance object.
4412  * return: error code
4413  * op(in): object to lock
4414  * for_write(in): non-zero to get a write lock
4415  * NOTE: Callers should know op is an instance mop.
4416  */
4417 int
4418 obj_inst_lock (MOP op, int for_write)
4419 {
4420  int error = NO_ERROR;
4421 
4422  if (op->is_temp)
4423  {
4424  /* if it is a temporary object, just ignore the request */
4425  return NO_ERROR;
4426  }
4427 
4428  if (for_write)
4429  {
4431  }
4432  else
4433  {
4434  /* get dirty version, since need to lock the object */
4436  }
4437 
4438  return error;
4439 }
4440 
4441 #if defined(ENABLE_UNUSED_FUNCTION)
4442 /*
4443  * obj_find_unique_id - This function is used to identify attributes
4444  * which posses a UNIQUE constraint and to
4445  * return the associated B-tree IDs.
4446  * return: error code
4447  * op(in): class or instance
4448  * att_name(in): attribute name
4449  * id_array(in): array of BTID's where the results will be written
4450  * id_array_size(in): size of the array (needed so that we don't overrun it)
4451  * total_ids(in): total number of ids found (might be larger than
4452  * id_array_size)
4453  *
4454  */
4455 int
4456 obj_find_unique_id (MOP op, const char *att_name, BTID * id_array, int id_array_size, int *total_ids)
4457 {
4458  SM_CLASS *class_;
4459  SM_ATTRIBUTE *att;
4460  int error = NO_ERROR;
4461  SM_CONSTRAINT *ptr;
4462  int num_constraints = 0;
4463 
4464  *total_ids = 0;
4465 
4466  error = au_fetch_class (op, &class_, AU_FETCH_READ, AU_SELECT);
4467  if (error == NO_ERROR)
4468  {
4469  att = classobj_find_attribute (class_, att_name, 0);
4470  if (att == NULL)
4471  {
4472  error = ER_OBJ_INVALID_ATTRIBUTE;
4473  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, att_name);
4474  }
4475  else
4476  {
4477  for (ptr = att->constraints; ptr != NULL; ptr = ptr->next)
4478  {
4480  {
4481  if (num_constraints < id_array_size)
4482  {
4483  id_array[num_constraints] = ptr->index;
4484  }
4485  num_constraints++;
4486  }
4487  }
4488 
4489  *total_ids = num_constraints;
4490  }
4491  }
4492 
4493  return error;
4494 }
4495 #endif /* ENABLE_UNUSED_FUNCTION */
unsigned decached
Definition: work_space.h:152
static int find_attribute(SM_CLASS **classp, SM_ATTRIBUTE **attp, MOP op, const char *name, int for_write)
int obj_get_shared(MOP op, const char *name, DB_VALUE *value)
#define ER_OBJ_ARGUMENT_DOMAIN_CONFLICT
Definition: error_code.h:300
static void argstate_from_list(ARGSTATE *state, DB_VALUE_LIST *arglist)
MOP obj_find_multi_desc(MOP op, int size, const SM_DESCRIPTOR *desc[], const DB_VALUE *values[], AU_FETCHMODE fetchmode)
int char_isspace(int c)
Definition: chartype.c:109
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
SM_ATTRIBUTE * shared
Definition: class_object.h:722
DB_VALUE * old_value
TP_DOMAIN_STATUS tp_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
bool classobj_has_unique_constraint(SM_CONSTRAINT *constraints)
DB_VALUE val
Definition: dbtype_def.h:1092
#define WS_IS_DELETED(mop)
Definition: work_space.h:284
#define NO_ERROR
Definition: error_code.h:46
#define AU_DISABLE(save)
Definition: authenticate.h:106
int db_value_put_null(DB_VALUE *value)
Definition: db_macro.c:122
DB_COLLECTION * db_get_set(const DB_VALUE *value)
struct db_value_list * next
Definition: dbtype_def.h:1091
void ws_class_has_object_dependencies(MOP class_mop)
Definition: work_space.c:3166
char * obj_alloc(SM_CLASS *class_, int bound_bit_status)
void(* METHOD_FUNC_ARG5)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:170
int fixed_count
Definition: class_object.h:737
static int flush_temporary_OID(MOP classop, DB_VALUE *key)
MOP obj_copy(MOP op)
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
enum au_fetchmode AU_FETCHMODE
TP_DOMAIN * tp_domain_select(const TP_DOMAIN *domain_list, const DB_VALUE *value, int allow_coercion, TP_MATCH exact_match)
SM_COMPONENT header
Definition: class_object.h:591
int tp_value_domain_name(const DB_VALUE *value, char *buffer, int maxlen)
int obj_delete(MOP op)
char * MOBJ
Definition: work_space.h:174
#define OR_BOUND_BIT_WORDS(count)
void(* METHOD_FUNC_ARG13)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:185
#define AU_DELETE
Definition: authenticate.h:72
#define TP_IS_SET_TYPE(typenum)
#define ER_OBJ_INVALID_INDEX_IN_PATH
Definition: error_code.h:292
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
static int obj_get_temp(DB_OBJECT *obj, SM_CLASS *class_, SM_ATTRIBUTE *att, DB_VALUE *value)
int db_seq_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:712
#define LC_DOESNOT_EXIST
DB_TYPE
Definition: dbtype_def.h:670
int mq_update_attribute(DB_OBJECT *vclass_object, const char *attr_name, DB_OBJECT *real_class_object, DB_VALUE *virtual_value, DB_VALUE *real_value, const char **real_name, int db_auth)
SM_CLASS_CONSTRAINT * classobj_find_class_primary_key(SM_CLASS *class_)
TP_DOMAIN * domain
Definition: class_object.h:444
#define LC_ERROR
#define OBJ_MAX_ARGS
static int check_args(SM_METHOD *method, ARGSTATE *state)
#define OBJ_GET_BOUND_BIT(obj, element)
int obj_assign_value(MOP op, SM_ATTRIBUTE *att, char *mem, DB_VALUE *value)
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
#define ASSERT_ERROR_AND_SET(error_code)
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
MOP obj_find_unique(MOP op, const char *attname, DB_VALUE *value, AU_FETCHMODE fetchmode)
static int obj_set_att(MOP op, SM_CLASS *class_, SM_ATTRIBUTE *att, DB_VALUE *value, SM_VALIDATION *valid)
int obt_update(OBJ_TEMPLATE *template_ptr, MOP *newobj)
#define ER_OBJ_INVALID_OBJECT_IN_PATH
Definition: error_code.h:289
OBJ_TEMPASSIGN ** assignments
void(* METHOD_FUNC_ARG33)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE_LIST *)
Definition: class_object.h:264
#define OBJ_HEADER_BOUND_BITS_OFFSET
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
void(* METHOD_FUNC_ARG28)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:239
int obj_desc_set(MOP op, SM_DESCRIPTOR *desc, DB_VALUE *value)
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
MOP obj_desc_find_unique(MOP op, SM_DESCRIPTOR *desc, DB_VALUE *value, AU_FETCHMODE fetchmode)
#define SM_IS_CONSTRAINT_UNIQUE_FAMILY(c)
Definition: class_object.h:111
#define WS_ISVID(mop)
Definition: work_space.h:288
struct sm_component * next
Definition: class_object.h:384
TP_DOMAIN * domain
Definition: class_object.h:559
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
void(* METHOD_FUNC_ARG10)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:179
int obj_desc_send_list(MOP obj, SM_DESCRIPTOR *desc, DB_VALUE *returnval, DB_VALUE_LIST *arglist)
SM_ATTRIBUTE * classobj_find_attribute(SM_CLASS *class_, const char *name, int class_attribute)
void(* METHOD_FUNC_ARG26)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:230
void(* METHOD_FUNC_ARG8)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:175
struct sm_class_constraint * next
Definition: class_object.h:530
SM_NAME_SPACE name_space
Definition: class_object.h:386
int er_errid(void)
void(* METHOD_FUNC_ARG20)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:206
#define ER_OBJ_INVALID_PATH_EXPRESSION
Definition: error_code.h:290
void(* METHOD_FUNC_ARG24)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:222
enum tp_domain_status TP_DOMAIN_STATUS
int getmem(void *memptr, const tp_domain *domain, DB_VALUE *value, bool copy=true) const
struct argstate ARGSTATE
PR_TYPE * tp_Type_object
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
bool ws_is_same_object(MOP mop1, MOP mop2)
Definition: work_space.c:5065
#define AU_ALTER
Definition: authenticate.h:73
DB_VALUE * obt_check_assignment(SM_ATTRIBUTE *att, DB_VALUE *proposed_value, SM_VALIDATION *valid, unsigned force_check_not_null)
SM_VALIDATION * valid
Definition: class_object.h:901
#define ERROR0(error, code)
Definition: error_manager.h:48
void(* METHOD_FUNC_ARG21)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:210
int sm_get_descriptor_component(MOP op, SM_DESCRIPTOR *desc, int for_update, SM_CLASS **class_ptr, SM_COMPONENT **comp_ptr)
int obj_desc_send_array(MOP obj, SM_DESCRIPTOR *desc, DB_VALUE *returnval, DB_VALUE **argarray)
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
int pr_free_ext_value(DB_VALUE *value)
DB_VALUE_LIST * save_overflow
int obj_send_va(MOP obj, const char *name, DB_VALUE *returnval, va_list args)
#define AU_EXECUTE
Definition: authenticate.h:75
void(* METHOD_FUNC_ARG30)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:249
bool vid_inhibit_null_check
int setmem(void *memptr, const tp_domain *domain, const DB_VALUE *value) const
#define ER_IT_NOT_UPDATABLE_STMT
Definition: error_code.h:506
int ref_count
Definition: db_set.h:47
void(* METHOD_FUNC_ARG23)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:218
void(* METHOD_FUNC_ARG32)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:259
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
int db_set_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:508
struct tr_schema_cache * triggers
Definition: class_object.h:756
int obt_quit(OBJ_TEMPLATE *template_ptr)
MOP obj_create_by_name(const char *name)
#define assert(x)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:369
DB_VALUE_LIST * overflow
static int find_shared_attribute(SM_CLASS **classp, SM_ATTRIBUTE **attp, MOP op, const char *name, int for_write)
int db_make_set(DB_VALUE *value, DB_C_SET *set)
int db_make_multiset(DB_VALUE *value, DB_C_SET *set)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
#define ERROR1(error, code, arg1)
Definition: error_manager.h:56
int obj_lock(MOP op, int for_write)
int ws_pin(MOP mop, int pin)
Definition: work_space.c:2989
struct db_object * class_mop
Definition: work_space.h:121
void(* METHOD_FUNC_ARG4)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:169
OBJ_TEMPLATE * obt_def_object(MOP class_mop)
void obj_free_memory(SM_CLASS *class_, MOBJ obj)
void(* METHOD_FUNC_ARG16)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:194
void(* METHOD_FUNC_ARG18)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:200
int tp_domain_name(const TP_DOMAIN *domain, char *buffer, int maxlen)
static int assign_set_value(MOP op, SM_ATTRIBUTE *att, char *mem, SETREF *setref)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:725
void(* METHOD_FUNC_ARG29)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:244
BTREE_SEARCH
TEMPOID_FLUSH_RESULT
int db_is_updatable_attribute(DB_OBJECT *obj, const char *attr_name)
Definition: db_virt.c:395
int obt_assign(OBJ_TEMPLATE *template_ptr, SM_ATTRIBUTE *att, int base_assignment, DB_VALUE *value, SM_VALIDATION *valid)
#define SM_COMPARE_NAMES
Definition: class_object.h:47
void ws_pin_instance_and_class(MOP obj, int *opin, int *cpin)
Definition: work_space.c:3020
void(* METHOD_FUNC_ARG9)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:177
void ws_restore_pin(MOP obj, int opin, int cpin)
Definition: work_space.c:3052
int obj_send_array(MOP obj, const char *name, DB_VALUE *returnval, DB_VALUE **argarray)
METHOD_FUNCTION function
Definition: class_object.h:594
int obj_class_lock(MOP op, int for_write)
DB_OBJECT * db_get_object(const DB_VALUE *value)
static int forge_flag_pat
MOP ws_class_mop(MOP mop)
Definition: work_space.c:2907
int classobj_get_cached_constraint(SM_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type, BTID *id)
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
int obj_desc_send_va(MOP obj, SM_DESCRIPTOR *desc, DB_VALUE *returnval, va_list args)
#define TP_DOMAIN_TYPE(dom)
void locator_remove_instance(MOP mop)
Definition: locator_cl.c:5916
#define WS_SET_DELETED(mop)
Definition: work_space.h:286
int char_isdigit(int c)
Definition: chartype.c:73
void(* METHOD_FUNC_ARG12)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:183
#define NULL
Definition: freelistheap.h:34
void(* METHOD_FUNC_ARG14)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:188
#define ER_OBJ_METHOD_USER_ERROR
Definition: error_code.h:831
struct pr_type * type
Definition: object_domain.h:76
SM_METHOD_SIGNATURE * signatures
Definition: class_object.h:593
void initmem(void *memptr, const tp_domain *domain) const
#define ER_OBJ_OBJECT_NOT_FOUND
Definition: error_code.h:873
static void argstate_from_array(ARGSTATE *state, DB_VALUE **argarray)
#define OBJ_SET_BOUND_BIT(obj, element)
#define ER_OBJ_INDEX_NOT_FOUND
Definition: error_code.h:877
#define BTID_SET_NULL(btid)
DB_VALUE * pr_make_ext_value(void)
#define SM_IS_CONSTRAINT_INDEX_FAMILY(c)
Definition: class_object.h:117
DB_COLLECTION * set_change_owner(DB_COLLECTION *ref, MOP owner, int attid, TP_DOMAIN *domain)
Definition: set_object.c:2308
#define ERROR3(error, code, arg1, arg2, arg3)
Definition: error_manager.h:72
int au_fetch_instance_force(MOP op, MOBJ *obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE fetch_version_type)
void(* METHOD_FUNC_ARG19)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:203
#define ER_OBJ_INVALID_ATTRIBUTE
Definition: error_code.h:273
#define TM_TRAN_READ_FETCH_VERSION()
static MOP find_unique(MOP classop, SM_ATTRIBUTE *att, DB_VALUE *value, AU_FETCHMODE fetchmode)
DB_VALUE * save[OBJ_MAX_ARGS]
void(* METHOD_FUNC_ARG31)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:254
int tr_prepare_class(TR_STATE **state_p, TR_SCHEMA_CACHE *cache, MOP class_mop, DB_TRIGGER_EVENT event)
int set_connect(DB_COLLECTION *ref, MOP owner, int attid, TP_DOMAIN *domain)
Definition: set_object.c:2231
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
MOP vid_get_referenced_mop(MOP mop)
need_clear_type need_clear
Definition: dbtype_def.h:1084
int sm_flush_objects(MOP obj)
static int obj_send_method_array(MOP obj, SM_CLASS *class_, SM_METHOD *method, DB_VALUE *returnval, DB_VALUE **argarray)
int obj_desc_get(MOP op, SM_DESCRIPTOR *desc, DB_VALUE *value)
void(* METHOD_FUNC_ARG25)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:226
int pr_clear_value(DB_VALUE *value)
static int get_object_value(MOP op, SM_ATTRIBUTE *att, char *mem, DB_VALUE *source, DB_VALUE *dest)
int obj_set_shared(MOP op, const char *name, DB_VALUE *value)
#define AU_INSERT
Definition: authenticate.h:70
int sm_active_triggers(MOP class_mop, SM_CLASS *class_, DB_TRIGGER_EVENT event_type)
void(* METHOD_FUNC_ARG11)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:181
#define DB_DEFAULT_SCALE
Definition: dbtype_def.h:561
SM_CONSTRAINT * constraints
Definition: class_object.h:454
static int get_set_value(MOP op, SM_ATTRIBUTE *att, char *mem, DB_VALUE *source, DB_VALUE *dest)
void(* METHOD_FUNC_ARG7)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:173
static DB_VALUE * obj_make_key_value(DB_VALUE *key, const DB_VALUE *values[], int size)
static MOP obj_find_object_by_cons_and_key(MOP classop, SM_CLASS_CONSTRAINT *cons, DB_VALUE *key, AU_FETCHMODE fetchmode)
SM_CLASS_CONSTRAINT * constraints
Definition: class_object.h:757
char * obj_Method_error_msg
int set_put_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2719
static void error(const char *msg)
Definition: gencat.c:331
void(* METHOD_FUNC_ARG27)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:234
#define OBJ_CLEAR_BOUND_BIT(obj, element)
static int rc
Definition: serial.c:50
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
#define MAX_DOMAIN_NAME
#define AU_UPDATE
Definition: authenticate.h:71
bool vid_is_updatable(MOP mop)
int obj_send_list(MOP obj, const char *name, DB_VALUE *returnval, DB_VALUE_LIST *arglist)
int locator_does_exist_object(MOP mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:3242
#define AU_SELECT
Definition: authenticate.h:69
static int call_method(METHOD_FUNCTION method, MOP obj, DB_VALUE *returnval, int nargs, DB_VALUE **values, DB_VALUE_LIST *overow)
int obj_locate_attribute(MOP op, int attid, int for_write, char **memp, SM_ATTRIBUTE **attp)
#define ARG_FILE_LINE
Definition: error_manager.h:44
DB_VALUE * variable
MOP obj_find_primary_key(MOP op, const DB_VALUE **values, int size, AU_FETCHMODE fetchmode)
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
#define WS_OID(mop)
Definition: work_space.h:293
int obj_set(MOP op, const char *name, DB_VALUE *value)
#define AU_ENABLE(save)
Definition: authenticate.h:113
MOP obj_create(MOP classop)
void(* METHOD_FUNC_ARG15)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:191
void * object
Definition: work_space.h:123
#define free_and_init(ptr)
Definition: memory_alloc.h:147
void vid_rem_instance(MOP mop)
int obj_get_value(MOP op, SM_ATTRIBUTE *att, void *mem, DB_VALUE *source, DB_VALUE *dest)
SM_COMPONENT header
Definition: class_object.h:441
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
#define TM_TRAN_ASYNC_WS()
int obj_inst_lock(MOP op, int for_write)
int obj_get_path(DB_OBJECT *object, const char *attpath, DB_VALUE *value)
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
OBJ_TEMPLATE * obt_edit_object(MOP object)
static void argstate_from_va(ARGSTATE *state, va_list args, int nargs)
void(* METHOD_FUNC_ARG6)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:171
int obj_desc_send_array_quick(MOP obj, SM_DESCRIPTOR *desc, DB_VALUE *returnval, int nargs, DB_VALUE **argarray)
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
BTREE_SEARCH btree_find_unique(BTID *btid, DB_VALUE *key, OID *class_oid, OID *oid)
SM_CLASS_TYPE class_type
Definition: class_object.h:713
void * db_ws_alloc(size_t size)
Definition: quick_fit.c:73
SM_METHOD_ARGUMENT * args
Definition: class_object.h:577
static int obj_send_method_list(MOP obj, SM_CLASS *class_, SM_METHOD *method, DB_VALUE *returnval, DB_VALUE_LIST *arglist)
int tr_before_object(TR_STATE *state, DB_OBJECT *current, DB_OBJECT *temp)
#define ER_IT_ATTR_NOT_UPDATABLE
Definition: error_code.h:742
#define IS_CLASS_MOP(mop)
Definition: work_space.h:209
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
int obj_is_instance_of(MOP obj, MOP class_mop)
int obj_isinstance(MOP obj)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
#define ER_OBJ_TOO_MANY_ARGUMENTS
Definition: error_code.h:299
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
int obj_get_att(MOP op, SM_CLASS *class_, SM_ATTRIBUTE *att, DB_VALUE *value)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define ER_OBJ_INVALID_SET_IN_PATH
Definition: error_code.h:291
void freemem(void *memptr) const
static int obj_send_method_va(MOP obj, SM_CLASS *class_, SM_METHOD *method, DB_VALUE *returnval, va_list args)
unsigned is_temp
Definition: work_space.h:149
const char * name
Definition: class_object.h:385
int obj_get(MOP op, const char *name, DB_VALUE *value)
void(* METHOD_FUNCTION)()
Definition: class_object.h:168
int db_get_error(const DB_VALUE *value)
int au_fetch_instance(MOP op, MOBJ *obj_ptr, AU_FETCHMODE mode, LC_FETCH_VERSION_TYPE fetch_version_type, DB_AUTH type)
int set_disconnect(DB_COLLECTION *ref)
Definition: set_object.c:2268
DB_FETCH_MODE
Definition: dbtype_def.h:215
int sm_link_method(SM_CLASS *class_, SM_METHOD *method)
static int assign_null_value(MOP op, SM_ATTRIBUTE *att, char *mem)
int object_size
Definition: class_object.h:719
MOP sm_find_class(const char *name)
static void cleanup_argstate(ARGSTATE *state)
#define OBT_BASE_OBJECT(template_ptr)
int locator_is_class(MOP mop, DB_FETCH_MODE hint_purpose)
Definition: locator_cl.c:239
MOP obj_find_object_by_pkey(MOP classop, DB_VALUE *key, AU_FETCHMODE fetchmode)
int mq_get_attribute(DB_OBJECT *vclass_object, const char *attr_name, DB_OBJECT *real_class_object, DB_VALUE *virtual_value, DB_OBJECT *real_instance)
void(* METHOD_FUNC_ARG17)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:197
struct sm_constraint * next
Definition: class_object.h:366
#define WS_MOP_IS_NULL(mop)
Definition: work_space.h:328
int tr_after_object(TR_STATE *state, DB_OBJECT *current, DB_OBJECT *temp)
int obt_update_internal(OBJ_TEMPLATE *template_ptr, MOP *newobj, int check_non_null)
int ws_find(MOP mop, MOBJ *obj)
Definition: work_space.c:3112
static int obj_Method_call_level
static int obj_set_temp(DB_OBJECT *obj, SM_ATTRIBUTE *att, DB_VALUE *value)
#define ER_OBJ_INVALID_METHOD
Definition: error_code.h:279
MOP obj_find_multi_attr(MOP op, int size, const char *attr_names[], const DB_VALUE *values[], AU_FETCHMODE fetchmode)
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
#define ER_OBJ_INVALID_TEMP_OBJECT
Definition: error_code.h:302
void(* METHOD_FUNC_ARG22)(DB_OBJECT *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *, DB_VALUE *)
Definition: class_object.h:214
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
struct sm_method_argument * next
Definition: class_object.h:556
unsigned is_old_template
DB_VALUE * values[OBJ_MAX_ARGS]
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
unsigned is_vid
Definition: work_space.h:148
SM_METHOD * classobj_find_method(SM_CLASS *class_, const char *name, int class_method)