CUBRID Engine  latest
unload_schema.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  * unload_schema.c: Utility that emits database schema definitions
21  * in interpreter format
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <string.h>
32 #if !defined (WINDOWS)
33 #include <unistd.h>
34 #endif
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <assert.h>
38 
39 #include "db.h"
40 #include "extract_schema.hpp"
41 #include "authenticate.h"
42 #include "schema_manager.h"
43 #include "trigger_description.hpp"
44 #include "load_object.h"
45 #include "object_primitive.h"
46 #include "parser.h"
47 #include "printer.hpp"
48 #include "message_catalog.h"
49 #include "utility.h"
50 #include "unloaddb.h"
51 #include "execute_schema.h"
52 #include "parser.h"
53 #include "set_object.h"
54 #include "jsp_cl.h"
55 #include "class_object.h"
56 #include "object_print.h"
57 #include "dbtype.h"
58 #include "tde.h"
59 
60 #define CLASS_NAME_MAX 80
61 
62 /* suffix names */
63 #define SCHEMA_SUFFIX "_schema"
64 #define TRIGGER_SUFFIX "_trigger"
65 #define INDEX_SUFFIX "_indexes"
66 
67 #define EX_ERROR_CHECK(c,d,m) \
68  do { \
69  if (c) { \
70  if (db_error_code() != NO_ERROR) { \
71  goto error; \
72  } \
73  else { \
74  if (!d) { /* if it is not db error check only, */ \
75  if (m != NULL) { \
76  fprintf(stderr, "%s: %s.\n\n", \
77  exec_name, m); \
78  } \
79  else { \
80  fprintf(stderr, "%s: Unknown database error occurs but may not be database error.\n\n", \
81  exec_name); \
82  } \
83  goto error; \
84  } \
85  } \
86  } \
87  } while (0)
88 
89 typedef enum
90 {
95 
96 typedef enum
97 {
101 
102 typedef enum
103 {
107 
108 typedef enum
109 {
120 
123 
124 static void filter_system_classes (DB_OBJLIST ** class_list);
125 static void filter_unrequired_classes (DB_OBJLIST ** class_list);
126 static int is_dependent_class (DB_OBJECT * class_, DB_OBJLIST * unordered, DB_OBJLIST * ordered);
127 static int check_domain_dependencies (DB_DOMAIN * domain, DB_OBJECT * this_class, DB_OBJLIST * unordered,
128  DB_OBJLIST * ordered);
129 static int has_dependencies (DB_OBJECT * class_, DB_OBJLIST * unordered, DB_OBJLIST * ordered, int conservative);
130 static int order_classes (DB_OBJLIST ** class_list, DB_OBJLIST ** order_list, int conservative);
131 static void emit_cycle_warning (print_output & output_ctx);
132 static void force_one_class (print_output & output_ctx, DB_OBJLIST ** class_list, DB_OBJLIST ** order_list);
133 static DB_OBJLIST *get_ordered_classes (print_output & output_ctx, MOP * class_table);
134 static void emit_class_owner (print_output & output_ctx, MOP class_);
135 static int export_serial (print_output & output_ctx);
136 static int emit_indexes (print_output & output_ctx, DB_OBJLIST * classes, int has_indexes,
137  DB_OBJLIST * vclass_list_has_using_index);
138 
139 static int emit_schema (print_output & output_ctx, DB_OBJLIST * classes, int do_auth,
140  DB_OBJLIST ** vclass_list_has_using_index, EMIT_STORAGE_ORDER emit_storage_order);
141 static bool has_vclass_domains (DB_OBJECT * vclass);
142 static DB_OBJLIST *emit_query_specs (print_output & output_ctx, DB_OBJLIST * classes);
143 static int emit_query_specs_has_using_index (print_output & output_ctx, DB_OBJLIST * vclass_list_has_using_index);
144 static bool emit_superclasses (print_output & output_ctx, DB_OBJECT * class_, const char *class_type);
145 static bool emit_resolutions (print_output & output_ctx, DB_OBJECT * class_, const char *class_type);
146 static void emit_resolution_def (print_output & output_ctx, DB_RESOLUTION * resolution, RESOLUTION_QUALIFIER qualifier);
147 static bool emit_instance_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type,
148  int *has_indexes, EMIT_STORAGE_ORDER storage_order);
149 static bool emit_class_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type);
150 static bool emit_all_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type,
151  int *has_indexes, EMIT_STORAGE_ORDER storage_order);
152 static bool emit_class_meta (print_output & output_ctx, DB_OBJECT * table);
153 static void emit_method_files (print_output & output_ctx, DB_OBJECT * class_);
154 static bool emit_methods (print_output & output_ctx, DB_OBJECT * class_, const char *class_type);
155 static int ex_contains_object_reference (DB_VALUE * value);
156 static void emit_attribute_def (print_output & output_ctx, DB_ATTRIBUTE * attribute, ATTRIBUTE_QUALIFIER qualifier);
157 static void emit_unique_def (print_output & output_ctx, DB_OBJECT * class_, const char *class_type);
158 static void emit_reverse_unique_def (print_output & output_ctx, DB_OBJECT * class_);
159 static void emit_index_def (print_output & output_ctx, DB_OBJECT * class_);
160 static void emit_domain_def (print_output & output_ctx, DB_DOMAIN * domains);
161 static int emit_autoincrement_def (print_output & output_ctx, DB_ATTRIBUTE * attribute);
162 static void emit_method_def (print_output & output_ctx, DB_METHOD * method, METHOD_QUALIFIER qualifier);
163 static void emit_methfile_def (print_output & output_ctx, DB_METHFILE * methfile);
164 static void emit_partition_parts (print_output & output_ctx, SM_PARTITION * partition_info, int partcnt);
165 static void emit_partition_info (print_output & output_ctx, MOP clsobj);
166 static int emit_stored_procedure_args (print_output & output_ctx, int arg_cnt, DB_SET * arg_set);
167 static int emit_stored_procedure (print_output & output_ctx);
168 static int emit_foreign_key (print_output & output_ctx, DB_OBJLIST * classes);
169 static int create_filename (const char *output_dirname, const char *output_prefix, const char *suffix,
170  char *output_filename_p, const size_t filename_size);
171 /*
172  * CLASS DEPENDENCY ORDERING
173  *
174  * This section contains code to calculate an ordered list of classes
175  * based on subclass dependencies. The class definitions must be
176  * output in order so that they make sense.
177  *
178  * Algorithm for dependency checking is pretty dumb. Speed isn't particularly
179  * important however since the number of classes is normally well under 1000.
180  *
181  * Uses workspace ml_ calls for object list maintenance !
182  *
183  * THOUGHT: Now that classes are always defined empty and altered later
184  * to add attributes & super classes, I don't believe we can get into
185  * a situation where the order of definition is important? Think
186  * about this. If it is the case then we can skip the dependency ordering
187  * step.
188  *
189  */
190 
191 
192 /*
193  * filter_system_classes - Goes through a class list removing system classes.
194  * return: void
195  * class_list(in): class list to filter
196  */
197 static void
199 {
200  DB_OBJLIST *cl, *prev, *next;
201 
202  for (cl = *class_list, prev = NULL, next = NULL; cl != NULL; cl = next)
203  {
204  next = cl->next;
205  if (!db_is_system_class (cl->op))
206  {
207  prev = cl;
208  }
209  else
210  {
211  if (prev == NULL)
212  {
213  *class_list = next;
214  }
215  else
216  {
217  prev->next = next;
218  }
219  /*
220  * class_list links were allocated via ml_ext_alloc_link, so we must
221  * free them via ml_ext_free_link. Otherwise, we can crash.
222  */
223  ml_ext_free_link (cl);
224  }
225  }
226 }
227 
228 /*
229  * filter_unrequired_classes - remove unrequired class from list
230  * return: void
231  * class_list(out): class list
232  */
233 static void
235 {
236  DB_OBJLIST *cl, *prev, *next;
237 
238  for (cl = *class_list, prev = NULL, next = NULL; cl != NULL; cl = next)
239  {
240  next = cl->next;
241  if (is_req_class (cl->op))
242  {
243  prev = cl;
244  }
245  else
246  {
247  if (prev == NULL)
248  {
249  *class_list = next;
250  }
251  else
252  {
253  prev->next = next;
254  }
255  ml_ext_free_link (cl);
256  }
257  }
258 }
259 
260 
261 /*
262  * is_dependent_class - determines if a particular class results in a
263  * dependency.
264  * return: non-zero if a dependency exists
265  * class(in): class to ponder
266  * unordered(in): remaining unordered class list
267  * ordered(in): ordered class list
268  * Note:
269  * This is determined by seeint if the class is NOT already on the
270  * ordered list AND the class IS on the unordered list.
271  * If the class is not on the unordered list, then we have to
272  * assume that the user is responsible for defining it at the
273  * appropriate time. This will also handle the case
274  * where we have dependencies on system defined classes since these
275  * won't be in the original class list.
276  */
277 static int
278 is_dependent_class (DB_OBJECT * class_, DB_OBJLIST * unordered, DB_OBJLIST * ordered)
279 {
280  return (!ml_find (ordered, class_) && ml_find (unordered, class_));
281 }
282 
283 
284 /*
285  * check_domain_dependencies - checks for dependencies on the classes that are
286  * found in a domain specification.
287  * return: non-zero if there are dependencies
288  * domain(in): domain to ponder
289  * this_class(in): class to ckeck
290  * unordered(in): remaining unordered class list
291  * ordered(in): ordered class list
292  */
293 static int
294 check_domain_dependencies (DB_DOMAIN * domain, DB_OBJECT * this_class, DB_OBJLIST * unordered, DB_OBJLIST * ordered)
295 {
296  DB_DOMAIN *d, *setdomain;
297  DB_OBJECT *class_;
298  int dependencies;
299 
300  dependencies = 0;
301  for (d = domain; d != NULL && !dependencies; d = db_domain_next (d))
302  {
303  setdomain = db_domain_set (d);
304  if (setdomain != NULL)
305  {
306  dependencies = check_domain_dependencies (setdomain, this_class, unordered, ordered);
307  }
308  else
309  {
310  class_ = db_domain_class (d);
311  if (class_ != NULL && class_ != this_class)
312  {
313  dependencies = is_dependent_class (class_, unordered, ordered);
314  }
315  }
316  }
317  return (dependencies);
318 }
319 
320 /*
321  * has_dependencies - checks to see if a class has any remaining dependencnes
322  * return: non zero if there are dependencies remaining
323  * mop(in): class to ponder
324  * unordered(in): remaining unordered list
325  * ordered(in): ordered list being built
326  * conservative(in): if set detect a depencency on any class that is used
327  * as the domain of an attribute in this class.
328  */
329 static int
330 has_dependencies (DB_OBJECT * mop, DB_OBJLIST * unordered, DB_OBJLIST * ordered, int conservative)
331 {
332  DB_OBJLIST *supers, *su;
333  DB_ATTRIBUTE *att;
334  DB_DOMAIN *domain;
335  int dependencies;
336 
337  dependencies = 0;
338 
339  supers = db_get_superclasses (mop);
340  for (su = supers; su != NULL && !dependencies; su = su->next)
341  {
342  dependencies = is_dependent_class (su->op, unordered, ordered);
343  }
344 
345  /*
346  * if we're doing a conservative dependency check, look at the domains
347  * of each attribute.
348  */
349  if (!dependencies && conservative)
350  {
351  for (att = db_get_attributes (mop); att != NULL && !dependencies; att = db_attribute_next (att))
352  {
353  domain = db_attribute_domain (att);
354  dependencies = check_domain_dependencies (domain, mop, unordered, ordered);
355  }
356  }
357 
358  return (dependencies);
359 }
360 
361 
362 /*
363  * order_classes - transfers class list to ordered list if they have no
364  * dependencies
365  * return: number of classes transfered
366  * class_list(in): remaining unordered list
367  * order_list(out): order list we're building
368  * conservative(in): if set detect a depencency on any class that is used
369  * as the domain of an attribute in this class.
370  * Note:
371  * This makes a pass on the unordered class list transfering
372  * classes to the ordered list if they have no dependencies.
373  * We may make many passes over this list but there will be at least
374  * one class moved on each pass. If a pass is made and no classes
375  * can be moved, in indicates a circular depenency that cannot be
376  * handled by this algorithm. For normal classes, this would
377  * be an error condition since it indicates a cycle in the class
378  * hierarcy which isn't allowed.
379  * For proxy classes, it indicates circular references between the
380  * attributes that make up the OBJECT_ID which also isn't allowed.
381  * It can also indicate a bug in the dependency algorithm.
382  */
383 static int
384 order_classes (DB_OBJLIST ** class_list, DB_OBJLIST ** order_list, int conservative)
385 {
386  DB_OBJLIST *cl, *o, *next, *prev, *last;
387  int add_count;
388 
389  add_count = 0;
390 
391  for (cl = *class_list, prev = NULL, next = NULL; cl != NULL; cl = next)
392  {
393  next = cl->next;
394 
395  if (has_dependencies (cl->op, *class_list, *order_list, conservative))
396  {
397  prev = cl;
398  }
399  else
400  {
401  /* no dependencies, move it to the other list */
402  if (prev == NULL)
403  {
404  *class_list = next;
405  }
406  else
407  {
408  prev->next = next;
409  }
410 
411  /* append it on the order list */
412  cl->next = NULL;
413  for (o = *order_list, last = NULL; o != NULL; o = o->next)
414  {
415  last = o;
416  }
417 
418  if (last == NULL)
419  {
420  *order_list = cl;
421  }
422  else
423  {
424  last->next = cl;
425  }
426 
427  add_count++;
428  }
429  }
430 
431  return (add_count);
432 }
433 
434 
435 /*
436  * emit_cycle_warning - emit cyclic dependency warning
437  * return: void
438  * Note:
439  * Dump a warning message enclosed in a comment to the output file
440  * indicating that cycles were encountered in the schema that either
441  * represent error conditions or schema we're not prepared
442  * to handle yet.
443  */
444 static void
446 {
447  output_ctx ("/* Error calculating class dependency order.\n");
448  output_ctx (" This indicates one of the following:\n");
449  output_ctx (" - bug in dependency algorithm\n");
450  output_ctx (" - cycle in class hierarchy\n");
451  output_ctx (" - cycle in proxy attribute used as object ids\n");
452  output_ctx (" The next class may not be in the proper definition order.\n");
453  output_ctx (" Hand editing of the schema may be required before loading.\n");
454  output_ctx (" */\n");
455 }
456 
457 
458 /*
459  * force_one_class - pick the top class off the 'class_list' and append to
460  * the 'order_list'
461  * return: void
462  * class_list(out): remaining unordered classes
463  * order_list(out): ordered class list
464  * Note:
465  * This is called when a depencency cycle is detected that we can't
466  * figure out. So we at least get the full schema dumped to the
467  * output file, pick the top class off the list and hopefully this
468  * will break the cycle.
469  * The user will then have to go in and hand edit the output file
470  * so that it can be loaded.
471  */
472 static void
473 force_one_class (print_output & output_ctx, DB_OBJLIST ** class_list, DB_OBJLIST ** order_list)
474 {
475  DB_OBJLIST *cl, *o, *last;
476 
477  emit_cycle_warning (output_ctx);
478 
479  cl = *class_list;
480  *class_list = cl->next;
481 
482  cl->next = NULL;
483  for (o = *order_list, last = NULL; o != NULL; o = o->next)
484  {
485  last = o;
486  }
487 
488  if (last == NULL)
489  {
490  *order_list = cl;
491  }
492  else
493  {
494  last->next = cl;
495  }
496 }
497 
498 
499 /*
500  * get_ordered_classes - takes a list of classes to dump and returns a list
501  * of classes ordered according to their definition dependencies.
502  * return: ordered class list
503  * class_table(in): classes to dump
504  */
505 static DB_OBJLIST *
507 {
508  DB_OBJLIST *classes, *ordered;
509  int count, i;
510 
511  ordered = NULL;
512 
513  /*
514  * if class_table is passed, use it to initialize the list, otherwise
515  * get it from the API.
516  */
517  if (class_table == NULL)
518  {
519  classes = sm_fetch_all_classes (1, DB_FETCH_READ);
520  if (classes == NULL)
521  {
522  return NULL;
523  }
524 
525  filter_system_classes (&classes);
526  if (classes == NULL)
527  { /* no user class */
529  return NULL;
530  }
531 
533  {
534  filter_unrequired_classes (&classes);
535  }
536  }
537  else
538  {
539  classes = NULL;
540  for (i = 0; class_table[i] != NULL; i++)
541  {
542  if (ml_ext_add (&classes, class_table[i], NULL))
543  {
544  /* memory error */
545  ml_ext_free (classes);
546  return NULL;
547  }
548  }
549  }
550 
551  while (classes != NULL)
552  {
553 
554  count = order_classes (&classes, &ordered, 1);
555  if (count == 0)
556  {
557  /*
558  * didn't find any using the conservative ordering, try the
559  * more relaxed one.
560  */
561  count = order_classes (&classes, &ordered, 0);
562  if (count == 0)
563  {
564  force_one_class (output_ctx, &classes, &ordered);
565  }
566  }
567  }
568  return (ordered);
569 }
570 
571 
572 /*
573  * emit_class_owner - Emits a change_owner statement for a class that has been
574  * created.
575  * return: void
576  * fp(in/out): FILE pointer
577  * class(in): class MOP
578  */
579 static void
580 emit_class_owner (print_output & output_ctx, MOP class_)
581 {
582  const char *classname;
583  MOP owner;
584  DB_VALUE value;
585 
586  classname = db_get_class_name (class_);
587  if (classname != NULL)
588  {
589  owner = au_get_class_owner (class_);
590  if (owner != NULL)
591  {
592  if (db_get (owner, "name", &value) == NO_ERROR)
593  {
594  if (DB_VALUE_TYPE (&value) == DB_TYPE_STRING && db_get_string (&value) != NULL)
595  {
596  output_ctx ("call [change_owner]('%s', '%s') on class [db_root];\n", classname,
597  db_get_string (&value));
598  }
599  db_value_clear (&value);
600  }
601  }
602  }
603 }
604 
605 /*
606  * export_serial - export db_serial
607  * return: NO_ERROR if successful, error code otherwise
608  * output_ctx(in/out): output context
609  */
610 static int
612 {
613  int error = NO_ERROR;
614  int i;
615  DB_QUERY_RESULT *query_result;
616  DB_QUERY_ERROR query_error;
617  DB_VALUE values[SERIAL_VALUE_INDEX_MAX], diff_value, answer_value;
618  DB_DOMAIN *domain;
619  char str_buf[NUMERIC_MAX_STRING_SIZE];
620 
621  /*
622  * You must check SERIAL_VALUE_INDEX enum defined on the top of this file
623  * when changing the following query. Notice the order of the result.
624  */
625  const char *query =
626  "select [name], [owner].[name], " "[current_val], " "[increment_val], " "[max_val], " "[min_val], " "[cyclic], "
627  "[started], " "[cached_num], " "[comment] " "from [db_serial] where [class_name] is null and [att_name] is null";
628 
629  db_make_null (&diff_value);
630  db_make_null (&answer_value);
631 
632  error = db_compile_and_execute_local (query, &query_result, &query_error);
633  if (error < 0)
634  {
635  goto err;
636  }
637 
638  error = db_query_first_tuple (query_result);
639  if (error != DB_CURSOR_SUCCESS)
640  {
641  goto err;
642  }
643 
644  do
645  {
646  for (i = 0; i < SERIAL_VALUE_INDEX_MAX; i++)
647  {
648  error = db_query_get_tuple_value (query_result, i, &values[i]);
649  if (error != NO_ERROR)
650  {
651  goto err;
652  }
653 
654  /* Validation of the result value */
655  switch (i)
656  {
657  case SERIAL_OWNER_NAME:
658  {
659  if (DB_IS_NULL (&values[i]) || DB_VALUE_TYPE (&values[i]) != DB_TYPE_STRING)
660  {
661  db_make_string (&values[i], "PUBLIC");
662  }
663  }
664  break;
665 
666  case SERIAL_NAME:
667  {
668  if (DB_IS_NULL (&values[i]) || DB_VALUE_TYPE (&values[i]) != DB_TYPE_STRING)
669  {
671  error = ER_INVALID_SERIAL_VALUE;
672  goto err;
673  }
674  }
675  break;
676 
677  case SERIAL_CURRENT_VAL:
679  case SERIAL_MAX_VAL:
680  case SERIAL_MIN_VAL:
681  {
682  if (DB_IS_NULL (&values[i]) || DB_VALUE_TYPE (&values[i]) != DB_TYPE_NUMERIC)
683  {
685  error = ER_INVALID_SERIAL_VALUE;
686  goto err;
687  }
688  }
689  break;
690 
691  case SERIAL_CYCLIC:
692  case SERIAL_STARTED:
693  case SERIAL_CACHED_NUM:
694  {
695  if (DB_IS_NULL (&values[i]) || DB_VALUE_TYPE (&values[i]) != DB_TYPE_INTEGER)
696  {
698  error = ER_INVALID_SERIAL_VALUE;
699  goto err;
700  }
701  }
702  break;
703 
704  case SERIAL_COMMENT:
705  {
706  if (DB_IS_NULL (&values[i]) == false && DB_VALUE_TYPE (&values[i]) != DB_TYPE_STRING)
707  {
709  error = ER_INVALID_SERIAL_VALUE;
710  goto err;
711  }
712  }
713  break;
714 
715  default:
717  error = ER_INVALID_SERIAL_VALUE;
718  goto err;
719  }
720  }
721 
722  if (db_get_int (&values[SERIAL_STARTED]) == 1)
723  {
724  /* Calculate next value of serial */
725  db_make_null (&diff_value);
726  error = numeric_db_value_sub (&values[SERIAL_MAX_VAL], &values[SERIAL_CURRENT_VAL], &diff_value);
727  if (error == ER_IT_DATA_OVERFLOW)
728  {
729  // max - curr might be flooded.
730  diff_value = values[SERIAL_MAX_VAL];
731  er_clear ();
732  }
733  else if (error != NO_ERROR)
734  {
735  goto err;
736  }
737 
738  error = numeric_db_value_compare (&values[SERIAL_INCREMENT_VAL], &diff_value, &answer_value);
739  if (error != NO_ERROR)
740  {
741  goto err;
742  }
743  /* increment > diff */
744  if (db_get_int (&answer_value) > 0)
745  {
746  /* no cyclic case */
747  if (db_get_int (&values[SERIAL_CYCLIC]) == 0)
748  {
751  pr_type_name (TP_DOMAIN_TYPE (domain)));
752  error = ER_IT_DATA_OVERFLOW;
753  goto err;
754  }
755 
756  db_value_clear (&values[SERIAL_CURRENT_VAL]);
757  values[SERIAL_CURRENT_VAL] = values[SERIAL_MIN_VAL];
758  }
759  /* increment <= diff */
760  else
761  {
762  error = numeric_db_value_add (&values[SERIAL_CURRENT_VAL], &values[SERIAL_INCREMENT_VAL], &answer_value);
763  if (error != NO_ERROR)
764  {
765  goto err;
766  }
767 
768  db_value_clear (&values[SERIAL_CURRENT_VAL]);
769  values[SERIAL_CURRENT_VAL] = answer_value;
770  }
771  }
772 
773  output_ctx ("call [find_user]('%s') on class [db_user] to [auser];\n",
774  db_get_string (&values[SERIAL_OWNER_NAME]));
775  output_ctx ("create serial %s%s%s\n", PRINT_IDENTIFIER (db_get_string (&values[SERIAL_NAME])));
776  output_ctx ("\t start with %s\n", numeric_db_value_print (&values[SERIAL_CURRENT_VAL], str_buf));
777  output_ctx ("\t increment by %s\n", numeric_db_value_print (&values[SERIAL_INCREMENT_VAL], str_buf));
778  output_ctx ("\t minvalue %s\n", numeric_db_value_print (&values[SERIAL_MIN_VAL], str_buf));
779  output_ctx ("\t maxvalue %s\n", numeric_db_value_print (&values[SERIAL_MAX_VAL], str_buf));
780  output_ctx ("\t %scycle\n", (db_get_int (&values[SERIAL_CYCLIC]) == 0 ? "no" : ""));
781  if (db_get_int (&values[SERIAL_CACHED_NUM]) <= 1)
782  {
783  output_ctx ("\t nocache\n");
784 
785  }
786  else
787  {
788  output_ctx ("\t cache %d\n", db_get_int (&values[SERIAL_CACHED_NUM]));
789 
790  }
791  if (DB_IS_NULL (&values[SERIAL_COMMENT]) == false)
792  {
793  output_ctx ("\t comment ");
794  desc_value_print (output_ctx, &values[SERIAL_COMMENT]);
795  }
796  output_ctx (";\n");
797  output_ctx ("call [change_serial_owner] ('%s', '%s') on class [db_serial];\n\n",
798  db_get_string (&values[SERIAL_NAME]), db_get_string (&values[SERIAL_OWNER_NAME]));
799 
800  db_value_clear (&diff_value);
801  db_value_clear (&answer_value);
802  for (i = 0; i < SERIAL_VALUE_INDEX_MAX; i++)
803  {
804  db_value_clear (&values[i]);
805  }
806  }
807  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS);
808 
809 err:
810  db_query_end (query_result);
811  return error;
812 }
813 
814 /*
815  * extract_classes_to_file - exports schema to file
816  * return: 0 if successful, error count otherwise
817  * ctxt(in/out): extract context
818  * output_filename(in/out) : output filename
819  */
820 int
822 {
823  FILE *output_file;
824  int err_count = 0;
825 
826  output_file = fopen_ex (output_filename, "w");
827  if (output_file == NULL)
828  {
829  (void) fprintf (stderr, "%s: %s.\n\n", ctxt.exec_name, strerror (errno));
830  return 1;
831  }
832 
833  file_print_output output_ctx (output_file);
834 
835  err_count = extract_classes (ctxt, output_ctx);
836 
837  if (err_count == 0)
838  {
839  output_ctx ("\n");
840  output_ctx ("COMMIT WORK;\n");
841  }
842 
843  fclose (output_file);
844 
845  return err_count;
846 }
847 
848 /*
849  * extract_classes - exports schema to output
850  * return: 0 if successful, error count otherwise
851  * ctxt(in/out): extract context
852  * schema_output_ctx(in/out) : output countext
853  * Note:
854  * Always output the entire schema.
855  */
856 int
857 extract_classes (extract_context & ctxt, print_output & schema_output_ctx)
858 {
859  DB_OBJLIST *classes = NULL;
860  DB_OBJLIST *vclass_list_has_using_index = NULL;
861  int err_count = 0;
862 
863  /*
864  * convert the class table into an ordered class list, would be better
865  * if we just built the initial list rather than using the table.
866  */
867  ctxt.classes = get_ordered_classes (schema_output_ctx, NULL);
868  if (ctxt.classes == NULL)
869  {
870  if (db_error_code () != NO_ERROR)
871  {
872  return 1;
873  }
874  else
875  {
876  fprintf (stderr, "%s: Unknown database error occurs " "but may not be database error.\n\n", ctxt.exec_name);
877  return 1;
878  }
879  }
880 
881  /*
882  * Schema
883  */
884  if (!required_class_only && ctxt.do_auth)
885  {
886  if (au_export_users (schema_output_ctx) != NO_ERROR)
887  {
888  err_count++;
889  }
890  }
891 
892  if (!required_class_only && export_serial (schema_output_ctx) < 0)
893  {
894  fprintf (stderr, "%s", db_error_string (3));
896  {
897  fprintf (stderr, " Check the value of db_serial object.\n");
898  }
899  }
900 
901  if (emit_stored_procedure (schema_output_ctx) != NO_ERROR)
902  {
903  err_count++;
904  }
905 
906  ctxt.has_indexes = emit_schema (schema_output_ctx, ctxt.classes, ctxt.do_auth, &ctxt.vclass_list_has_using_index,
907  ctxt.storage_order);
908  if (er_errid () != NO_ERROR)
909  {
910  err_count++;
911  }
912 
913  if (emit_foreign_key (schema_output_ctx, ctxt.classes) != NO_ERROR)
914  {
915  err_count++;
916  }
917 
918  return err_count;
919 }
920 
921 /*
922  * extract_triggers_to_file - exports triggers to file
923  * return: 0 if successful, error count otherwise
924  * ctxt(in/out): extract context
925  * output_filename(in/out) : output filename
926  */
927 int
929 {
930  FILE *output_file;
931  int err_count = 0;
932 
933  output_file = fopen_ex (output_filename, "w");
934  if (output_file == NULL)
935  {
936  (void) fprintf (stderr, "%s: %s.\n\n", ctxt.exec_name, strerror (errno));
937  return 1;
938  }
939 
940  file_print_output output_ctx (output_file);
941 
942  err_count = extract_triggers (ctxt, output_ctx);
943 
944  fflush (output_file);
945 
946  if (ftell (output_file) == 0)
947  {
948  /* file is empty (database has no trigger to be emitted) */
949  fclose (output_file);
950  output_file = NULL;
951  remove (output_filename);
952  }
953  else
954  {
955  /* not empty */
956  if (err_count == 0)
957  {
958  output_ctx ("\n");
959  output_ctx ("COMMIT WORK;\n");
960  }
961  fclose (output_file);
962  output_file = NULL;
963  }
964 
965  return err_count;
966 }
967 
968 /*
969  * extract_triggers - exports triggers to output
970  * return: 0 if successful, error count otherwise
971  * ctxt(in/out): extract context
972  * schema_output_ctx(in/out) : output countext
973  * Note:
974  * Always output the entire schema.
975  */
976 int
978 {
979  /*
980  * Trigger
981  * emit the triggers last, they will have no mutual dependencies so
982  * it doesn't really matter what order they're in.
983  */
984  assert (ctxt.classes != NULL);
985  if (tr_dump_selective_triggers (output_ctx, ctxt.classes) != NO_ERROR)
986  {
987  return 1;
988  }
989 
990  return 0;
991 }
992 
993 /*
994  * extract_indexes_to_file - exports indexes to file
995  * return: 0 if successful, error count otherwise
996  * ctxt(in/out): extract context
997  * output_filename(in/out) : output filename
998  */
999 int
1001 {
1002  FILE *output_file = NULL;
1003  int err_count = 0;
1004 
1005  if (!ctxt.has_indexes)
1006  {
1007  /* remove any indexes file from previous attempt */
1008  output_file = fopen_ex (output_filename, "r");
1009  if (output_file != NULL)
1010  {
1011  fclose (output_file);
1012  output_file = NULL;
1013  if (unlink (output_filename))
1014  {
1015  (void) fprintf (stderr, "%s.\n\n", strerror (errno));
1016  return 1;
1017  }
1018  }
1019  return 0;
1020  }
1021 
1022  output_file = fopen_ex (output_filename, "w");
1023  if (output_file == NULL)
1024  {
1025  (void) fprintf (stderr, "%s: %s.\n\n", ctxt.exec_name, strerror (errno));
1026  return 1;
1027  }
1028 
1029  file_print_output output_ctx (output_file);
1030 
1031  err_count = emit_indexes (output_ctx, ctxt.classes, ctxt.has_indexes, ctxt.vclass_list_has_using_index);
1032 
1033  fflush (output_file);
1034 
1035  if (ftell (output_file) == 0)
1036  {
1037  /* file is empty (database has no indexes to be emitted) */
1038  fclose (output_file);
1039  output_file = NULL;
1040  remove (output_filename);
1041  }
1042  else
1043  { /* not empty */
1044  if (err_count == 0)
1045  {
1046  output_ctx ("\n");
1047  output_ctx ("COMMIT WORK;\n");
1048  }
1049  fclose (output_file);
1050  output_file = NULL;
1051  }
1052 
1053  return err_count;
1054 }
1055 
1056 /*
1057  * emit_indexes - Emit SQL statements to define indexes for all attributes
1058  * that have them.
1059  * return:
1060  * classes(in):
1061  * has_indexes(in):
1062  * vclass_list_has_using_index(in):
1063  */
1064 static int
1065 emit_indexes (print_output & output_ctx, DB_OBJLIST * classes, int has_indexes,
1066  DB_OBJLIST * vclass_list_has_using_index)
1067 {
1068  DB_OBJLIST *cl;
1069 
1070  for (cl = classes; cl != NULL; cl = cl->next)
1071  {
1072  /* if its some sort of vclass then it can't have indexes */
1073  if (db_is_vclass (cl->op) <= 0)
1074  {
1075  emit_index_def (output_ctx, cl->op);
1076  }
1077  }
1078 
1079  if (vclass_list_has_using_index != NULL)
1080  {
1081  emit_query_specs_has_using_index (output_ctx, vclass_list_has_using_index);
1082  }
1083 
1084  return 0;
1085 }
1086 
1087 /*
1088  * emit_schema -
1089  * return:
1090  * classes():
1091  * do_auth():
1092  * vclass_list_has_using_index():
1093  */
1094 static int
1095 emit_schema (print_output & output_ctx, DB_OBJLIST * classes, int do_auth, DB_OBJLIST ** vclass_list_has_using_index,
1096  EMIT_STORAGE_ORDER storage_order)
1097 {
1098  DB_OBJLIST *cl;
1099  int is_vclass;
1100  const char *class_type;
1101  int has_indexes = 0;
1102  const char *name;
1103  const char *tde_algo_name;
1104  int is_partitioned = 0;
1105  SM_CLASS *class_ = NULL;
1106  /*
1107  * First create all the classes
1108  */
1109  for (cl = classes; cl != NULL; cl = cl->next)
1110  {
1111  is_vclass = db_is_vclass (cl->op);
1112 
1113  name = db_get_class_name (cl->op);
1114  if (do_is_partitioned_subclass (&is_partitioned, name, NULL))
1115  {
1116  continue;
1117  }
1118 
1119  output_ctx ("CREATE %s %s%s%s", is_vclass ? "VCLASS" : "CLASS", PRINT_IDENTIFIER (name));
1120 
1121  if (au_fetch_class_force (cl->op, &class_, AU_FETCH_READ) != NO_ERROR)
1122  {
1123  class_ = NULL;
1124  }
1125 
1126  if (is_vclass > 0)
1127  {
1129  {
1130  output_ctx (" WITH CHECK OPTION");
1131  }
1133  {
1134  output_ctx (" WITH LOCAL CHECK OPTION");
1135  }
1136  }
1137  else
1138  {
1140  {
1141  output_ctx (" REUSE_OID");
1142  }
1143  else
1144  {
1145  output_ctx (" DONT_REUSE_OID");
1146  }
1147 
1148  if (class_ != NULL)
1149  {
1150  output_ctx (", COLLATE %s", lang_get_collation_name (class_->collation_id));
1151  }
1152 
1153  if (class_ != NULL)
1154  {
1155  tde_algo_name = tde_get_algorithm_name ((TDE_ALGORITHM) class_->tde_algorithm);
1156  assert (tde_algo_name != NULL);
1157  if (strcmp (tde_algo_name, tde_get_algorithm_name (TDE_ALGORITHM_NONE)) != 0)
1158  {
1159  output_ctx (" ENCRYPT=%s", tde_algo_name);
1160  }
1161  }
1162  }
1163 
1164  if (class_ != NULL && class_->comment != NULL && class_->comment[0] != '\0')
1165  {
1166  output_ctx (" ");
1167  help_print_describe_comment (output_ctx, class_->comment);
1168  }
1169 
1170  output_ctx (";\n");
1171  if (is_vclass <= 0 && storage_order == FOLLOW_STORAGE_ORDER)
1172  {
1173  emit_class_meta (output_ctx, cl->op);
1174  }
1175  output_ctx ("\n");
1176  }
1177 
1178  output_ctx ("\n");
1179 
1180  /* emit super classes without resolutions for non-proxies */
1181  for (cl = classes; cl != NULL; cl = cl->next)
1182  {
1183  is_vclass = db_is_vclass (cl->op);
1184  class_type = (is_vclass > 0) ? "VCLASS" : "CLASS";
1185  (void) emit_superclasses (output_ctx, cl->op, class_type);
1186  }
1187 
1188  output_ctx ("\n\n");
1189 
1190  /*
1191  * Now fill out the class definitions for the non-proxy classes.
1192  */
1193  for (cl = classes; cl != NULL; cl = cl->next)
1194  {
1195  bool found = false;
1196 
1197  is_vclass = db_is_vclass (cl->op);
1198  name = db_get_class_name (cl->op);
1199  if (do_is_partitioned_subclass (&is_partitioned, name, NULL))
1200  {
1201  continue;
1202  }
1203 
1204  class_type = (is_vclass > 0) ? "VCLASS" : "CLASS";
1205 
1206  if (emit_all_attributes (output_ctx, cl->op, class_type, &has_indexes, storage_order))
1207  {
1208  found = true;
1209  }
1210 
1211  if (emit_methods (output_ctx, cl->op, class_type))
1212  {
1213  found = true;
1214  }
1215 
1216  if (found)
1217  {
1218  (void) output_ctx ("\n");
1219  }
1220  if (is_partitioned)
1221  {
1222  emit_partition_info (output_ctx, cl->op);
1223  }
1224 
1225  /*
1226  * change_owner method should be called after adding all columns.
1227  * If some column has auto_increment attribute, change_owner method
1228  * will change serial object's owner related to that attribute.
1229  */
1230  if (do_auth)
1231  {
1232  emit_class_owner (output_ctx, cl->op);
1233  }
1234  }
1235 
1236  output_ctx ("\n");
1237 
1238  /* emit super class resolutions for non-proxies */
1239  for (cl = classes; cl != NULL; cl = cl->next)
1240  {
1241  is_vclass = db_is_vclass (cl->op);
1242  class_type = (is_vclass > 0) ? "VCLASS" : "CLASS";
1243  (void) emit_resolutions (output_ctx, cl->op, class_type);
1244  }
1245 
1246  /*
1247  * do query specs LAST after we're sure that all potentially
1248  * referenced classes have their full definitions.
1249  */
1250  *vclass_list_has_using_index = emit_query_specs (output_ctx, classes);
1251 
1252  /*
1253  * Dump authorizations.
1254  */
1255  if (do_auth)
1256  {
1257  output_ctx ("\n");
1258  for (cl = classes; cl != NULL; cl = cl->next)
1259  {
1260  name = db_get_class_name (cl->op);
1261  if (do_is_partitioned_subclass (&is_partitioned, name, NULL))
1262  {
1263  continue;
1264  }
1265  au_export_grants (output_ctx, cl->op);
1266  }
1267  }
1268 
1269  return has_indexes;
1270 
1271 }
1272 
1273 
1274 /*
1275  * has_vclass_domains -
1276  * return: non-zero if the class has vclasses as attribute domains
1277  * vclass(in): class MOP
1278  * Note:
1279  * This is a helper function for emit_query_specs().
1280  * Look through the attribute list of this class to see if there are
1281  * any attributes defined with domsins that are other vclasses. If so
1282  * we have to adjust the way we emit the query spec lists for
1283  * this class.
1284  */
1285 static bool
1287 {
1288  /*
1289  * this doesn't seem to be enough, always return 1 so we make two full passes
1290  * on the query specs of all vclasses
1291  */
1292  return 1;
1293 }
1294 
1295 
1296 /*
1297  * emit_query_specs - Emit the object ids for a virtual class.
1298  * return:
1299  * classes(in):
1300  */
1301 static DB_OBJLIST *
1302 emit_query_specs (print_output & output_ctx, DB_OBJLIST * classes)
1303 {
1304  DB_QUERY_SPEC *specs, *s;
1305  DB_OBJLIST *cl;
1306  DB_OBJLIST *vclass_list_has_using_index = NULL;
1308  PT_NODE **query_ptr;
1309  const char *name;
1310  const char *null_spec;
1311  bool has_using_index;
1312  bool change_vclass_spec;
1313  int i;
1314 
1315  /*
1316  * pass 1, emit NULL spec lists for vclasses that have attribute
1317  * domains which are other vclasses
1318  */
1319  for (cl = classes; cl != NULL; cl = cl->next)
1320  {
1321  if (db_is_vclass (cl->op) <= 0)
1322  {
1323  continue;
1324  }
1325 
1326  name = db_get_class_name (cl->op);
1327  specs = db_get_query_specs (cl->op);
1328  if (specs == NULL)
1329  {
1330  continue;
1331  }
1332 
1333  if (!has_vclass_domains (cl->op))
1334  {
1335  continue;
1336  }
1337 
1338  has_using_index = false;
1339  for (s = specs; s && has_using_index == false; s = db_query_spec_next (s))
1340  {
1341  /*
1342  * convert the query spec into one containing NULLs for
1343  * each column
1344  */
1345  parser = parser_create_parser ();
1346  if (parser == NULL)
1347  {
1348  continue;
1349  }
1350 
1351  query_ptr = parser_parse_string (parser, db_query_spec_string (s));
1352  if (query_ptr != NULL)
1353  {
1354  parser_walk_tree (parser, *query_ptr, pt_has_using_index_clause, &has_using_index, NULL, NULL);
1355 
1356  if (has_using_index == true)
1357  {
1358  /* all view specs should be emitted at index file */
1359  ml_append (&vclass_list_has_using_index, cl->op, NULL);
1360  }
1361  }
1362  parser_free_parser (parser);
1363  }
1364 
1365  if (has_using_index == false)
1366  {
1367  for (s = specs; s; s = db_query_spec_next (s))
1368  {
1369  parser = parser_create_parser ();
1370  if (parser == NULL)
1371  {
1372  continue;
1373  }
1374 
1375  query_ptr = parser_parse_string (parser, db_query_spec_string (s));
1376  if (query_ptr != NULL)
1377  {
1378  null_spec = pt_print_query_spec_no_list (parser, *query_ptr);
1379 
1380  output_ctx ("ALTER VCLASS %s%s%s ADD QUERY %s ; \n", PRINT_IDENTIFIER (name), null_spec);
1381  }
1382  parser_free_parser (parser);
1383  }
1384  }
1385  }
1386 
1387  /*
1388  * pass 2, emit full spec lists
1389  */
1390  for (cl = classes; cl != NULL; cl = cl->next)
1391  {
1392  if (db_is_vclass (cl->op) <= 0)
1393  {
1394  continue;
1395  }
1396 
1397  name = db_get_class_name (cl->op);
1398  specs = db_get_query_specs (cl->op);
1399  if (specs == NULL)
1400  {
1401  continue;
1402  }
1403 
1404  if (ml_find (vclass_list_has_using_index, cl->op))
1405  {
1406  continue;
1407  }
1408 
1409  change_vclass_spec = has_vclass_domains (cl->op);
1410 
1411  for (s = specs, i = 1; s != NULL; s = db_query_spec_next (s), i++)
1412  {
1413  if (change_vclass_spec)
1414  { /* change the existing spec lists */
1415  output_ctx ("ALTER VCLASS %s%s%s CHANGE QUERY %d %s ;\n", PRINT_IDENTIFIER (name), i,
1416  db_query_spec_string (s));
1417  }
1418  else
1419  { /* emit the usual statements */
1420  output_ctx ("ALTER VCLASS %s%s%s ADD QUERY %s ;\n", PRINT_IDENTIFIER (name), db_query_spec_string (s));
1421  }
1422  }
1423  }
1424 
1425  return vclass_list_has_using_index;
1426 }
1427 
1428 
1429 /*
1430  * emit_query_specs_has_using_index - Emit the object ids for a virtual class
1431  * return:
1432  * vclass_list_has_using_index():
1433  */
1434 static int
1435 emit_query_specs_has_using_index (print_output & output_ctx, DB_OBJLIST * vclass_list_has_using_index)
1436 {
1437  DB_QUERY_SPEC *specs, *s;
1438  DB_OBJLIST *cl;
1440  PT_NODE **query_ptr;
1441  const char *name;
1442  const char *null_spec;
1443  bool change_vclass_spec;
1444  int i;
1445 
1446  output_ctx ("\n\n");
1447 
1448  /*
1449  * pass 1, emit NULL spec lists for vclasses that have attribute
1450  * domains which are other vclasses
1451  */
1452 
1453  for (cl = vclass_list_has_using_index; cl != NULL; cl = cl->next)
1454  {
1455  if (db_is_vclass (cl->op) <= 0)
1456  {
1457  continue;
1458  }
1459 
1460  name = db_get_class_name (cl->op);
1461  specs = db_get_query_specs (cl->op);
1462  if (specs == NULL)
1463  {
1464  continue;
1465  }
1466 
1467  if (!has_vclass_domains (cl->op))
1468  {
1469  continue;
1470  }
1471 
1472  for (s = specs; s != NULL; s = db_query_spec_next (s))
1473  {
1474  /*
1475  * convert the query spec into one containing NULLs for
1476  * each column
1477  */
1478  parser = parser_create_parser ();
1479  if (parser == NULL)
1480  {
1481  continue;
1482  }
1483  query_ptr = parser_parse_string (parser, db_query_spec_string (s));
1484  if (query_ptr != NULL)
1485  {
1486  null_spec = pt_print_query_spec_no_list (parser, *query_ptr);
1487  output_ctx ("ALTER VCLASS %s%s%s ADD QUERY %s ; \n", PRINT_IDENTIFIER (name), null_spec);
1488  }
1489  parser_free_parser (parser);
1490  }
1491  }
1492 
1493  /* pass 2, emit full spec lists */
1494  for (cl = vclass_list_has_using_index; cl != NULL; cl = cl->next)
1495  {
1496  if (db_is_vclass (cl->op) <= 0)
1497  {
1498  continue;
1499  }
1500  name = db_get_class_name (cl->op);
1501  specs = db_get_query_specs (cl->op);
1502  if (specs == NULL)
1503  {
1504  continue;
1505  }
1506 
1507  change_vclass_spec = has_vclass_domains (cl->op);
1508 
1509  for (s = specs, i = 1; s; s = db_query_spec_next (s), i++)
1510  {
1511  if (change_vclass_spec)
1512  { /* change the existing spec lists */
1513  output_ctx ("ALTER VCLASS %s%s%s CHANGE QUERY %d %s ;\n", PRINT_IDENTIFIER (name), i,
1514  db_query_spec_string (s));
1515  }
1516  else
1517  { /* emit the usual statements */
1518  output_ctx ("ALTER VCLASS %s%s%s ADD QUERY %s ;\n", PRINT_IDENTIFIER (name), db_query_spec_string (s));
1519  }
1520  }
1521  }
1522 
1523  return NO_ERROR;
1524 }
1525 
1526 
1527 /*
1528  * emit_superclasses - emit queries for adding superclass for the class given
1529  * return: true if there are any superclasses or conflict resolutions
1530  * output_ctx(in/out): output context
1531  * class(in): the class to emit the superclasses for
1532  * class_type(in): CLASS or VCLASS
1533  */
1534 static bool
1535 emit_superclasses (print_output & output_ctx, DB_OBJECT * class_, const char *class_type)
1536 {
1537  DB_OBJLIST *supers, *s;
1538  const char *name;
1539 
1540  supers = db_get_superclasses (class_);
1541  if (supers != NULL)
1542  {
1543  /* create class alter string */
1544  name = db_get_class_name (class_);
1545  if (do_is_partitioned_subclass (NULL, name, NULL))
1546  {
1547  return (supers != NULL);
1548  }
1549 
1550  output_ctx ("ALTER %s %s%s%s ADD SUPERCLASS ", class_type, PRINT_IDENTIFIER (name));
1551 
1552  for (s = supers; s != NULL; s = s->next)
1553  {
1554  name = db_get_class_name (s->op);
1555  if (s != supers)
1556  {
1557  output_ctx (", ");
1558  }
1559  output_ctx ("%s%s%s", PRINT_IDENTIFIER (name));
1560  }
1561 
1562  output_ctx (";\n");
1563 
1564  }
1565 
1566  return (supers != NULL);
1567 }
1568 
1569 
1570 /*
1571  * emit_resolutions - emit queries for the resolutions (instance, shared and
1572  * class) for the class given
1573  * return: true if any resolutions are emitted, false otherwise
1574  * class(in): the class to emit resolutions for
1575  * class_type(in): CLASS or VCLASS
1576  * Note:
1577  * Calls emit_resolution_def for each resolution. This function will
1578  * only emit those resolutions defined in this class and NOT any of the
1579  * inherited resolutions.
1580  */
1581 static bool
1582 emit_resolutions (print_output & output_ctx, DB_OBJECT * class_, const char *class_type)
1583 {
1584  DB_RESOLUTION *resolution_list;
1585  bool return_value = false;
1586  const char *name;
1587 
1588  resolution_list = db_get_resolutions (class_);
1589  if (resolution_list != NULL)
1590  {
1591  name = db_get_class_name (class_);
1592  output_ctx ("ALTER %s %s%s%s INHERIT", class_type, PRINT_IDENTIFIER (name));
1593 
1594  for (; resolution_list != NULL; resolution_list = db_resolution_next (resolution_list))
1595  {
1596  if (return_value == true)
1597  {
1598  output_ctx (",\n");
1599  }
1600  else
1601  {
1602  output_ctx ("\n");
1603  return_value = true;
1604  }
1605  emit_resolution_def (output_ctx, resolution_list,
1607  }
1608 
1609  output_ctx (";\n");
1610  } /* if */
1611 
1612  return (return_value);
1613 }
1614 
1615 
1616 /*
1617  * emit_resolution_def - emit the resolution qualifier
1618  * return: void
1619  * resolution(in): the resolution
1620  * qualifier(in): the qualifier for this resolution (instance or class)
1621  */
1622 static void
1624 {
1625  const char *name, *alias, *class_name;
1626  DB_OBJECT *class_;
1627 
1628  class_ = db_resolution_class (resolution);
1629  if (class_ == NULL)
1630  {
1631  return;
1632  }
1633 
1634  name = db_resolution_name (resolution);
1635  if (name == NULL)
1636  {
1637  return;
1638  }
1639 
1640  class_name = db_get_class_name (class_);
1641  if (class_name == NULL)
1642  {
1643  return;
1644  }
1645 
1646  alias = db_resolution_alias (resolution);
1647 
1648  switch (qualifier)
1649  {
1650  case INSTANCE_RESOLUTION:
1651  {
1652  output_ctx (" %s%s%s OF %s%s%s", PRINT_IDENTIFIER (name), PRINT_IDENTIFIER (class_name));
1653  break;
1654  }
1655  case CLASS_RESOLUTION:
1656  {
1657  output_ctx ("CLASS %s%s%s OF %s%s%s", PRINT_IDENTIFIER (name), PRINT_IDENTIFIER (class_name));
1658  break;
1659  }
1660  }
1661 
1662  if (alias != NULL)
1663  {
1664  output_ctx (" AS %s%s%s", PRINT_IDENTIFIER (alias));
1665  }
1666 
1667  class_ = NULL;
1668 }
1669 
1670 
1671 /*
1672  * emit_instance_attributes - emit quries for adding the attributes (instance,
1673  * shared and class) for the class given
1674  * return: true if any locally defined attributes are found, false
1675  * otherwise
1676  * output_ctx(in/out): output context
1677  * class(in): the class to emit the attributes for
1678  * class_type(in):
1679  * has_indexes(in):
1680  * Note:
1681  * Calls emit_attribute_def for each attribute. This function will only
1682  * emit those attributes defined in this class and NOT any of the
1683  * inherited attributes.
1684  *
1685  * If its a proxy, only dump those attributes whose domains
1686  * are other classes, the attributes with primitive type domains will
1687  * have been dumped in the main class definition.
1688  */
1689 static bool
1690 emit_instance_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type, int *has_indexes,
1691  EMIT_STORAGE_ORDER storage_order)
1692 {
1693  DB_ATTRIBUTE *attribute_list, *first_attribute, *a;
1694  int unique_flag = 0;
1695  int reverse_unique_flag = 0;
1696  int index_flag = 0;
1697  DB_VALUE cur_val, started_val, min_val, max_val, inc_val, sr_name;
1698  const char *name, *start_with;
1699  char str_buf[NUMERIC_MAX_STRING_SIZE];
1700 
1701  attribute_list = db_get_attributes (class_);
1702 
1703  /* see if we have an index or unique defined on any attribute */
1704  for (a = attribute_list; a != NULL; a = db_attribute_next (a))
1705  {
1706  if (db_attribute_class (a) == class_)
1707  {
1708  if (db_attribute_is_unique (a))
1709  {
1710  unique_flag = 1;
1711  }
1712  else if (db_attribute_is_reverse_unique (a))
1713  {
1714  reverse_unique_flag = 1;
1715  }
1716  }
1717 
1718  if (db_attribute_is_indexed (a))
1719  {
1720  index_flag = 1;
1721  }
1722 
1723  if (unique_flag && reverse_unique_flag && index_flag)
1724  {
1725  /* Since we already found all, no need to go further. */
1726  break;
1727  }
1728  }
1729 
1730  /*
1731  * We call this function many times, so be careful not to clobber
1732  * (i.e. overwrite) the has_index parameter
1733  */
1734  if (has_indexes != NULL)
1735  {
1736  *has_indexes |= index_flag;
1737  }
1738 
1739 
1740  /* see if we have any locally defined components on either list */
1741  first_attribute = NULL;
1742  for (a = attribute_list; a != NULL && first_attribute == NULL; a = db_attribute_next (a))
1743  {
1744  if (db_attribute_class (a) == class_)
1745  {
1746  first_attribute = a;
1747  }
1748  }
1749 
1750  if (first_attribute == NULL)
1751  {
1752  return false;
1753  }
1754 
1755  name = db_get_class_name (class_);
1756  if (storage_order == FOLLOW_STORAGE_ORDER)
1757  {
1758  DB_ATTRIBUTE **ordered_attributes, **storage_attributes;
1759  int i, j, max_order, shared_pos;
1760  const char *option, *old_attribute_name;
1761 
1762  max_order = 0;
1763  for (a = first_attribute; a != NULL; a = db_attribute_next (a))
1764  {
1765  if (db_attribute_class (a) != class_)
1766  {
1767  continue;
1768  }
1769 
1770  if (a->order > max_order)
1771  {
1772  max_order = a->order;
1773  }
1774  }
1775  max_order++;
1776 
1777  ordered_attributes = (DB_ATTRIBUTE **) calloc (max_order * 2, sizeof (DB_ATTRIBUTE *));
1778  if (ordered_attributes == NULL)
1779  {
1780  return false;
1781  }
1782  storage_attributes = &ordered_attributes[max_order];
1783 
1784  shared_pos = 1;
1785  for (a = first_attribute; a != NULL; a = db_attribute_next (a))
1786  {
1787  if (db_attribute_class (a) != class_)
1788  {
1789  continue;
1790  }
1791 
1792  if (db_attribute_is_shared (a))
1793  {
1794  storage_attributes[max_order - shared_pos] = a;
1795  shared_pos++;
1796  }
1797  else
1798  {
1799  assert (storage_attributes[a->storage_order] == NULL);
1800  storage_attributes[a->storage_order] = a;
1801  }
1802  }
1803 
1804  for (i = 0; i < max_order; i++)
1805  {
1806  a = storage_attributes[i];
1807  if (a == NULL)
1808  {
1809  continue;
1810  }
1811 
1812  assert (ordered_attributes[a->order] == NULL);
1813  ordered_attributes[a->order] = a;
1814 
1815  for (j = a->order - 1; j >= 0; j--)
1816  {
1817  if (ordered_attributes[j])
1818  {
1819  option = "AFTER ";
1820  old_attribute_name = db_attribute_name (ordered_attributes[j]);
1821  break;
1822  }
1823  }
1824 
1825  if (j < 0)
1826  {
1827  option = "FIRST";
1828  old_attribute_name = "";
1829  }
1830 
1831  output_ctx ("ALTER %s %s%s%s ADD ATTRIBUTE ", class_type, PRINT_IDENTIFIER (name));
1832  if (db_attribute_is_shared (a))
1833  {
1834  emit_attribute_def (output_ctx, a, SHARED_ATTRIBUTE);
1835  }
1836  else
1837  {
1838  emit_attribute_def (output_ctx, a, INSTANCE_ATTRIBUTE);
1839  }
1840  output_ctx (" %s", option);
1841  if (old_attribute_name[0] == '\0')
1842  {
1843  output_ctx (";\n");
1844  }
1845  else
1846  {
1847  output_ctx (" %s%s%s;\n", PRINT_IDENTIFIER (old_attribute_name));
1848  }
1849  }
1850 
1851  free (ordered_attributes);
1852  }
1853  else
1854  {
1855  output_ctx ("ALTER %s %s%s%s ADD ATTRIBUTE\n", class_type, PRINT_IDENTIFIER (name));
1856  for (a = first_attribute; a != NULL; a = db_attribute_next (a))
1857  {
1858  if (db_attribute_class (a) == class_)
1859  {
1860  if (a != first_attribute)
1861  {
1862  output_ctx (",\n");
1863  }
1864 
1865  if (db_attribute_is_shared (a))
1866  {
1867  emit_attribute_def (output_ctx, a, SHARED_ATTRIBUTE);
1868  }
1869  else
1870  {
1871  emit_attribute_def (output_ctx, a, INSTANCE_ATTRIBUTE);
1872  }
1873  }
1874  }
1875 
1876  output_ctx (";\n");
1877  }
1878 
1879  for (a = first_attribute; a != NULL; a = db_attribute_next (a))
1880  {
1881  if (db_attribute_class (a) == class_)
1882  {
1883  /* update attribute's auto increment serial object */
1884  if (a->auto_increment != NULL)
1885  {
1886  int sr_error = NO_ERROR;
1887 
1888  db_make_null (&sr_name);
1889  db_make_null (&cur_val);
1890  db_make_null (&started_val);
1891  db_make_null (&min_val);
1892  db_make_null (&max_val);
1893  db_make_null (&inc_val);
1894 
1895  sr_error = db_get (a->auto_increment, "name", &sr_name);
1896  if (sr_error < 0)
1897  {
1898  continue;
1899  }
1900 
1901  sr_error = db_get (a->auto_increment, "current_val", &cur_val);
1902  if (sr_error < 0)
1903  {
1904  pr_clear_value (&sr_name);
1905  continue;
1906  }
1907 
1908  sr_error = db_get (a->auto_increment, "increment_val", &inc_val);
1909  if (sr_error < 0)
1910  {
1911  pr_clear_value (&sr_name);
1912  continue;
1913  }
1914 
1915  sr_error = db_get (a->auto_increment, "min_val", &min_val);
1916  if (sr_error < 0)
1917  {
1918  pr_clear_value (&sr_name);
1919  continue;
1920  }
1921 
1922  sr_error = db_get (a->auto_increment, "max_val", &max_val);
1923  if (sr_error < 0)
1924  {
1925  pr_clear_value (&sr_name);
1926  continue;
1927  }
1928 
1929  sr_error = db_get (a->auto_increment, "started", &started_val);
1930  if (sr_error < 0)
1931  {
1932  pr_clear_value (&sr_name);
1933  continue;
1934  }
1935 
1936  if (db_get_int (&started_val) == 1)
1937  {
1938  DB_VALUE diff_val, answer_val;
1939 
1940  db_make_null (&diff_val);
1941  sr_error = numeric_db_value_sub (&max_val, &cur_val, &diff_val);
1942  if (sr_error == ER_IT_DATA_OVERFLOW)
1943  {
1944  // max - cur might be flooded.
1945  diff_val = max_val;
1946  er_clear ();
1947  }
1948  else if (sr_error != NO_ERROR)
1949  {
1950  pr_clear_value (&sr_name);
1951  continue;
1952  }
1953  sr_error = numeric_db_value_compare (&inc_val, &diff_val, &answer_val);
1954  if (sr_error != NO_ERROR)
1955  {
1956  pr_clear_value (&sr_name);
1957  continue;
1958  }
1959  /* auto_increment is always non-cyclic */
1960  if (db_get_int (&answer_val) > 0)
1961  {
1962  pr_clear_value (&sr_name);
1963  continue;
1964  }
1965 
1966  sr_error = numeric_db_value_add (&cur_val, &inc_val, &answer_val);
1967  if (sr_error != NO_ERROR)
1968  {
1969  pr_clear_value (&sr_name);
1970  continue;
1971  }
1972 
1973  pr_clear_value (&cur_val);
1974  cur_val = answer_val;
1975  }
1976 
1977  start_with = numeric_db_value_print (&cur_val, str_buf);
1978  if (start_with[0] == '\0')
1979  {
1980  start_with = "NULL";
1981  }
1982 
1983  output_ctx ("ALTER SERIAL %s%s%s START WITH %s;\n",
1984  PRINT_IDENTIFIER (db_get_string (&sr_name)), start_with);
1985 
1986  pr_clear_value (&sr_name);
1987  }
1988  }
1989  }
1990 
1991  output_ctx ("\n");
1992  if (unique_flag)
1993  {
1994  emit_unique_def (output_ctx, class_, class_type);
1995  }
1996 
1997  if (reverse_unique_flag)
1998  {
1999  emit_reverse_unique_def (output_ctx, class_);
2000  }
2001 
2002  return true;
2003 }
2004 
2005 
2006 /*
2007  * emit_class_attributes - emit ALTER statements for the class attributes
2008  * return: non-zero if something was emitted
2009  * output_ctx(in/out): output context
2010  * class(in): class
2011  * class_type(in): class type
2012  */
2013 static bool
2014 emit_class_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type)
2015 {
2016  DB_ATTRIBUTE *class_attribute_list, *first_class_attribute, *a;
2017  const char *name;
2018 
2019  class_attribute_list = db_get_class_attributes (class_);
2020  first_class_attribute = NULL;
2021 
2022  for (a = class_attribute_list; a != NULL && first_class_attribute == NULL; a = db_attribute_next (a))
2023  {
2024  if (db_attribute_class (a) == class_)
2025  {
2026  first_class_attribute = a;
2027  }
2028  }
2029 
2030  if (first_class_attribute != NULL)
2031  {
2032  name = db_get_class_name (class_);
2033  output_ctx ("ALTER %s %s%s%s ADD CLASS ATTRIBUTE \n", class_type, PRINT_IDENTIFIER (name));
2034 
2035  for (a = first_class_attribute; a != NULL; a = db_attribute_next (a))
2036  {
2037  if (db_attribute_class (a) == class_)
2038  {
2039  if (a != first_class_attribute)
2040  {
2041  output_ctx (",\n");
2042  }
2043  emit_attribute_def (output_ctx, a, CLASS_ATTRIBUTE);
2044  }
2045  }
2046  output_ctx (";\n");
2047  }
2048 
2049  return (first_class_attribute != NULL);
2050 }
2051 
2052 static bool
2053 emit_class_meta (print_output & output_ctx, DB_OBJECT * table)
2054 {
2055  DB_ATTRIBUTE *attribute_list, *a;
2056  const char *table_name;
2057  bool first_print = true;
2058 
2059  table_name = db_get_class_name (table);
2060  output_ctx ("-- !META! %s%s%s:", PRINT_IDENTIFIER (table_name));
2061 
2062  attribute_list = db_get_attributes (table);
2063  for (a = attribute_list; a != NULL; a = db_attribute_next (a))
2064  {
2065  if (db_attribute_class (a) != table)
2066  {
2067  continue;
2068  }
2069  if (!first_print)
2070  {
2071  output_ctx (",");
2072  }
2073  output_ctx ("%s%s%s", PRINT_IDENTIFIER (db_attribute_name (a)));
2074  output_ctx ("(%d)", db_attribute_type (a));
2075  output_ctx ("(%d)", db_attribute_order (a));
2076  output_ctx ("(%d)", a->storage_order);
2077  output_ctx ("(%c)", db_attribute_is_shared (a) ? 'S' : 'I');
2078  first_print = false;
2079  }
2080 
2081  output_ctx ("\n");
2082 
2083  return true;
2084 }
2085 
2086 /*
2087  * emit_all_attributes - Emit both the instance and class attributes.
2088  * return: non-zero if something was emmitted
2089  * output_ctx(in/out): output context
2090  * class(in): class to dump
2091  * class_type(in): class type string
2092  * has_indexes(in):
2093  */
2094 static bool
2095 emit_all_attributes (print_output & output_ctx, DB_OBJECT * class_, const char *class_type, int *has_indexes,
2096  EMIT_STORAGE_ORDER storage_order)
2097 {
2098  bool istatus, cstatus;
2099 
2100  istatus = emit_instance_attributes (output_ctx, class_, class_type, has_indexes, storage_order);
2101  cstatus = emit_class_attributes (output_ctx, class_, class_type);
2102 
2103  return istatus || cstatus;
2104 }
2105 
2106 
2107 /*
2108  * emit_method_files - emit all methods files
2109  * return: void
2110  * class(in): class object
2111  */
2112 static void
2113 emit_method_files (print_output & output_ctx, DB_OBJECT * class_mop)
2114 {
2115  DB_METHFILE *files, *f;
2116  bool printed_once = false;
2117 
2118  /* should clean this list ! */
2119  files = db_get_method_files (class_mop);
2120 
2121  if (files != NULL)
2122  {
2123  for (f = files; f != NULL; f = db_methfile_next (f))
2124  {
2125  if (f->class_mop == class_mop)
2126  {
2127  if (printed_once == false)
2128  {
2129  printed_once = true;
2130  output_ctx ("\nFILE");
2131  }
2132  else
2133  {
2134  output_ctx (",\n");
2135  }
2136  emit_methfile_def (output_ctx, f);
2137  }
2138  }
2139 
2140  if (printed_once)
2141  {
2142  output_ctx ("\n");
2143  }
2144  }
2145 }
2146 
2147 
2148 /*
2149  * emit_methods - emit quries for adding the methods (instance, shared and
2150  * class) for the class given
2151  * return: true if any locally defined methods are emitted, false
2152  * otherwise
2153  * class(in): the class to emit the method definitions for
2154  * class_type(in): class type
2155  * Note:
2156  * Calls emit_method_def for each method. This function will only
2157  * emit those methods defined in this class and NOT any of the
2158  * inherited methods.
2159  */
2160 static bool
2161 emit_methods (print_output & output_ctx, DB_OBJECT * class_, const char *class_type)
2162 {
2163  DB_METHOD *method_list, *class_method_list, *m;
2164  DB_METHOD *first_method, *first_class_method;
2165  const char *name;
2166 
2167  method_list = db_get_methods (class_);
2168  class_method_list = db_get_class_methods (class_);
2169 
2170  /* see if we have any locally defined components on either list */
2171  first_method = first_class_method = NULL;
2172  for (m = method_list; m != NULL && first_method == NULL; m = db_method_next (m))
2173  {
2174  if (db_method_class (m) == class_)
2175  {
2176  first_method = m;
2177  }
2178  }
2179 
2180  for (m = class_method_list; m != NULL && first_class_method == NULL; m = db_method_next (m))
2181  {
2182  if (db_method_class (m) == class_)
2183  {
2184  first_class_method = m;
2185  }
2186  }
2187 
2188  if (first_method != NULL)
2189  {
2190  name = db_get_class_name (class_);
2191  output_ctx ("ALTER %s %s%s%s ADD METHOD\n", class_type, PRINT_IDENTIFIER (name));
2192 
2193  for (m = first_method; m != NULL; m = db_method_next (m))
2194  {
2195  if (db_method_class (m) == class_)
2196  {
2197  if (m != first_method)
2198  {
2199  output_ctx (",\n");
2200  }
2201  emit_method_def (output_ctx, m, INSTANCE_METHOD);
2202  }
2203  }
2204 
2205  output_ctx ("\n");
2206  emit_method_files (output_ctx, class_);
2207  output_ctx (";\n");
2208  }
2209 
2210  /* eventually, this may merge with the statement above */
2211  if (first_class_method != NULL)
2212  {
2213  name = db_get_class_name (class_);
2214  output_ctx ("ALTER %s %s%s%s ADD METHOD\n", class_type, PRINT_IDENTIFIER (name));
2215 
2216  for (m = first_class_method; m != NULL; m = db_method_next (m))
2217  {
2218  if (db_method_class (m) == class_)
2219  {
2220  if (m != first_class_method)
2221  {
2222  output_ctx (",\n");
2223  }
2224  emit_method_def (output_ctx, m, CLASS_METHOD);
2225  }
2226  }
2227 
2228  output_ctx ("\n");
2229 
2230  if (first_method == NULL)
2231  {
2232  emit_method_files (output_ctx, class_);
2233  }
2234  output_ctx (";\n");
2235  }
2236 
2237  return ((first_method != NULL || first_class_method != NULL));
2238 }
2239 
2240 /*
2241  * ex_contains_object_reference - see if a value contains a reference
2242  * to a database object.
2243  * return: non-zero if there is an object reference in the value
2244  * value(in): value to examine
2245  * Note:
2246  * This is used during the dumping of the default values for attribute
2247  * definitions in the schema file.
2248  * When we encounter object references, we don't include them in
2249  * the schema file, they must be included in the object file.
2250  * This is public so it can be used by unload_object.c to tell when to
2251  * dump the values in the object file.
2252  */
2253 static int
2255 {
2256  DB_TYPE type;
2257  DB_SET *set;
2258  int error;
2259  DB_VALUE setval;
2260  int has_object, size, i;
2261 
2262  has_object = 0;
2263  if (value != NULL)
2264  {
2265  if (DB_VALUE_TYPE (value) == DB_TYPE_OBJECT)
2266  {
2267  has_object = db_get_object (value) != NULL;
2268  }
2269  else if (TP_IS_SET_TYPE (DB_VALUE_TYPE (value)))
2270  {
2271  set = db_get_set (value);
2272  size = db_set_size (set);
2273  type = db_set_type (set);
2274 
2275  for (i = 0; i < size && !has_object; i++)
2276  {
2277  if (type == DB_TYPE_SEQUENCE)
2278  {
2279  error = db_seq_get (set, i, &setval);
2280  }
2281  else
2282  {
2283  error = db_set_get (set, i, &setval);
2284  }
2285 
2286  if (error)
2287  {
2288  /*
2289  * shouldn't happen, return 1 so we don't try to dump this
2290  * value
2291  */
2292  has_object = 1;
2293  }
2294  else
2295  {
2296  has_object = ex_contains_object_reference (&setval);
2297  }
2298 
2299  db_value_clear (&setval);
2300  }
2301  }
2302  }
2303  return has_object;
2304 }
2305 
2306 /*
2307  * emit_attribute_def - emit attribute definition
2308  * return: void
2309  * attribute(in): attribute descriptor
2310  * qualifier(in): the qualifier for the attribute (default, class or shared)
2311  */
2312 static void
2313 emit_attribute_def (print_output & output_ctx, DB_ATTRIBUTE * attribute, ATTRIBUTE_QUALIFIER qualifier)
2314 {
2316  const char *name;
2317 
2318  name = db_attribute_name (attribute);
2319  switch (qualifier)
2320  {
2321  case INSTANCE_ATTRIBUTE:
2322  {
2323  output_ctx (" %s%s%s ", PRINT_IDENTIFIER (name));
2324  break;
2325  } /* case INSTANCE_ATTRIBUTE */
2326  case SHARED_ATTRIBUTE:
2327  {
2328  output_ctx (" %s%s%s ", PRINT_IDENTIFIER (name));
2329  break;
2330  } /* case SHARED_ATTRIBUTE */
2331  case CLASS_ATTRIBUTE:
2332  {
2333  /*
2334  * NOTE: The parser no longer recognizes a CLASS prefix for class
2335  * attributes, this will have been encoded in the surrounding
2336  * "ADD CLASS ATTRIBUTE" clause
2337  */
2338  output_ctx (" %s%s%s ", PRINT_IDENTIFIER (name));
2339  break;
2340  } /* case CLASS_ATTRIBUTE */
2341  }
2342 
2343  emit_domain_def (output_ctx, db_attribute_domain (attribute));
2344 
2345  if (emit_autoincrement_def (output_ctx, attribute) != NO_ERROR)
2346  {
2347  ; /* just continue */
2348  }
2349 
2350  if (qualifier == SHARED_ATTRIBUTE)
2351  {
2352  output_ctx (" SHARED ");
2353  }
2354 
2355  default_value = db_attribute_default (attribute);
2356  if ((default_value != NULL && !DB_IS_NULL (default_value))
2358  {
2359  const char *default_expr_type_str;
2360 
2361  if (qualifier != SHARED_ATTRIBUTE)
2362  {
2363  output_ctx (" DEFAULT ");
2364  }
2365 
2367  {
2368  output_ctx ("TO_CHAR(");
2369  }
2370 
2371  default_expr_type_str = db_default_expression_string (attribute->default_value.default_expr.default_expr_type);
2372  if (default_expr_type_str != NULL)
2373  {
2374  output_ctx ("%s", default_expr_type_str);
2375  }
2376  else
2377  {
2378  /* these are set during the object load phase */
2379  if (ex_contains_object_reference (default_value))
2380  {
2381  output_ctx ("NULL");
2382  }
2383  else
2384  {
2385  /* use the desc_ printer, need to have this in a better place */
2386  desc_value_print (output_ctx, default_value);
2387  }
2388  }
2389 
2391  {
2393  {
2394  output_ctx (", \'");
2395  output_ctx ("%s", attribute->default_value.default_expr.default_expr_format);
2396  output_ctx ("\'");
2397  }
2398 
2399  output_ctx (")");
2400  }
2401  }
2402 
2403  if (attribute->on_update_default_expr != DB_DEFAULT_NONE)
2404  {
2405  const char *default_expr_type_str;
2406 
2407  output_ctx (" ON UPDATE ");
2408 
2409  default_expr_type_str = db_default_expression_string (attribute->on_update_default_expr);
2410  if (default_expr_type_str != NULL)
2411  {
2412  output_ctx ("%s", default_expr_type_str);
2413  }
2414  }
2415 
2416  /* emit constraints */
2417  if (db_attribute_is_non_null (attribute))
2418  {
2419  output_ctx (" NOT NULL");
2420  }
2421 
2422  /* emit comment */
2423  if (attribute->comment != NULL && attribute->comment[0] != '\0')
2424  {
2425  output_ctx (" ");
2426  help_print_describe_comment (output_ctx, attribute->comment);
2427  }
2428 }
2429 
2430 
2431 
2432 /*
2433  * emit_unique_def - emit the unique constraint definitions for this class
2434  * return: void
2435  * class(in): the class to emit the attributes for
2436  */
2437 static void
2438 emit_unique_def (print_output & output_ctx, DB_OBJECT * class_, const char *class_type)
2439 {
2440  DB_CONSTRAINT *constraint_list, *constraint;
2441  DB_ATTRIBUTE **atts, **att;
2442  bool has_inherited_atts;
2443  int num_printed = 0;
2444  const char *name, *class_name;
2445  int not_online = 0;
2446 
2447  class_name = db_get_class_name (class_);
2448 
2449  /* First we must check if there is a unique one without the online index tag. */
2450 
2451  constraint_list = db_get_constraints (class_);
2452  if (constraint_list == NULL)
2453  {
2454  return;
2455  }
2456 
2457  for (constraint = constraint_list; constraint != NULL && not_online == 0;
2458  constraint = db_constraint_next (constraint))
2459  {
2460  if (db_constraint_type (constraint) != DB_CONSTRAINT_UNIQUE
2461  && db_constraint_type (constraint) != DB_CONSTRAINT_PRIMARY_KEY)
2462  {
2463  continue;
2464  }
2465 
2467  {
2468  /* Skip the unique index definitions for online indexes. */
2469  continue;
2470  }
2471  not_online++;
2472  }
2473 
2474  if (not_online == 0)
2475  {
2476  /* We need to return and not print anything. */
2477  return;
2478  }
2479 
2480  output_ctx ("\nALTER %s %s%s%s ADD ATTRIBUTE\n", class_type, PRINT_IDENTIFIER (class_name));
2481 
2482  for (constraint = constraint_list; constraint != NULL; constraint = db_constraint_next (constraint))
2483  {
2484  if (db_constraint_type (constraint) != DB_CONSTRAINT_UNIQUE
2485  && db_constraint_type (constraint) != DB_CONSTRAINT_PRIMARY_KEY)
2486  {
2487  continue;
2488  }
2489 
2491  {
2492  /* Skip the unique index definitions for online indexes. */
2493  continue;
2494  }
2495 
2496  atts = db_constraint_attributes (constraint);
2497  has_inherited_atts = false;
2498 
2499  for (att = atts; *att != NULL; att++)
2500  {
2501  if (db_attribute_class (*att) != class_)
2502  {
2503  has_inherited_atts = true;
2504  break;
2505  }
2506  }
2507 
2508  if (!has_inherited_atts)
2509  {
2510  if (num_printed > 0)
2511  {
2512  output_ctx (",\n");
2513  }
2514 
2515  if (constraint->type == SM_CONSTRAINT_PRIMARY_KEY)
2516  {
2517  output_ctx (" CONSTRAINT [%s] PRIMARY KEY(", constraint->name);
2518  }
2519  else
2520  {
2521  output_ctx (" CONSTRAINT [%s] UNIQUE(", constraint->name);
2522  }
2523 
2524  int i;
2525  for (att = atts, i = 0; *att != NULL; att++, i++)
2526  {
2527  name = db_attribute_name (*att);
2528  if (att != atts)
2529  {
2530  output_ctx (", ");
2531  }
2532 
2533  output_ctx ("%s%s%s", PRINT_IDENTIFIER (name));
2534 
2535  if (constraint->asc_desc != NULL && constraint->asc_desc[i] != 0)
2536  {
2537  output_ctx ("%s", " DESC");
2538  }
2539  }
2540  output_ctx (")");
2541 
2542  if (constraint->comment != NULL && constraint->comment[0] != '\0')
2543  {
2544  output_ctx (" ");
2545  help_print_describe_comment (output_ctx, constraint->comment);
2546  }
2547 
2548  ++num_printed;
2549  }
2550  }
2551 
2552  output_ctx (";\n");
2553 }
2554 
2555 /*
2556  * emit_reverse_unique_def - emit a reverse unique index definition query part
2557  * return: void
2558  * class(in): class object
2559  */
2560 static void
2562 {
2563  DB_CONSTRAINT *constraint_list, *constraint;
2564  DB_ATTRIBUTE **atts, **att;
2565  bool has_inherited_atts;
2566  const char *name;
2567 
2568  constraint_list = db_get_constraints (class_);
2569  if (constraint_list == NULL)
2570  {
2571  return;
2572  }
2573 
2574  for (constraint = constraint_list; constraint != NULL; constraint = db_constraint_next (constraint))
2575  {
2577  {
2578  continue;
2579  }
2580 
2582  {
2583  /* We skip definitions for unique indexes during online loading. */
2584  continue;
2585  }
2586 
2587  atts = db_constraint_attributes (constraint);
2588  has_inherited_atts = false;
2589 
2590  for (att = atts; *att != NULL; att++)
2591  {
2592  if (db_attribute_class (*att) != class_)
2593  {
2594  has_inherited_atts = true;
2595  break;
2596  }
2597  }
2598 
2599  if (!has_inherited_atts)
2600  {
2601  name = db_get_class_name (class_);
2602  output_ctx ("CREATE REVERSE UNIQUE INDEX %s%s%s on %s%s%s (", PRINT_IDENTIFIER (constraint->name),
2603  PRINT_IDENTIFIER (name));
2604 
2605  for (att = atts; *att != NULL; att++)
2606  {
2607  name = db_attribute_name (*att);
2608  if (att != atts)
2609  {
2610  output_ctx (", ");
2611  }
2612  output_ctx ("%s%s%s", PRINT_IDENTIFIER (name));
2613 
2614  // reverse unique does not care for direction of the column.
2615  }
2616  output_ctx (");\n");
2617  }
2618  }
2619 }
2620 
2621 
2622 /*
2623  * emit_index_def - emit the index constraint definitions for this class
2624  * return: void
2625  * class(in): the class to emit the indexes for
2626  */
2627 static void
2628 emit_index_def (print_output & output_ctx, DB_OBJECT * class_)
2629 {
2630  DB_CONSTRAINT *constraint_list, *constraint;
2631  DB_CONSTRAINT_TYPE ctype;
2632  DB_ATTRIBUTE **atts, **att;
2633  const char *cls_name, *att_name;
2634  int partitioned_subclass = 0, au_save;
2635  SM_CLASS *supclass = NULL;
2636  const int *asc_desc;
2637  const int *prefix_length;
2638  int k, n_attrs = 0;
2639 
2640  constraint_list = db_get_constraints (class_);
2641  if (constraint_list == NULL)
2642  {
2643  return;
2644  }
2645 
2646  cls_name = db_get_class_name (class_);
2647  if (cls_name != NULL)
2648  {
2649  partitioned_subclass = do_is_partitioned_subclass (NULL, cls_name, NULL);
2650  }
2651  else
2652  {
2653  cls_name = "";
2654  }
2655 
2656  if (partitioned_subclass)
2657  {
2658  DB_OBJECT *root_op = NULL;
2659  AU_DISABLE (au_save);
2660  if (do_get_partition_parent (class_, &root_op) == NO_ERROR)
2661  {
2662  if (au_fetch_class (root_op, &supclass, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
2663  {
2664  supclass = NULL;
2665  }
2666  }
2667 
2668  AU_ENABLE (au_save);
2669  }
2670 
2671  for (constraint = constraint_list; constraint != NULL; constraint = db_constraint_next (constraint))
2672  {
2673  ctype = db_constraint_type (constraint);
2675  && (ctype != DB_CONSTRAINT_INDEX && ctype != DB_CONSTRAINT_REVERSE_INDEX))
2676  {
2677  continue;
2678  }
2679 
2680  if (supclass && classobj_find_class_index (supclass, constraint->name) != NULL)
2681  {
2682  continue; /* same index skip */
2683  }
2684 
2685  if (constraint->func_index_info)
2686  {
2687  output_ctx ("CREATE %s%sINDEX %s%s%s ON %s%s%s (",
2688  (ctype == DB_CONSTRAINT_REVERSE_INDEX || ctype == DB_CONSTRAINT_REVERSE_UNIQUE) ? "REVERSE " : "",
2689  (ctype == DB_CONSTRAINT_UNIQUE || ctype == DB_CONSTRAINT_REVERSE_UNIQUE) ? "UNIQUE " : "",
2690  PRINT_FUNCTION_INDEX_NAME (constraint->name), PRINT_IDENTIFIER (cls_name));
2691  }
2692  else
2693  {
2694  output_ctx ("CREATE %s%sINDEX %s%s%s ON %s%s%s (",
2695  (ctype == DB_CONSTRAINT_REVERSE_INDEX || ctype == DB_CONSTRAINT_REVERSE_UNIQUE) ? "REVERSE " : "",
2696  (ctype == DB_CONSTRAINT_UNIQUE || ctype == DB_CONSTRAINT_REVERSE_UNIQUE) ? "UNIQUE " : "",
2697  PRINT_IDENTIFIER (constraint->name), PRINT_IDENTIFIER (cls_name));
2698  }
2699 
2700  asc_desc = NULL; /* init */
2701  prefix_length = NULL;
2702  if (ctype == DB_CONSTRAINT_INDEX)
2703  { /* is not reverse index */
2704  /* need to get asc/desc info */
2705  asc_desc = db_constraint_asc_desc (constraint);
2706  prefix_length = db_constraint_prefix_length (constraint);
2707  }
2708  else if (ctype == DB_CONSTRAINT_UNIQUE)
2709  { /* is not reverse unique index */
2710  /* need to get asc/desc info */
2711  asc_desc = db_constraint_asc_desc (constraint);
2712  }
2713 
2714  atts = db_constraint_attributes (constraint);
2715 
2716  if (constraint->func_index_info)
2717  {
2718  n_attrs = constraint->func_index_info->attr_index_start + 1;
2719  }
2720  else
2721  {
2722  n_attrs = 0;
2723  for (att = atts; *att != NULL; att++)
2724  {
2725  n_attrs++;
2726  }
2727  }
2728  k = 0;
2729  for (att = atts; k < n_attrs; att++)
2730  {
2731  if (constraint->func_index_info)
2732  {
2733  if (k == constraint->func_index_info->col_id)
2734  {
2735  if (k > 0)
2736  {
2737  output_ctx (", ");
2738  }
2739  output_ctx ("%s", constraint->func_index_info->expr_str);
2740  if (constraint->func_index_info->fi_domain->is_desc)
2741  {
2742  output_ctx ("%s", " DESC");
2743  }
2744 
2745  k++;
2746  if (k == n_attrs)
2747  {
2748  break;
2749  }
2750  }
2751  }
2752  att_name = db_attribute_name (*att);
2753  if (k > 0)
2754  {
2755  output_ctx (", ");
2756  }
2757  output_ctx ("%s%s%s", PRINT_IDENTIFIER (att_name));
2758 
2759  if (prefix_length)
2760  {
2761  if (*prefix_length >= 0)
2762  {
2763  output_ctx (" (%d)", *prefix_length);
2764  }
2765  prefix_length++;
2766  }
2767 
2768  if (asc_desc)
2769  {
2770  if (*asc_desc == 1)
2771  {
2772  output_ctx ("%s", " DESC");
2773  }
2774  asc_desc++;
2775  }
2776  k++;
2777  }
2778  if (constraint->filter_predicate)
2779  {
2780  if (constraint->filter_predicate->pred_string)
2781  {
2782  output_ctx (") where %s", constraint->filter_predicate->pred_string);
2783  }
2784  }
2785  else
2786  {
2787  output_ctx (")");
2788  }
2789  if (constraint->comment != NULL && constraint->comment[0] != '\0')
2790  {
2791  output_ctx (" ");
2792  help_print_describe_comment (output_ctx, constraint->comment);
2793  }
2794 
2795  /* Safeguard. */
2796  /* If it's unique then it must surely be with online flag. */
2798  || (ctype != DB_CONSTRAINT_UNIQUE && ctype != DB_CONSTRAINT_REVERSE_UNIQUE));
2800  {
2801  output_ctx (" WITH ONLINE");
2802  }
2803  output_ctx (";\n");
2804  }
2805 }
2806 
2807 
2808 /*
2809  * emit_domain_def - emit a domain defintion part
2810  * return: void
2811  * domains(in): domain list
2812  */
2813 static void
2814 emit_domain_def (print_output & output_ctx, DB_DOMAIN * domains)
2815 {
2816  DB_TYPE type;
2817  PR_TYPE *prtype;
2818  DB_DOMAIN *domain;
2819  DB_OBJECT *class_;
2820  int precision;
2821  int has_collation;
2822  const char *name;
2823  const char *json_schema;
2824 
2825  for (domain = domains; domain != NULL; domain = db_domain_next (domain))
2826  {
2827  type = TP_DOMAIN_TYPE (domain);
2828  prtype = pr_type_from_id (type);
2829  if (prtype == NULL)
2830  {
2831  continue;
2832  }
2833 
2834  if (type == DB_TYPE_OBJECT)
2835  {
2836  class_ = db_domain_class (domain);
2837  if (class_ == NULL)
2838  {
2839  output_ctx ("%s", prtype->name);
2840  }
2841  else
2842  {
2843  name = db_get_class_name (class_);
2844  output_ctx ("%s%s%s", PRINT_IDENTIFIER (name));
2845  }
2846  }
2847  else
2848  {
2849  has_collation = 0;
2850  output_ctx ("%s", prtype->name);
2851 
2852  switch (type)
2853  {
2854  case DB_TYPE_VARCHAR:
2855  case DB_TYPE_CHAR:
2856  case DB_TYPE_NCHAR:
2857  case DB_TYPE_VARNCHAR:
2858  has_collation = 1;
2859  /* FALLTHRU */
2860  case DB_TYPE_BIT:
2861  case DB_TYPE_VARBIT:
2862  precision = db_domain_precision (domain);
2863  output_ctx ("(%d)", precision == TP_FLOATING_PRECISION_VALUE ? DB_MAX_STRING_LENGTH : precision);
2864  break;
2865 
2866  case DB_TYPE_ENUMERATION:
2867  {
2868  int i = 0;
2869  DB_ENUM_ELEMENT *elem = NULL;
2870  int count = DOM_GET_ENUM_ELEMS_COUNT (domain);
2871 
2872  if (count == 0)
2873  {
2874  /* empty enumeration */
2875  output_ctx ("()");
2876  break;
2877  }
2878 
2879  output_ctx ("(");
2880  for (i = 1; i < count; i++)
2881  {
2882  elem = &DOM_GET_ENUM_ELEM (domain, i);
2883  output_ctx ("'%s', ", DB_GET_ENUM_ELEM_STRING (elem));
2884  }
2885  elem = &DOM_GET_ENUM_ELEM (domain, count);
2886  output_ctx ("'%s')", DB_GET_ENUM_ELEM_STRING (elem));
2887  has_collation = 1;
2888  break;
2889  }
2890 
2891  case DB_TYPE_NUMERIC:
2892  output_ctx ("(%d,%d)", db_domain_precision (domain), db_domain_scale (domain));
2893  break;
2894 
2895  case DB_TYPE_SET:
2896  case DB_TYPE_MULTISET:
2897  case DB_TYPE_SEQUENCE:
2898  output_ctx ("(");
2899  emit_domain_def (output_ctx, db_domain_set (domain));
2900  output_ctx (")");
2901  break;
2902 
2903  case DB_TYPE_JSON:
2904  json_schema = db_domain_raw_json_schema (domain);
2905  if (json_schema != NULL)
2906  {
2907  output_ctx ("('%s')", json_schema);
2908  }
2909  break;
2910 
2911  default:
2912  break;
2913  }
2914 
2915  if (has_collation)
2916  {
2917  (void) output_ctx (" COLLATE %s", lang_get_collation_name (domain->collation_id));
2918  }
2919  }
2920 
2921  if (db_domain_next (domain) != NULL)
2922  {
2923  output_ctx (",");
2924  }
2925  }
2926 }
2927 
2928 /*
2929  * emit_autoincrement_def - emit a auto-increment query part
2930  * return: void
2931  * attribute(in): attribute to add query part for
2932  */
2933 static int
2935 {
2936  int error = NO_ERROR;
2937  DB_VALUE min_val, inc_val;
2938  char str_buf[NUMERIC_MAX_STRING_SIZE];
2939 
2940  if (attribute->auto_increment != NULL)
2941  {
2942  db_make_null (&min_val);
2943  db_make_null (&inc_val);
2944 
2945  error = db_get (attribute->auto_increment, "min_val", &min_val);
2946  if (error < 0)
2947  {
2948  return error;
2949  }
2950 
2951  error = db_get (attribute->auto_increment, "increment_val", &inc_val);
2952  if (error < 0)
2953  {
2954  pr_clear_value (&min_val);
2955  return error;
2956  }
2957 
2958  output_ctx (" AUTO_INCREMENT(%s", numeric_db_value_print (&min_val, str_buf));
2959  output_ctx (", %s)", numeric_db_value_print (&inc_val, str_buf));
2960 
2961  pr_clear_value (&min_val);
2962  pr_clear_value (&inc_val);
2963  }
2964 
2965  return error;
2966 }
2967 
2968 
2969 /*
2970  * emit_method_def - emit method definitnio query
2971  * return: void
2972  * method(in): method
2973  * qualifier(in): the qualifier for this method (default or class)
2974  */
2975 static void
2976 emit_method_def (print_output & output_ctx, DB_METHOD * method, METHOD_QUALIFIER qualifier)
2977 {
2978  int arg_count, i;
2979  DB_DOMAIN *method_return_domain;
2980  const char *method_function_name;
2981  const char *name;
2982 
2983  name = db_method_name (method);
2984 
2985  switch (qualifier)
2986  {
2987  case INSTANCE_METHOD:
2988  {
2989  if (name != NULL)
2990  {
2991  output_ctx (" %s%s%s(", PRINT_IDENTIFIER (name));
2992  }
2993  break;
2994  } /* case INSTANCE_METHOD */
2995  case CLASS_METHOD:
2996  {
2997  if (name != NULL)
2998  {
2999  output_ctx ("CLASS %s%s%s(", PRINT_IDENTIFIER (name));
3000  }
3001  break;
3002  } /* case CLASS_METHOD */
3003  }
3004 
3005  /*
3006  * Emit argument type list
3007  */
3008  arg_count = db_method_arg_count (method);
3009  /* recall that arguments are numbered from 1 */
3010  for (i = 1; i < arg_count; i++)
3011  {
3012  emit_domain_def (output_ctx, db_method_arg_domain (method, i));
3013  output_ctx (", ");
3014  }
3015 
3016  if (arg_count)
3017  {
3018  emit_domain_def (output_ctx, db_method_arg_domain (method, i));
3019  }
3020 
3021  output_ctx (") ");
3022 
3023  /*
3024  * Emit method return domain
3025  */
3026  method_return_domain = db_method_return_domain (method);
3027  if (method_return_domain != NULL)
3028  {
3029  emit_domain_def (output_ctx, db_method_return_domain (method));
3030  }
3031 
3032  /*
3033  * Emit method function implementation
3034  */
3035  method_function_name = db_method_function (method);
3036  if (method_function_name != NULL)
3037  {
3038  name = db_method_function (method);
3039  if (name != NULL)
3040  {
3041  output_ctx (" FUNCTION %s%s%s", PRINT_IDENTIFIER (name));
3042  }
3043  }
3044 }
3045 
3046 
3047 /*
3048  * emit_methfile_def - emit method file name
3049  * return: nothing
3050  * methfile(in): method file
3051  */
3052 static void
3053 emit_methfile_def (print_output & output_ctx, DB_METHFILE * methfile)
3054 {
3055  output_ctx (" '%s'", db_methfile_name (methfile));
3056 }
3057 
3058 /*
3059  * emit_partition_parts - emit PARTITION query part
3060  * return: void
3061  * parts(in): part MOP
3062  * partcnt(in): relative position of 'parts'
3063  */
3064 static void
3065 emit_partition_parts (print_output & output_ctx, SM_PARTITION * partition_info, int partcnt)
3066 {
3067  DB_VALUE ele;
3068  int setsize, i1;
3069 
3070  if (partition_info == NULL)
3071  {
3072  return;
3073  }
3074 
3075  if (partcnt > 0)
3076  {
3077  output_ctx (",\n ");
3078  }
3079 
3080  output_ctx ("PARTITION %s%s%s ", PRINT_IDENTIFIER (partition_info->pname));
3081 
3082  switch (partition_info->partition_type)
3083  {
3084  case PT_PARTITION_RANGE:
3085  output_ctx (" VALUES LESS THAN ");
3086  if (!set_get_element_nocopy (partition_info->values, 1, &ele))
3087  { /* 0:MIN, 1:MAX */
3088  if (DB_IS_NULL (&ele))
3089  {
3090  output_ctx ("MAXVALUE");
3091  }
3092  else
3093  {
3094  output_ctx ("(");
3095  desc_value_print (output_ctx, &ele);
3096  output_ctx (")");
3097  }
3098  }
3099  break;
3100  case PT_PARTITION_LIST:
3101  output_ctx (" VALUES IN (");
3102  setsize = set_size (partition_info->values);
3103 
3104  for (i1 = 0; i1 < setsize; i1++)
3105  {
3106  if (i1 > 0)
3107  {
3108  output_ctx (", ");
3109  }
3110 
3111  if (!set_get_element_nocopy (partition_info->values, i1, &ele))
3112  {
3113  desc_value_print (output_ctx, &ele);
3114  }
3115  }
3116 
3117  output_ctx (")");
3118  break;
3119  }
3120 
3121  if (partition_info->comment != NULL && partition_info->comment[0] != '\0')
3122  {
3123  output_ctx (" ");
3124  help_print_describe_comment (output_ctx, partition_info->comment);
3125  }
3126 }
3127 
3128 /*
3129  * emit_partition_info - emit PARTINTION query for a class
3130  * return: void
3131  * clsobj(in): class object
3132  */
3133 static void
3134 emit_partition_info (print_output & output_ctx, MOP clsobj)
3135 {
3136  DB_VALUE ele;
3137  int partcnt = 0;
3138  char *ptr, *ptr2;
3139  const char *name;
3140  SM_CLASS *class_, *subclass;
3141  DB_OBJLIST *user;
3142 
3143  if (clsobj == NULL)
3144  {
3145  return;
3146  }
3147 
3148  name = db_get_class_name (clsobj);
3149  if (au_fetch_class (clsobj, &class_, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
3150  {
3151  return;
3152  }
3153 
3154  output_ctx ("\nALTER CLASS %s%s%s ", PRINT_IDENTIFIER (name));
3155  output_ctx ("\nPARTITION BY ");
3156 
3157  if (class_->partition->expr != NULL)
3158  {
3159  switch (class_->partition->partition_type)
3160  {
3161  case PT_PARTITION_HASH:
3162  output_ctx ("HASH ( ");
3163  break;
3164  case PT_PARTITION_RANGE:
3165  output_ctx ("RANGE ( ");
3166  break;
3167  case PT_PARTITION_LIST:
3168  output_ctx ("LIST ( ");
3169  break;
3170  }
3171 
3172  ptr = (char *) strstr (class_->partition->expr, "SELECT ");
3173  if (ptr)
3174  {
3175  ptr2 = strstr (ptr + 7, " FROM ");
3176  if (ptr2)
3177  {
3178  *ptr2 = 0;
3179  output_ctx ("%s", ptr + 7);
3180  output_ctx (" ) \n ");
3181  }
3182  }
3183 
3184  if (class_->partition->partition_type == PT_PARTITION_HASH)
3185  {
3186  if (!set_get_element_nocopy (class_->partition->values, 1, &ele))
3187  {
3188  output_ctx (" PARTITIONS %d", db_get_int (&ele));
3189  }
3190  }
3191  else
3192  {
3193  output_ctx (" ( ");
3194  for (user = class_->users; user != NULL; user = user->next)
3195  {
3196  if (au_fetch_class (user->op, &subclass, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
3197  {
3198  if (subclass->partition)
3199  {
3200  emit_partition_parts (output_ctx, subclass->partition, partcnt);
3201  partcnt++;
3202  }
3203  }
3204  }
3205  output_ctx (" ) ");
3206  }
3207  }
3208  else
3209  {
3210  /* FIXME */
3211  }
3212  output_ctx (";\n");
3213 }
3214 
3215 /*
3216  * emit_stored_procedure_args - emit stored procedure arguments
3217  * return: 0 if success, error count otherwise
3218  * arg_cnt(in): argument count
3219  * arg_set(in): set containg argument DB_VALUE
3220  */
3221 static int
3222 emit_stored_procedure_args (print_output & output_ctx, int arg_cnt, DB_SET * arg_set)
3223 {
3224  MOP arg;
3225  DB_VALUE arg_val, arg_name_val, arg_mode_val, arg_type_val, arg_comment_val;
3226  int arg_mode, arg_type, i, save;
3227  int err;
3228  int err_count = 0;
3229 
3230  AU_DISABLE (save);
3231 
3232  for (i = 0; i < arg_cnt; i++)
3233  {
3234  err = set_get_element (arg_set, i, &arg_val);
3235  if (err != NO_ERROR)
3236  {
3237  err_count++;
3238  continue;
3239  }
3240 
3241  arg = db_get_object (&arg_val);
3242 
3243  if ((err = db_get (arg, SP_ATTR_ARG_NAME, &arg_name_val)) != NO_ERROR
3244  || (err = db_get (arg, SP_ATTR_MODE, &arg_mode_val)) != NO_ERROR
3245  || (err = db_get (arg, SP_ATTR_DATA_TYPE, &arg_type_val)) != NO_ERROR
3246  || (err = db_get (arg, SP_ATTR_ARG_COMMENT, &arg_comment_val)) != NO_ERROR)
3247  {
3248  err_count++;
3249  continue;
3250  }
3251 
3252  output_ctx ("%s%s%s ", PRINT_IDENTIFIER (db_get_string (&arg_name_val)));
3253 
3254  arg_mode = db_get_int (&arg_mode_val);
3255  output_ctx ("%s ", arg_mode == SP_MODE_IN ? "IN" : arg_mode == SP_MODE_OUT ? "OUT" : "INOUT");
3256 
3257  arg_type = db_get_int (&arg_type_val);
3258 
3259  if (arg_type == DB_TYPE_RESULTSET)
3260  {
3261  output_ctx ("CURSOR");
3262  }
3263  else
3264  {
3265  output_ctx ("%s", db_get_type_name ((DB_TYPE) arg_type));
3266  }
3267 
3268  if (!DB_IS_NULL (&arg_comment_val))
3269  {
3270  output_ctx (" COMMENT ");
3271  desc_value_print (output_ctx, &arg_comment_val);
3272  }
3273 
3274  if (i < arg_cnt - 1)
3275  {
3276  output_ctx (", ");
3277  }
3278 
3279  pr_clear_value (&arg_val);
3280  }
3281 
3282  AU_ENABLE (save);
3283  return err_count;
3284 }
3285 
3286 /*
3287  * emit_stored_procedure - emit stored procedure
3288  * return: void
3289  * output_ctx(in/out): output context
3290  */
3291 static int
3293 {
3294  MOP cls, obj, owner;
3295  DB_OBJLIST *sp_list = NULL, *cur_sp;
3296  DB_VALUE sp_name_val, sp_type_val, arg_cnt_val, args_val, rtn_type_val, method_val, comment_val;
3297  DB_VALUE owner_val, owner_name_val;
3298  int sp_type, rtn_type, arg_cnt, save;
3299  DB_SET *arg_set;
3300  int err;
3301  int err_count = 0;
3302 
3303  AU_DISABLE (save);
3304 
3305  cls = db_find_class (SP_CLASS_NAME);
3306  if (cls == NULL)
3307  {
3308  AU_ENABLE (save);
3309  return 1;
3310  }
3311 
3312  sp_list = db_get_all_objects (cls);
3313  for (cur_sp = sp_list; cur_sp; cur_sp = cur_sp->next)
3314  {
3315  obj = cur_sp->op;
3316 
3317  if ((err = db_get (obj, SP_ATTR_SP_TYPE, &sp_type_val)) != NO_ERROR
3318  || (err = db_get (obj, SP_ATTR_NAME, &sp_name_val)) != NO_ERROR
3319  || (err = db_get (obj, SP_ATTR_ARG_COUNT, &arg_cnt_val)) != NO_ERROR
3320  || (err = db_get (obj, SP_ATTR_ARGS, &args_val)) != NO_ERROR
3321  || ((err = db_get (obj, SP_ATTR_RETURN_TYPE, &rtn_type_val)) != NO_ERROR)
3322  || (err = db_get (obj, SP_ATTR_TARGET, &method_val)) != NO_ERROR
3323  || (err = db_get (obj, SP_ATTR_OWNER, &owner_val)) != NO_ERROR
3324  || (err = db_get (obj, SP_ATTR_COMMENT, &comment_val)) != NO_ERROR)
3325  {
3326  err_count++;
3327  continue;
3328  }
3329 
3330  sp_type = db_get_int (&sp_type_val);
3331  output_ctx ("\nCREATE %s", sp_type == SP_TYPE_PROCEDURE ? "PROCEDURE" : "FUNCTION");
3332 
3333  output_ctx (" %s%s%s (", PRINT_IDENTIFIER (db_get_string (&sp_name_val)));
3334 
3335  arg_cnt = db_get_int (&arg_cnt_val);
3336  arg_set = db_get_set (&args_val);
3337  if (emit_stored_procedure_args (output_ctx, arg_cnt, arg_set) > 0)
3338  {
3339  err_count++;
3340  output_ctx (";\n");
3341  continue;
3342  }
3343  output_ctx (") ");
3344 
3345  if (sp_type == SP_TYPE_FUNCTION)
3346  {
3347  rtn_type = db_get_int (&rtn_type_val);
3348 
3349  if (rtn_type == DB_TYPE_RESULTSET)
3350  {
3351  output_ctx ("RETURN CURSOR ");
3352  }
3353  else
3354  {
3355  output_ctx ("RETURN %s ", db_get_type_name ((DB_TYPE) rtn_type));
3356  }
3357  }
3358 
3359  output_ctx ("AS LANGUAGE JAVA NAME '%s'", db_get_string (&method_val));
3360 
3361  if (!DB_IS_NULL (&comment_val))
3362  {
3363  output_ctx (" COMMENT ");
3364  desc_value_print (output_ctx, &comment_val);
3365  }
3366 
3367  output_ctx (";\n");
3368 
3369  owner = db_get_object (&owner_val);
3370  err = db_get (owner, "name", &owner_name_val);
3371  if (err != NO_ERROR)
3372  {
3373  err_count++;
3374  continue;
3375  }
3376 
3377  output_ctx ("call [change_sp_owner]('%s', '%s') on class [db_root];\n", db_get_string (&sp_name_val),
3378  db_get_string (&owner_name_val));
3379 
3380  db_value_clear (&owner_name_val);
3381  }
3382 
3383  db_objlist_free (sp_list);
3384  AU_ENABLE (save);
3385 
3386  return err_count;
3387 }
3388 
3389 /*
3390  * emit_foreign_key - emit foreign key
3391  * return: NO_ERROR if successful, error code otherwise
3392  * output_ctx(in/out): output context
3393  * classes(in): MOP list for dump foreign key
3394  */
3395 static int
3396 emit_foreign_key (print_output & output_ctx, DB_OBJLIST * classes)
3397 {
3398  DB_OBJLIST *cl;
3399  DB_CONSTRAINT *constraint_list, *constraint;
3400  DB_ATTRIBUTE **atts, **att;
3401  bool has_inherited_atts;
3402  const char *cls_name, *att_name;
3403  MOP ref_clsop;
3404 
3405  for (cl = classes; cl != NULL; cl = cl->next)
3406  {
3407  constraint_list = db_get_constraints (cl->op);
3408  cls_name = db_get_class_name (cl->op);
3409 
3410  for (constraint = constraint_list; constraint != NULL; constraint = db_constraint_next (constraint))
3411  {
3412  if (db_constraint_type (constraint) != DB_CONSTRAINT_FOREIGN_KEY)
3413  {
3414  continue;
3415  }
3416 
3417  atts = db_constraint_attributes (constraint);
3418  has_inherited_atts = false;
3419  for (att = atts; *att != NULL; att++)
3420  {
3421  if (db_attribute_class (*att) != cl->op)
3422  {
3423  has_inherited_atts = true;
3424  break;
3425  }
3426  }
3427 
3428  if (has_inherited_atts)
3429  {
3430  continue;
3431  }
3432 
3433  output_ctx ("ALTER CLASS [%s] ADD", cls_name);
3434 
3435  output_ctx (" CONSTRAINT [%s] FOREIGN KEY(", constraint->name);
3436 
3437  for (att = atts; *att != NULL; att++)
3438  {
3439  att_name = db_attribute_name (*att);
3440  if (att != atts)
3441  {
3442  output_ctx (", ");
3443  }
3444  output_ctx ("%s%s%s", PRINT_IDENTIFIER (att_name));
3445  }
3446  output_ctx (")");
3447 
3448  ref_clsop = ws_mop (&(constraint->fk_info->ref_class_oid), NULL);
3449  output_ctx (" REFERENCES %s%s%s ", PRINT_IDENTIFIER (db_get_class_name (ref_clsop)));
3450  output_ctx ("ON DELETE %s ", classobj_describe_foreign_key_action (constraint->fk_info->delete_action));
3451  output_ctx ("ON UPDATE %s ", classobj_describe_foreign_key_action (constraint->fk_info->update_action));
3452 
3453  if (constraint->comment != NULL && constraint->comment[0] != '\0')
3454  {
3455  output_ctx (" ");
3456  help_print_describe_comment (output_ctx, constraint->comment);
3457  }
3458 
3459  (void) output_ctx (";\n\n");
3460  }
3461  }
3462 
3463  return NO_ERROR;
3464 }
3465 
3466 int
3468  char *output_filename_p, const size_t filename_size)
3469 {
3470  return create_filename (output_dirname, output_prefix, SCHEMA_SUFFIX, output_filename_p, filename_size);
3471 }
3472 
3473 int
3475  char *output_filename_p, const size_t filename_size)
3476 {
3477  return create_filename (output_dirname, output_prefix, TRIGGER_SUFFIX, output_filename_p, filename_size);
3478 }
3479 
3480 int
3482  char *output_filename_p, const size_t filename_size)
3483 {
3484  return create_filename (output_dirname, output_prefix, INDEX_SUFFIX, output_filename_p, filename_size);
3485 }
3486 
3487 static int
3488 create_filename (const char *output_dirname, const char *output_prefix, const char *suffix,
3489  char *output_filename_p, const size_t filename_size)
3490 {
3491  if (output_dirname == NULL)
3492  {
3493  output_dirname = ".";
3494  }
3495 
3496  size_t total = strlen (output_dirname) + strlen (output_prefix) + strlen (suffix) + 8;
3497 
3498  if (total > filename_size)
3499  {
3500  return -1;
3501  }
3502 
3503  snprintf (output_filename_p, filename_size - 1, "%s/%s%s", output_dirname, output_prefix, suffix);
3504 
3505  return 0;
3506 }
#define SP_ATTR_RETURN_TYPE
Definition: jsp_cl.h:42
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
DB_OBJECT * db_attribute_class(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1189
int ml_append(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4548
const char * expr
Definition: class_object.h:697
DB_OBJLIST * classes
static int emit_foreign_key(print_output &output_ctx, DB_OBJLIST *classes)
void desc_value_print(print_output &output_ctx, DB_VALUE *value)
Definition: load_object.c:1616
METHOD_QUALIFIER
Definition: unload_schema.c:96
#define NO_ERROR
Definition: error_code.h:46
int set_get_element_nocopy(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2616
#define DB_GET_ENUM_ELEM_STRING(elem)
Definition: dbtype.h:103
#define AU_DISABLE(save)
Definition: authenticate.h:106
DB_COLLECTION * db_get_set(const DB_VALUE *value)
int tr_dump_selective_triggers(print_output &output_ctx, DB_OBJLIST *classes)
EMIT_STORAGE_ORDER storage_order
static int is_dependent_class(DB_OBJECT *class_, DB_OBJLIST *unordered, DB_OBJLIST *ordered)
#define SP_ATTR_ARG_COUNT
Definition: jsp_cl.h:44
int db_attribute_is_indexed(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1375
SM_FOREIGN_KEY_INFO * fk_info
Definition: class_object.h:537
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
static DB_OBJLIST * emit_query_specs(print_output &output_ctx, DB_OBJLIST *classes)
int db_domain_scale(const DB_DOMAIN *domain)
Definition: db_macro.c:4098
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
const char * db_get_type_name(DB_TYPE type_id)
Definition: db_info.c:722
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
SM_PREDICATE_INFO * filter_predicate
Definition: class_object.h:536
static void emit_method_def(print_output &output_ctx, DB_METHOD *method, METHOD_QUALIFIER qualifier)
#define TP_IS_SET_TYPE(typenum)
static bool emit_class_attributes(print_output &output_ctx, DB_OBJECT *class_, const char *class_type)
#define DB_MAX_STRING_LENGTH
Definition: dbtype_def.h:516
int db_domain_precision(const DB_DOMAIN *domain)
Definition: db_macro.c:4079
int extract_triggers_to_file(extract_context &ctxt, const char *output_filename)
int db_seq_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:712
int db_get_int(const DB_VALUE *value)
static int emit_stored_procedure_args(print_output &output_ctx, int arg_cnt, DB_SET *arg_set)
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
DB_TYPE
Definition: dbtype_def.h:670
static void filter_unrequired_classes(DB_OBJLIST **class_list)
DB_CONSTRAINT * db_constraint_next(DB_CONSTRAINT *constraint)
Definition: db_info.c:1938
static int ex_contains_object_reference(DB_VALUE *value)
int db_method_arg_count(DB_METHOD *method)
Definition: db_info.c:1710
char * output_prefix
Definition: unloaddb.c:67
static int check_domain_dependencies(DB_DOMAIN *domain, DB_OBJECT *this_class, DB_OBJLIST *unordered, DB_OBJLIST *ordered)
PT_NODE * pt_has_using_index_clause(PARSER_CONTEXT *parser, PT_NODE *node, void *arg, int *continue_walk)
SM_PARTITION * partition
Definition: class_object.h:760
DB_DOMAIN * db_domain_next(const DB_DOMAIN *domain)
Definition: db_macro.c:3974
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
int db_attribute_order(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1144
int is_req_class(DB_OBJECT *class_)
#define SP_ATTR_COMMENT
Definition: jsp_cl.h:48
DB_CONSTRAINT * db_get_constraints(DB_OBJECT *obj)
Definition: db_info.c:1909
PARSER_CONTEXT * parser_create_parser(void)
Definition: parse_tree.c:1169
static int class_type(DB_OBJECT *class_obj)
Definition: cas_execute.c:8143
DB_ATTRIBUTE ** db_constraint_attributes(DB_CONSTRAINT *constraint)
Definition: db_info.c:2052
int numeric_db_value_compare(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define PRINT_FUNCTION_INDEX_NAME(s)
Definition: unloaddb.h:59
static char * output_filename
Definition: unload_object.c:87
int extract_triggers(extract_context &ctxt, print_output &output_ctx)
DB_OBJLIST * db_get_superclasses(DB_OBJECT *obj)
Definition: db_info.c:630
static void emit_partition_parts(print_output &output_ctx, SM_PARTITION *partition_info, int partcnt)
#define SP_ATTR_TARGET
Definition: jsp_cl.h:46
SM_FUNCTION_INFO * func_index_info
Definition: class_object.h:541
const char * db_default_expression_string(DB_DEFAULT_EXPR_TYPE default_expr_type)
Definition: db_macro.c:4947
const char * pname
Definition: class_object.h:694
int extract_classes_to_file(extract_context &ctxt, const char *output_filename)
FILE * output_file
Definition: unloaddb.c:48
int er_errid(void)
int do_get_partition_parent(DB_OBJECT *const classop, MOP *const parentop)
const char * comment
Definition: class_object.h:698
DB_OBJECT * db_method_class(DB_METHOD *method)
Definition: db_info.c:1626
int au_export_users(print_output &output_ctx)
static bool emit_class_meta(print_output &output_ctx, DB_OBJECT *table)
int numeric_db_value_sub(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
const char * name
#define ER_NODATA_TOBE_UNLOADED
Definition: error_code.h:1091
static int order_classes(DB_OBJLIST **class_list, DB_OBJLIST **order_list, int conservative)
int collation_id
Definition: class_object.h:750
int ml_find(DB_OBJLIST *list, MOP mop)
Definition: work_space.c:4465
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
int db_attribute_is_shared(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1429
static void emit_domain_def(print_output &output_ctx, DB_DOMAIN *domains)
int create_filename_trigger(const char *output_dirname, const char *output_prefix, char *output_filename_p, const size_t filename_size)
static void emit_method_files(print_output &output_ctx, DB_OBJECT *class_)
int db_attribute_is_non_null(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1355
const int * db_constraint_prefix_length(DB_CONSTRAINT *constraint)
Definition: db_info.c:2089
const char * output_dirname
Definition: unloaddb.c:46
static bool emit_resolutions(print_output &output_ctx, DB_OBJECT *class_, const char *class_type)
SM_FOREIGN_KEY_ACTION update_action
Definition: class_object.h:482
int db_attribute_is_reverse_unique(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1328
static bool emit_all_attributes(print_output &output_ctx, DB_OBJECT *class_, const char *class_type, int *has_indexes, EMIT_STORAGE_ORDER storage_order)
static void emit_methfile_def(print_output &output_ctx, DB_METHFILE *methfile)
static void force_one_class(print_output &output_ctx, DB_OBJLIST **class_list, DB_OBJLIST **order_list)
void parser_free_parser(PARSER_CONTEXT *parser)
Definition: parse_tree.c:1240
static int has_dependencies(DB_OBJECT *class_, DB_OBJLIST *unordered, DB_OBJLIST *ordered, int conservative)
static bool emit_instance_attributes(print_output &output_ctx, DB_OBJECT *class_, const char *class_type, int *has_indexes, EMIT_STORAGE_ORDER storage_order)
const char * comment
Definition: class_object.h:542
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
const char * lang_get_collation_name(const int coll_id)
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
const char * tde_get_algorithm_name(TDE_ALGORITHM tde_algo)
Definition: tde.c:1694
#define SP_ATTR_DATA_TYPE
Definition: jsp_cl.h:52
PR_TYPE * pr_type_from_id(DB_TYPE id)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
int db_set_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:508
static void filter_system_classes(DB_OBJLIST **class_list)
DB_METHFILE * db_get_method_files(DB_OBJECT *obj)
Definition: db_info.c:2173
#define assert(x)
static int emit_schema(print_output &output_ctx, DB_OBJLIST *classes, int do_auth, DB_OBJLIST **vclass_list_has_using_index, EMIT_STORAGE_ORDER emit_storage_order)
static void emit_cycle_warning(print_output &output_ctx)
DB_CONSTRAINT_TYPE
Definition: dbtype_def.h:452
TDE_ALGORITHM
Definition: tde.h:71
static bool emit_methods(print_output &output_ctx, DB_OBJECT *class_, const char *class_type)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
int db_error_code(void)
Definition: db_admin.c:2143
#define ER_IT_DATA_OVERFLOW
Definition: error_code.h:505
DB_DOMAIN * db_method_arg_domain(DB_METHOD *method, int arg)
Definition: db_info.c:1671
PT_NODE ** parser_parse_string(PARSER_CONTEXT *parser, const char *buffer)
int create_filename_indexes(const char *output_dirname, const char *output_prefix, char *output_filename_p, const size_t filename_size)
unsigned is_desc
void db_objlist_free(DB_OBJLIST *list)
Definition: db_admin.c:2612
static DB_OBJLIST * get_ordered_classes(print_output &output_ctx, MOP *class_table)
DB_DOMAIN * db_method_return_domain(DB_METHOD *method)
Definition: db_info.c:1646
#define DOM_GET_ENUM_ELEM(dom, idx)
Definition: object_domain.h:44
const char * db_error_string(int level)
Definition: db_admin.c:2116
DB_OBJECT * db_domain_class(const DB_DOMAIN *domain)
Definition: db_macro.c:4030
#define DOM_GET_ENUM_ELEMS_COUNT(dom)
Definition: object_domain.h:42
const char * db_domain_raw_json_schema(const DB_DOMAIN *domain)
Definition: db_macro.c:4147
DB_SEQ * values
Definition: class_object.h:696
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
int db_resolution_isclass(DB_RESOLUTION *resolution)
Definition: db_info.c:1882
const char * db_query_spec_string(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:651
DB_OBJECT * db_get_object(const DB_VALUE *value)
#define TP_DOMAIN_TYPE(dom)
TP_DOMAIN * fi_domain
Definition: class_object.h:502
#define SP_ATTR_OWNER
Definition: jsp_cl.h:47
#define SP_ATTR_NAME
Definition: jsp_cl.h:40
SP_PARSER_CTX * parser
#define NULL
Definition: freelistheap.h:34
const char * db_method_function(DB_METHOD *method)
Definition: db_info.c:1606
#define NUMERIC_MAX_STRING_SIZE
const char * pr_type_name(DB_TYPE id)
#define SP_ATTR_ARGS
Definition: jsp_cl.h:43
static int create_filename(const char *output_dirname, const char *output_prefix, const char *suffix, char *output_filename_p, const size_t filename_size)
int sm_get_class_flag(MOP op, SM_CLASS_FLAG flag)
int au_export_grants(print_output &output_ctx, MOP class_mop)
SERIAL_VALUE_INDEX
#define err(fd,...)
Definition: porting.h:431
static void emit_partition_info(print_output &output_ctx, MOP clsobj)
int extract_indexes_to_file(extract_context &ctxt, const char *output_filename)
static bool has_vclass_domains(DB_OBJECT *vclass)
DB_OBJLIST * vclass_list_has_using_index
int ml_ext_add(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4877
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
int db_is_system_class(MOP op)
Definition: db_info.c:502
struct db_objlist * next
Definition: dbtype_def.h:442
static void emit_unique_def(print_output &output_ctx, DB_OBJECT *class_, const char *class_type)
int db_set_size(DB_SET *set)
Definition: db_set.c:557
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
char * input_filename
Definition: unloaddb.c:47
int pr_clear_value(DB_VALUE *value)
FILE * fopen_ex(const char *filename, const char *type)
Definition: util_common.c:322
DB_DOMAIN * db_attribute_domain(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1165
DB_METHOD * db_method_next(DB_METHOD *method)
Definition: db_info.c:1569
struct db_object * op
Definition: dbtype_def.h:443
static int emit_autoincrement_def(print_output &output_ctx, DB_ATTRIBUTE *attribute)
static void error(const char *msg)
Definition: gencat.c:331
RESOLUTION_QUALIFIER
DB_DEFAULT_EXPR_TYPE on_update_default_expr
Definition: class_object.h:452
const char * db_resolution_name(DB_RESOLUTION *resolution)
Definition: db_info.c:1843
SM_CLASS_CONSTRAINT * classobj_find_class_index(SM_CLASS *class_, const char *name)
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
char * numeric_db_value_print(const DB_VALUE *val, char *buf)
MOP au_get_class_owner(MOP classmop)
#define SP_ATTR_MODE
Definition: jsp_cl.h:53
#define AU_SELECT
Definition: authenticate.h:69
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define ER_INVALID_SERIAL_VALUE
Definition: error_code.h:987
const char * default_expr_format
Definition: dbtype_def.h:1206
static int export_serial(print_output &output_ctx)
#define AU_ENABLE(save)
Definition: authenticate.h:113
#define SP_ATTR_ARG_COMMENT
Definition: jsp_cl.h:54
SM_FOREIGN_KEY_ACTION delete_action
Definition: class_object.h:481
#define PRINT_IDENTIFIER(s)
Definition: unloaddb.h:58
#define strlen(s1)
Definition: intl_support.c:43
DB_CONSTRAINT_TYPE db_constraint_type(const DB_CONSTRAINT *constraint)
Definition: db_info.c:1978
void help_print_describe_comment(print_output &output_ctx, const char *comment)
Definition: object_print.c:716
const int * db_constraint_asc_desc(DB_CONSTRAINT *constraint)
Definition: db_info.c:2070
DB_RESOLUTION * db_get_resolutions(DB_OBJECT *obj)
Definition: db_info.c:1735
#define SP_ATTR_ARG_NAME
Definition: jsp_cl.h:50
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
int db_get(DB_OBJECT *object, const char *attpath, DB_VALUE *value)
Definition: db_obj.c:233
void ml_ext_free(DB_OBJLIST *list)
Definition: work_space.c:4806
bool required_class_only
Definition: unloaddb.c:60
DB_METHFILE * db_methfile_next(DB_METHFILE *methfile)
Definition: db_info.c:2201
DB_METHOD * db_get_class_methods(DB_OBJECT *obj)
Definition: db_info.c:1542
static void emit_attribute_def(print_output &output_ctx, DB_ATTRIBUTE *attribute, ATTRIBUTE_QUALIFIER qualifier)
DB_VALUE * db_attribute_default(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1209
void er_clear(void)
static void emit_class_owner(print_output &output_ctx, MOP class_)
#define TP_FLOATING_PRECISION_VALUE
DB_RESOLUTION * db_resolution_next(DB_RESOLUTION *resolution)
Definition: db_info.c:1799
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
DB_TYPE db_attribute_type(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1000
int create_filename_schema(const char *output_dirname, const char *output_prefix, char *output_filename_p, const size_t filename_size)
const char * db_resolution_alias(DB_RESOLUTION *resolution)
Definition: db_info.c:1862
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
DB_ATTRIBUTE * db_get_class_attributes(DB_OBJECT *obj)
Definition: db_info.c:939
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
DB_QUERY_SPEC * db_get_query_specs(DB_OBJECT *obj)
Definition: db_virt.c:608
int do_is_partitioned_subclass(int *is_partitioned, const char *classname, char *keyattr)
#define SP_ATTR_SP_TYPE
Definition: jsp_cl.h:41
SM_INDEX_STATUS index_status
Definition: class_object.h:544
DB_OBJLIST * db_get_all_objects(DB_OBJECT *op)
Definition: db_info.c:246
DB_OBJLIST * sm_fetch_all_classes(int external_list, DB_FETCH_MODE purpose)
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
DB_TYPE db_set_type(DB_SET *set)
Definition: db_set.c:683
#define INDEX_SUFFIX
Definition: unload_schema.c:65
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
#define TRIGGER_SUFFIX
Definition: unload_schema.c:64
int numeric_db_value_add(const DB_VALUE *dbv1, const DB_VALUE *dbv2, DB_VALUE *answer)
char * pt_print_query_spec_no_list(PARSER_CONTEXT *parser, const PT_NODE *node)
int collation_id
Definition: object_domain.h:92
const char * db_methfile_name(DB_METHFILE *methfile)
Definition: db_info.c:2219
static int emit_stored_procedure(print_output &output_ctx)
static void emit_index_def(print_output &output_ctx, DB_OBJECT *class_)
DB_VALUE * default_value
Definition: esql_cli.c:348
const char * db_method_name(DB_METHOD *method)
Definition: db_info.c:1587
const char * comment
Definition: class_object.h:758
int db_attribute_is_unique(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1228
#define SCHEMA_SUFFIX
Definition: unload_schema.c:63
int db_compile_and_execute_local(const char *CSQL_query, void *result, DB_QUERY_ERROR *query_error)
Definition: db_vdb.c:3068
static void emit_reverse_unique_def(print_output &output_ctx, DB_OBJECT *class_)
PT_NODE * parser_walk_tree(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE_WALK_FUNCTION pre_function, void *pre_argument, PT_NODE_WALK_FUNCTION post_function, void *post_argument)
const char * exec_name
static int emit_query_specs_has_using_index(print_output &output_ctx, DB_OBJLIST *vclass_list_has_using_index)
DB_METHOD * db_get_methods(DB_OBJECT *obj)
Definition: db_info.c:1513
char * classobj_describe_foreign_key_action(SM_FOREIGN_KEY_ACTION action)
Definition: class_object.c:748
const char * comment
Definition: class_object.h:467
ATTRIBUTE_QUALIFIER
Definition: unload_schema.c:89
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
static int emit_indexes(print_output &output_ctx, DB_OBJLIST *classes, int has_indexes, DB_OBJLIST *vclass_list_has_using_index)
int extract_classes(extract_context &ctxt, print_output &schema_output_ctx)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define SP_CLASS_NAME
Definition: jsp_cl.h:37
EMIT_STORAGE_ORDER
DB_DOMAIN * db_domain_set(const DB_DOMAIN *domain)
Definition: db_macro.c:4060
DB_OBJECT * db_resolution_class(DB_RESOLUTION *resolution)
Definition: db_info.c:1823
static bool emit_superclasses(print_output &output_ctx, DB_OBJECT *class_, const char *class_type)
void ml_ext_free_link(DB_OBJLIST *link)
Definition: work_space.c:4790
int tde_algorithm
Definition: class_object.h:767
const char * name
Definition: class_object.h:532
static void emit_resolution_def(print_output &output_ctx, DB_RESOLUTION *resolution, RESOLUTION_QUALIFIER qualifier)
DB_QUERY_SPEC * db_query_spec_next(DB_QUERY_SPEC *query_spec)
Definition: db_virt.c:632