Skip to content

File db_info.c

File List > compat > db_info.c

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/*
 * db_info.c - API functions for accessing database information
 *             and browsing classes.
 */

#ident "$Id$"

#include "config.h"

#include "authenticate.h"
#include "boot_cl.h"
#include "class_object.h"
#include "db.h"
#include "dbtype.h"
#include "locator_cl.h"
#include "mem_block.hpp"
#include "network_interface_cl.h"
#include "object_accessor.h"
#include "object_primitive.h"
#include "object_print.h"
#include "object_printer.hpp"
#include "parser.h"
#include "schema_manager.h"
#include "schema_template.h"
#include "server_interface.h"
#include "set_object.h"
#include "storage_common.h"
#include "string_buffer.hpp"
#include "system_parameter.h"
#include "virtual_object.h"

#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

/*
 *  CLASS LOCATION
 */

/*
 * db_find_class_of_index() - Find the name of the class that has a given
 *    index (specified by its name and type)
 * return: class object or NULL on error
 * index_name(in):
 * index_type(in):
 *
 * note:
 *    Only constraint types that satisfy the DB_IS_CONSTRAINT_INDEX_FAMILY
 *    condition will be searched for.
 *    If several indexes with the same name and type are found, NULL is
 *    returned.
 */
DB_OBJECT *
db_find_class_of_index (const char *const index_name, const DB_CONSTRAINT_TYPE index_type)
{
  DB_OBJLIST *clslist = NULL;
  SM_CLASS *smcls = NULL;
  DB_OBJECT *retval = NULL;
  int found = 0;
  const SM_CONSTRAINT_TYPE smtype = SM_MAP_DB_INDEX_CONSTRAINT_TO_SM_CONSTRAINT (index_type);

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (index_name);

  if (!DB_IS_CONSTRAINT_INDEX_FAMILY (index_type))
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0);
      goto end;
    }

  for (found = 0, clslist = db_fetch_all_classes (DB_FETCH_READ); clslist != NULL; clslist = clslist->next)
    {
      if (au_fetch_class (clslist->op, &smcls, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
    {
      retval = NULL;
      goto end;
    }

      if (classobj_find_class_constraint (smcls->constraints, smtype, index_name))
    {
      retval = clslist->op;
      found++;
    }

      if (found > 1)
    {
      break;
    }
    }
  if (found == 0)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_SM_NO_INDEX, 1, index_name);
      retval = NULL;
    }
  else if (found > 1)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_SM_INDEX_AMBIGUOUS, 1, index_name);
      retval = NULL;
    }

  /* TODO should the list returned by db_fetch_all_classes be freed? */
end:
  return retval;
}

/*
 * db_find_class()- This function searchs for a class in the database with a
 *    given name
 * return : class object
 * name(in): class name
 */
DB_OBJECT *
db_find_class (const char *name)
{
  return db_find_class_with_purpose (name, false);
}

/*
 * db_find_class_with_purpose()- This function search for a class in the database
 *     with a given name
 * return : class object
 * name(in): class name
 * for_update(in): true, if search the class for update purpose
 */
DB_OBJECT *
db_find_class_with_purpose (const char *name, bool for_update)
{
  DB_OBJECT *retval;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (name);

  retval = sm_find_class_with_purpose (name, for_update);

  return retval;
}

/*
 * db_find_synonym()- This function search for a synonym in the database
 *     with a given name
 * return : synonym object
 * name(in): synonym name
 */
DB_OBJECT *
db_find_synonym (const char *name)
{
  DB_OBJECT *retval;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (name);

  retval = sm_find_synonym (name);

  return retval;
}

/*
 * db_get_synonym_target_name() - get target_name.
 *   return: output buffer pointer or NULL on error
 *   synonym(in): synonym object
 *   buf(out): output buffer
 *   buf_size(in): output buffer length
 */
char *
db_get_synonym_target_name (MOP synonym, char *buf, int buf_size)
{
  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (synonym);

  return sm_get_synonym_target_name (synonym, buf, buf_size);
}

/*
 * db_fetch_all_objects() - This function fetches all objects fo given class
 *    for given purpose.
 * return : list of objects
 * op(in): class
 * purpose(in): Fetch purpose
 *
 * note : This function was intended to support very early development,
 *    it should not be used in normal circumstances. This function could
 *    potentially bring in extremely large numbers of objects resulting in
 *    workspace overflow.
 */
DB_OBJLIST *
db_fetch_all_objects (DB_OBJECT * op, DB_FETCH_MODE purpose)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (op);

  purpose =
    ((purpose == DB_FETCH_READ) ? DB_FETCH_QUERY_READ : ((purpose == DB_FETCH_WRITE) ? DB_FETCH_QUERY_WRITE : purpose));

  /* This always allocates an external mop list ! */
  retval = sm_fetch_all_objects (op, purpose);

  return retval;
}

/*
 * db_fetch_all_classes() - This function fetches all classes for given purpose
 * return : an object list
 * purpose(in): Fetch purpose
 *
 * Note: Authorization checking is not performed at this level so there may be
 *    MOPs in the list that you can't actually access.
 */
DB_OBJLIST *
db_fetch_all_classes (DB_FETCH_MODE purpose)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();

  /* return external list of class MOPs */
  retval = sm_fetch_all_classes (1, purpose);

  return retval;
}

/*
 * db_fetch_base_classes: This returns the list of classes
 *    that have no super classes.
 * return : an object list
 * purpose(in): Fetch purpose
 *
 */
DB_OBJLIST *
db_fetch_base_classes (DB_FETCH_MODE purpose)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();

  retval = sm_fetch_all_base_classes (1, purpose);

  return retval;
}

/*
 * db_get_all_objects() - This function fetches a list of all of the instances
 *    of a given class
 * return : list of objects
 * op(in): class
 *
 * note : This function was intended to support very early development,
 *    it should not be used in normal circumstances. This function could
 *    potentially bring in extremely large numbers of objects resulting in
 *    workspace overflow.
 */
DB_OBJLIST *
db_get_all_objects (DB_OBJECT * op)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (op);

  retval = sm_fetch_all_objects (op, DB_FETCH_QUERY_READ);

  return retval;
}

/*
 * db_get_all_classes() - This fetches a list of all of the class objects
 *    currently defined in the database.
 * return : an object list
 *
 * note: Authorization checking is not performed at this level so there
 *    may be MOPs in the list that you can't actually access.
 */
DB_OBJLIST *
db_get_all_classes (void)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();

  retval = sm_fetch_all_classes (1, DB_FETCH_QUERY_READ);

  return retval;
}

/*
 * db_get_base_classes() - This function fetches the list of classes that have
 *    no super classes.
 * return : an object list
 */
DB_OBJLIST *
db_get_base_classes (void)
{
  DB_OBJLIST *retval;

  CHECK_CONNECT_NULL ();

  retval = sm_fetch_all_base_classes (1, DB_FETCH_QUERY_READ);

  return retval;
}

/*
 *  OBJECT PREDICATES
 */

/*
 * db_is_class() - This function is used to test if a particular object
 *    pointer (MOP) actually is a reference to a class object.
 * return :  < 0 if error, > 0 non-zero if object is a class, 0 otherwise
 * obj(in): a pointer to a class or instance
 *
 * note : If it can be detected that the MOP has been deleted, this will
 *    return zero as well.  This means that you can't simply use this to
 *    see if a MOP is an instance or not.
 */
int
db_is_class (MOP obj)
{
  SM_CLASS *class_ = NULL;
  int result = 0;

  CHECK_CONNECT_ZERO ();

  if (obj == NULL)
    {
      return 0;
    }
  result = locator_is_class (obj, DB_FETCH_READ);
  if (result < 0)
    {
      return result;
    }
  if (!result)
    {
      return 0;
    }
  result = au_fetch_class_force (obj, &class_, AU_FETCH_READ);
  if (result != NO_ERROR)
    {
      return result;
    }

  assert (class_ != NULL);
  if (sm_get_class_type (class_) != SM_CLASS_CT)
    {
      return 0;
    }

  return 1;
}

/*
 * db_is_any_class() - This function is used to test if a particular object
 *    pointer (MOP) actually is a reference to a {class|vclass|view}
 *    object.
 * return : non-zero if object is a {class|vclass|view}
 * obj(in): a pointer to a class or instance
 * note : If it can be detected that the MOP has been deleted, this will return
 *    zero as well.  Note that this means that you can't simply use this to see
 *    if a MOP is an instance or not.
 */
int
db_is_any_class (MOP obj)
{
  SM_CLASS *class_ = NULL;
  int result = 0;

  CHECK_CONNECT_ZERO ();

  if (obj == NULL)
    {
      return 0;
    }
  result = locator_is_class (obj, DB_FETCH_READ);
  if (result < 0)
    {
      return result;
    }
  if (!result)
    {
      return 0;
    }
  result = au_fetch_class_force (obj, &class_, AU_FETCH_READ);
  if (result != NO_ERROR)
    {
      return result;
    }

  assert (class_ != NULL);

  return 1;
}

/*
 * db_is_instance() - This function is used to test if an object MOP
 *    references an instance of a class rather than a class itself.
 * return : non-zero if object is an instance
 * obj(in): a pointer to a class or instance
 */
int
db_is_instance (MOP obj)
{
  int retval;

  CHECK_CONNECT_ZERO ();

  retval = obj_isinstance (obj);

  return retval;
}

/*
 * db_is_instance_of() - This function is used to test if "obj" is an
 *    instance of "class".
 * return: non-zero if its an instance of the class
 * obj(in): an instance being tested
 * class(in): the class we're interested in
 *
 * note : For this to be true, the class must be exactly the class the instance
 *    was instantiated from, you cannot use this to see if an instance has
 *    a super class somewhere in its inheritance hierarchy.
 */
int
db_is_instance_of (MOP obj, MOP class_)
{
  int status = 0;

  CHECK_CONNECT_ZERO ();

  if (obj != NULL && class_ != NULL)
    {
      status = obj_is_instance_of (obj, class_);
      if (status == -1)
    {
      /* access error, convert this to zero */
      status = 0;
    }
    }

  return status;
}

/*
 * db_is_subclass() - This function is used to test if the classmop is a
 *    subclass of the supermop.
 * return : 1 if classmop is subclass of supermop, 0 if classmop is not
 *      subclass if supermop, negative for errors.
 * classmop(in): pointer to the class that might be a subclass
 * supermop(in): pointer to the super class
 */
int
db_is_subclass (MOP classmop, MOP supermop)
{
  int retval;

  CHECK_CONNECT_ZERO ();
  CHECK_2ARGS_ZERO (classmop, supermop);

  retval = sm_is_subclass (classmop, supermop);

  return retval;
}

/*
 * db_is_superclass() - This function is used to test if the supermop is a
 *    superclass of the classmop.
 * return : 1 if classmop is subclass of supermop, 0 if classmop is not
 *      subclass if supermop, negative for errors.
 * supermop(in): class pointer
 * classmop(in): class pointer
 */
int
db_is_superclass (MOP supermop, MOP classmop)
{
  int retval;

  retval = db_is_subclass (classmop, supermop);

  return retval;
}

/*
 * db_is_partition () - This function is used to test if classobj is a
 *    partition of superobj
 * return : greater than 0 if true, 0 if false, less than 0 for error
 * classobj (in) : partition candidate
 * superobj (in) : partitioned class
 */
int
db_is_partition (DB_OBJECT * classobj, DB_OBJECT * superobj)
{
  int retval;

  CHECK_CONNECT_ZERO ();
  CHECK_1ARG_MINUSONE (classobj);

  retval = sm_is_partition (classobj, superobj);

  return retval;
}

/*
 * db_is_system_class() - This function is a convenience function to determine
 *    if a class is one of the system defined classes or a user defined class.
 * return: true if op is system class
 * op(in): class pointer
 */
int
db_is_system_class (MOP op)
{
  int retval;

  CHECK_CONNECT_ZERO ();
  CHECK_1ARG_ZERO (op);

  retval = sm_is_system_class (op);

  return retval;
}

/*
 * db_is_deleted() - This function is used to determine whether or not the
 *    database object associated with an object handle has been deleted.
 * return : status code
 *      0 = The object is not deleted.
 *     >0 = The object is deleted.
 *     <0 = An error was detected, the state of the object is unknown and
 *           an error code is available through db_error_code().
 * obj(in): object to examine
 *
 * note : It performs this test in a more optimal way than db_lock_read() by
 *    avoiding authorization checking, and testing the workspace state before
 *    calling the more expensive fetch & lock function. For speed, we're not
 *    checking for connections unless we have to attempt to fetch the object.
 *
 */
int
db_is_deleted (DB_OBJECT * obj)
{
  int error;

  CHECK_1ARG_ERROR (obj);

  if (WS_IS_DELETED (obj))
    {
      return 1;
    }

  /* If we have obtained any lock except X_LOCK, that means it is real. However deleted bit is off and to hold X_LOCK
   * does not guarantee it exists, wever deleted bit is off and to hold X_LOCK does not guarantee it exists, for
   * instance, trigger action do server-side delete and trigger does not know it. Therefore we need to check it if we
   * hold X_LOCK on the object. */
  if (NULL_LOCK < obj->lock && obj->lock < X_LOCK)
    {
      return 0;
    }

  /* couldn't figure it out from the MOP hints, we'll have to try fetching it, note that we're acquiring a read lock
   * here, this may be bad if we really intend to update the object. */
  error = obj_lock (obj, 0);

  if (!error)
    {
      return 0;
    }

  /* if this is the deleted object error, then its deleted, the test for the MOP deleted flag should be unnecessary but
   * be safe. */
  if (error == ER_HEAP_UNKNOWN_OBJECT || WS_IS_DELETED (obj))
    {
      return 1;
    }

  return error;
}

/*
 *  CLASS INFORMATION
 */

/*
 * db_get_class() - When given an object, this function returns the
 *    corresponding class object. This function can be used in cases where
 *    it is not known whether an object is an instance or a class, but in
 *    either case the class is desired. If the object is already a class
 *    object, it is simply returned.
 * return : a class pointer
 * obj(in): an instance or class
 *
 * note : Unlike most other functions that accept DB_OBJECT as an argument,
 *    this function does not check for select authorization on the class.
 *    Even users without authorization to examine the contents of a class
 *    can get a pointer to the class object by calling this function.
 */
DB_OBJECT *
db_get_class (MOP obj)
{
  DB_OBJECT *retval;

  CHECK_CONNECT_NULL ();

  retval = sm_get_class (obj);

  return retval;
}

/*
 * db_get_class_name() - This function is used to get the name of a class
 *    object and return it as a C string. A NULL is returned if an error
 *    is encountered
 * return : name of the class
 * class(in): class object
 */
const char *
db_get_class_name (DB_OBJECT * class_)
{
  const char *retval;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (class_);

  retval = sm_get_ch_name (class_);

  return (retval);
}

/*
 * db_get_superclasses() - This function returns a list of all of the super
 *    classes defined for a class.
 * return : an object list
 * obj(in): a class or instance
 *
 * note : This list may be NULL if the class has no super classes.
 *    Only the immediate super classes are returned.
 */
DB_OBJLIST *
db_get_superclasses (DB_OBJECT * obj)
{
  DB_OBJLIST *supers;
  SM_CLASS *class_;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  supers = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      supers = class_->inheritance;
      if (supers == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }


  return (supers);
}

/*
 * db_get_subclasses() - This function returns a list of the immediate
 *    subclasses of the specified class.
 * return : an object list
 * obj(in): class or instance
 */
DB_OBJLIST *
db_get_subclasses (DB_OBJECT * obj)
{
  DB_OBJLIST *subs;
  SM_CLASS *class_;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  subs = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      subs = class_->users;
      if (subs == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return (subs);
}

/*
 * db_class_has_instance() -
 * return : an object list
 * classobj(in): class object
 */
int
db_class_has_instance (DB_OBJECT * classobj)
{
  DB_OBJLIST *sub_list;
  int has_instance;

  sub_list = db_get_subclasses (classobj);
  if (sub_list)
    {
      for (; sub_list; sub_list = sub_list->next)
    {
      has_instance = db_class_has_instance (sub_list->op);
      if (has_instance < 0)
        {
          return has_instance;
        }
      else if (has_instance > 0)
        {
          return 1;
        }
    }
    }
  else
    {
      return heap_has_instance (sm_get_ch_heap (classobj), WS_OID (classobj), 1);
    }

  return 0;
}

/*
 * db_get_type_name() - This function maps a type identifier constant to a
 *    printable string containing the type name.
 * return : string containing type name (or NULL if error)
 * type_id(in): an integer type identifier (DB_TYPE enumeration)
 */
const char *
db_get_type_name (DB_TYPE type_id)
{
  const char *name = NULL;

  name = pr_type_name (type_id);
  if (name == NULL)
    {
      name = "unknown primitive type identifier";
    }

  return (name);
}

/*
 * db_type_from_string() - This function checks a string to determine whether
 *    it matches a type.
 * return : a type identifier constant
 * name(in): a type name
 */
DB_TYPE
db_type_from_string (const char *name)
{
  DB_TYPE typeid_ = DB_TYPE_UNKNOWN;
  const PR_TYPE *type;
  DB_DOMAIN *domain = (DB_DOMAIN *) 0;

  if (name != NULL)
    {
      type = pr_find_type (name);
      if ((type == NULL) && (db_Connect_status == DB_CONNECTION_STATUS_CONNECTED))
    {
      domain = pt_string_to_db_domain (name, NULL);
      if (domain)
        {
          type = domain->type;
        }
    }
      if (type != NULL)
    {
      typeid_ = type->id;
      if (type->id != DB_TYPE_VARIABLE && type->id != DB_TYPE_SUB)
        {
          typeid_ = type->id;
        }
    }
      if (domain)
    {
      tp_domain_free (domain);
    }
    }

  return (typeid_);
}

/*
 *  ATTRIBUTE ACCESSORS
 */

/*
 * db_get_attribute() - This function returns a structure that describes the
 *    definition of an attribute.
 * return : an attribute descriptor
 * obj(in): class or instance
 * name(in): attribute name
 *
 * note : returned structure can be examined by using the db_attribute_
 *        functions.
 */
DB_ATTRIBUTE *
db_get_attribute (DB_OBJECT * obj, const char *name)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *att;

  CHECK_CONNECT_NULL ();
  CHECK_2ARGS_NULL (obj, name);

  att = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      att = classobj_find_attribute (class_, name, 0);
      if (att == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ATTRIBUTE, 1, name);
    }
    }

  return ((DB_ATTRIBUTE *) att);
}

/*
 * db_get_attribute_by_name() - This function returns a structure that
 *    describes the definition of an attribute.
 * return : an attribute descriptor
 * class_name(in): class name
 * name(in): attribute name
 *
 * note : returned structure can be examined by using the db_attribute_
 *        functions.
 */
DB_ATTRIBUTE *
db_get_attribute_by_name (const char *class_name, const char *attribute_name)
{
  DB_OBJECT *db_obj = NULL;
  if (class_name == NULL || attribute_name == NULL)
    {
      return NULL;
    }

  db_obj = db_find_class (class_name);
  if (db_obj == NULL)
    {
      return NULL;
    }

  return db_get_attribute (db_obj, attribute_name);
}


/*
 * db_get_shared_attribute() - This function returns a structure that describes
 *    the definition of an shared attribute.
 * return : attribute descriptor
 * obj(in): class or instance
 * name(in): shared attribute name
 */
DB_ATTRIBUTE *
db_get_shared_attribute (DB_OBJECT * obj, const char *name)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *att;

  CHECK_CONNECT_NULL ();
  CHECK_2ARGS_NULL (obj, name);

  att = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      att = classobj_find_attribute (class_, name, 0);
      if (att == NULL || att->header.name_space != ID_SHARED_ATTRIBUTE)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ATTRIBUTE, 1, name);
    }
    }

  return ((DB_ATTRIBUTE *) att);
}

/*
 * db_get_class_attribute() - This function returns a structure that describes
 *    the definition of an class attribute.
 * return : attribute descriptor
 * obj(in): class or instance
 * name(in): class attribute name
 */
DB_ATTRIBUTE *
db_get_class_attribute (DB_OBJECT * obj, const char *name)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *att;

  CHECK_CONNECT_NULL ();
  CHECK_2ARGS_NULL (obj, name);

  att = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      att = classobj_find_attribute (class_, name, 1);
      if (att == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ATTRIBUTE, 1, name);
    }
    }

  return ((DB_ATTRIBUTE *) att);
}

/*
 * db_get_attributes() - This function Returns descriptors for all of the
 *    attributes of a class. The attribute descriptors are maintained in
 *    a linked list so you can iterate through them using the db_attribute_next
 *    function.
 * return : attribute descriptor (in a list)
 * obj(in): class or instance
 */
DB_ATTRIBUTE *
db_get_attributes (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *atts;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  atts = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      /* formerly returned the non-shared attribute list */
      /* atts = class_->attributes; */
      atts = class_->ordered_attributes;
      if (atts == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_ATTRIBUTE *) atts);
}

/*
 * db_get_class_attributes() - This function returns descriptors for all of the
 *    class attribute of a class. The descriptors are maintained on a linked
 *    list so you can iterate through them using the db_attribute_next function
 * return : attribute descriptor list
 * obj(in): class or instance
 */
DB_ATTRIBUTE *
db_get_class_attributes (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *atts;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  atts = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      atts = class_->class_attributes;
      if (atts == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_ATTRIBUTE *) atts);
}

/*
 * db_get_ordered_attributes() - This function returns descriptors for the
 *    instance and shared attributes of a class.  The attributes are ordered
 *    in definition order.
 * return : attribute descriptor (in a list)
 * obj(in): class or instance
 *
 * note : To traverse this list, you must use db_attribute_order_next
 *    rather than db_attribute_next.
 */
DB_ATTRIBUTE *
db_get_ordered_attributes (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_ATTRIBUTE *atts;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);


  atts = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      atts = class_->ordered_attributes;
      if (atts == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_ATTRIBUTE *) atts);
}

/*
 * db_attribute_type() - This function returns the basic type constant
 *    for an attribute.
 * return : type identifier constant
 * attribute(in): attribute descriptor
 */
DB_TYPE
db_attribute_type (DB_ATTRIBUTE * attribute)
{
  DB_TYPE type = DB_TYPE_NULL;

  if (attribute != NULL)
    {
      type = attribute->type->id;
    }

  return (type);
}

/*
 * db_attribute_next() - This function is used to iterate through a list of
 *    attribute descriptors such as that returned from the db_get_attributes()
 *    function.
 * return : attribute descriptor (or NULL if end of list)
 * attribute(in): attribute descriptor
 */
DB_ATTRIBUTE *
db_attribute_next (DB_ATTRIBUTE * attribute)
{
  DB_ATTRIBUTE *next = NULL;

  if (attribute != NULL)
    {
      if (attribute->header.name_space == ID_CLASS_ATTRIBUTE)
    {
      next = (DB_ATTRIBUTE *) attribute->header.next;
    }
      else
    {
      next = attribute->order_link;
    }
    }

  return (next);
}

/*
 * db_attribute_ordered_next() - This function is used to iterate through a
 *    list of attribute descriptors that was returned by
 *    db_get_ordered_attributes.
 * return : attribute descriptor (or NULL if end of list)
 * attribute(in): attribute descriptor
 */
DB_ATTRIBUTE *
db_attribute_ordered_next (DB_ATTRIBUTE * attribute)
{
  DB_ATTRIBUTE *next = NULL;

  if (attribute != NULL)
    {
      next = attribute->order_link;
    }

  return (next);
}

/*
 * db_attribute_name() - This function gets the name string from an attribute.
 * return : C string containing name
 * attribute(in): attribute descriptor
 */
const char *
db_attribute_name (DB_ATTRIBUTE * attribute)
{
  const char *name = NULL;

  if (attribute != NULL)
    {
      name = attribute->header.name;
    }

  return (name);
}

/*
 * db_attribute_comment() - This function gets the comment string from an attribute.
 * return : C string containing comment
 * attribute(in): attribute descriptor
 */
const char *
db_attribute_comment (DB_ATTRIBUTE * attribute)
{
  const char *comment = NULL;

  if (attribute != NULL)
    {
      comment = attribute->comment;
    }

  return (comment);
}

/*
 * db_attribute_length() - This function gets the precision from an
 *    attribute if any.
 * return : precision of attribute
 * attribute(in): attribute descriptor
 */
int
db_attribute_length (DB_ATTRIBUTE * attribute)
{
  int length = 0;

  if (attribute && attribute->domain)
    {
      length = attribute->domain->precision;
    }

  return (length);
}

/*
 * db_attribute_id() - This function returns the ID for an attribute.
 * return : internal attribute identifier
 * attribute(in): attribute descriptor
 *
 * note : The internal attribute identifier is guaranteed to be unique
 *    for all of the attributes of this class, it has little utility to
 *    an application program but might be useful for fast searching etc.
 */
int
db_attribute_id (DB_ATTRIBUTE * attribute)
{
  int id = -1;

  if (attribute != NULL)
    {
      id = attribute->id;
    }

  return (id);
}

/*
 * db_attribute_order() - This function returns the position of an attribute
 *    within the attribute list for the class. This list is ordered according
 *    to the original class definition.
 * return : internal attribute identifier
 * attribute(in): attribute descriptor
 */
int
db_attribute_order (DB_ATTRIBUTE * attribute)
{
  int order = -1;

  if (attribute != NULL)
    {
      order = attribute->order;
    }

  return (order);
}

/*
 * db_attribute_domain() - This function returns the complete domain descriptor
 *    for an attribute.
 * return : domain descriptor
 * attribute(in): attribute descriptor
 *
 * note : The domain information is examined using the db_domain_ functions.
 */
DB_DOMAIN *
db_attribute_domain (DB_ATTRIBUTE * attribute)
{
  DB_DOMAIN *domain = NULL;

  if (attribute != NULL)
    {
      domain = attribute->domain;

      /* always filter the domain before returning to the higher levels */
      sm_filter_domain (domain, NULL);
    }

  return (domain);
}

/*
 * db_attribute_class() - This function returns a pointer to the class that is
 *    the source of this attribute in the class hierarchy. This can be used to
 *    see if an attribute was inherited from another class or if it was defined
 *    against the current class.
 * return : a pointer to a class
 * attribute(in): an attribute descriptor
 */
DB_OBJECT *
db_attribute_class (DB_ATTRIBUTE * attribute)
{
  DB_OBJECT *class_mop = NULL;

  if (attribute != NULL)
    {
      class_mop = attribute->class_mop;
    }

  return (class_mop);
}

/*
 * db_attribute_default() - This function returns the default value of
 *    an attribute. If the attribute was a shared or class attribute this
 *    will actually be the current value.
 * return : a value container
 * attribute(in): attribute descriptor
 */
DB_VALUE *
db_attribute_default (DB_ATTRIBUTE * attribute)
{
  DB_VALUE *value = NULL;

  if (attribute != NULL)
    {
      value = &attribute->default_value.value;
    }

  return (value);
}

/*
 * db_attribute_is_unique() - This function tests the status of the UNIQUE
 *    integrity constraint for an attribute.
 * return : non-zero if unique is defined
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_unique (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (con->type == SM_CONSTRAINT_UNIQUE || con->type == SM_CONSTRAINT_PRIMARY_KEY)
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_primary_key() - This function tests the status of the
 *    PRIMARY KEY integrity constraint for an attribute.
 * return : non-zero if primary key is defined
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_primary_key (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (con->type == SM_CONSTRAINT_PRIMARY_KEY)
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_foreign_key() - This function tests the status of the
 *    FOREIGN KEY integrity constraint for an attribute.
 * return : non-zero if foreign key is defined
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_foreign_key (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (con->type == SM_CONSTRAINT_FOREIGN_KEY)
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_auto_increment() - This funciton tests if attribute is
 *    defined as auto increment
 * return : non-zero if auto increment is defined.
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_auto_increment (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      status = (attribute->flags & SM_ATTFLAG_AUTO_INCREMENT) ? 1 : 0;
    }

  return (status);
}

/*
 * db_attribute_is_reverse_unique() - This function tests the status of the
 *    reverse UNIQUE for an attribute.
 * return : non-zero if reverse unique is defined.
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_reverse_unique (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (con->type == SM_CONSTRAINT_REVERSE_UNIQUE)
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_non_null() - This function tests the status of the NON_NULL
 *    integrity constraint for an attribute.
 * return : non-zero if non_null is defined.
 * attribute(in): attribute descriptor
 */
int
db_attribute_is_non_null (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      status = attribute->flags & SM_ATTFLAG_NON_NULL;
    }

  return (status);
}

/*
 * db_attribute_is_indexed() - This function tests to see if an attribute is
 *    indexed. Similar to db_is_indexed but works directly off the attribute
 *    descriptor structure.
 * return: non-zero if attribute is indexed
 * attributre(in): attribute descriptor
 */
int
db_attribute_is_indexed (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (SM_IS_CONSTRAINT_INDEX_FAMILY (con->type))
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_reverse_indexed() - This function tests to see if an attribute is
 *    reverse_indexed.
 * return: non-zero if attribute is indexed
 * attributre(in): attribute descriptor
 */
int
db_attribute_is_reverse_indexed (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      SM_CONSTRAINT *con;

      for (con = attribute->constraints; con != NULL && !status; con = con->next)
    {
      if (SM_IS_CONSTRAINT_REVERSE_INDEX_FAMILY (con->type))
        {
          status = 1;
        }
    }
    }

  return (status);
}

/*
 * db_attribute_is_shared() - This function tests to see if an attribute was
 *    defined as SHARED.
 * return: non-zero if shared is defined
 * attribute: attribute descriptor
 */
int
db_attribute_is_shared (DB_ATTRIBUTE * attribute)
{
  int status = 0;

  if (attribute != NULL)
    {
      status = attribute->header.name_space == ID_SHARED_ATTRIBUTE;
    }

  return (status);
}

/*
 *  METHOD ACCESSORS
 */

/*
 * db_get_method() - This function returns a method descriptor that contains
 *  information about the method. The descriptor can be examined using the
 *  db_method_ functions.
 * return : method descriptor
 * obj(in): class or instance
 * name(in): method name
 */
DB_METHOD *
db_get_method (DB_OBJECT * obj, const char *name)
{
  SM_CLASS *class_;
  SM_METHOD *method;

  CHECK_CONNECT_NULL ();
  CHECK_2ARGS_NULL (obj, name);

  method = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      method = classobj_find_method (class_, name, 0);
      if (method == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_METHOD, 1, name);
    }
    }

  return ((DB_METHOD *) method);
}

/*
 * db_get_class_method() - This function returns a method descriptor for the
 *    class method that contains information about the method. The descriptor
 *    can be examined using the db_method_ functions.
 * return : method descriptor
 * obj(in): class or instance
 * name(in): class method name
 */
DB_METHOD *
db_get_class_method (DB_OBJECT * obj, const char *name)
{
  SM_CLASS *class_;
  SM_METHOD *method;

  CHECK_CONNECT_NULL ();
  CHECK_2ARGS_NULL (obj, name);

  method = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      method = classobj_find_method (class_, name, 1);
      if (method == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_METHOD, 1, name);
    }
    }

  return ((DB_METHOD *) method);
}

/*
 * db_get_methods() - This function returns a list of descriptors for all of
 *    the methods defined for a class. The list can be traversed using the
 *    db_method_next() function.
 * return : method descriptor list
 * obj(in): class or instance
 */
DB_METHOD *
db_get_methods (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_METHOD *methods;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  methods = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      methods = class_->methods;
      if (methods == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_METHOD *) methods);
}

/*
 * db_get_class_methods() - This function returns a list of descriptors for all
 *    of the class methods defined for a class. The list can be traversed by
 *    using the db_method_next() function.
 * return : method descriptor list
 * obj(in): class or instance
 */
DB_METHOD *
db_get_class_methods (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_METHOD *methods;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  methods = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      methods = class_->class_methods;
      if (methods == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_METHOD *) methods);
}

/*
 * db_method_next() - This function gets the next method descriptor in the list
 * return : method descriptor(or NULL if at end of list)
 * method(in): method descriptor
 */
DB_METHOD *
db_method_next (DB_METHOD * method)
{
  DB_METHOD *next = NULL;

  if (method != NULL)
    {
      next = (DB_METHOD *) method->header.next;
    }

  return (next);
}

/*
 * db_method_name() - This function gets the method name from a descriptor.
 * return: method name string
 * method(in): method descriptor
 */
const char *
db_method_name (DB_METHOD * method)
{
  const char *name = NULL;

  if (method != NULL)
    {
      name = method->header.name;
    }

  return (name);
}

/*
 * db_method_function() - This function gets the function name that
 *    implements a method.
 * return: method function name
 * method(in): method descriptor
 */
const char *
db_method_function (DB_METHOD * method)
{
  const char *function = NULL;

  if (method != NULL && method->signatures != NULL && method->signatures->function_name != NULL)
    {
      function = method->signatures->function_name;
    }

  return (function);
}

/*
 * db_method_class() - This function gets the class that was the source of this
 *    method in the class hierarchy. This can be used to determine if a method
 *    was inherited or defined against the current class.
 * return : class pointer
 * method(in): method descriptor
 */
DB_OBJECT *
db_method_class (DB_METHOD * method)
{
  DB_OBJECT *class_mop = NULL;

  if (method != NULL)
    {
      class_mop = method->class_mop;
    }

  return (class_mop);
}

/*
 * db_method_return_domain() - This function Returns the domain descriptor for
 *    the return value of a method.  This may be NULL if no signature
 *    information was specified when the method was defined.
 * return : domain descriptor list
 * method(in): method descriptor
 */
DB_DOMAIN *
db_method_return_domain (DB_METHOD * method)
{
  DB_DOMAIN *domain = NULL;

  if (method != NULL && method->signatures != NULL && method->signatures->value != NULL)
    {
      domain = method->signatures->value->domain;
      sm_filter_domain (domain, NULL);
    }

  return (domain);
}

/*
 * db_method_arg_domain() - This function returns the domain descriptor for one
 *    of the method arguments.
 * return : domain descriptor list
 * method(in): method descriptor
 * arg(in): argument index
 * note : This is formatted the same way as an attribute domain list and may be
 *    hierarchical if the domain entries are sets. This list may be NULL if
 *    there was no signature definition in the original CUBRID definition of
 *    the method.
 */
DB_DOMAIN *
db_method_arg_domain (DB_METHOD * method, int arg)
{
  DB_DOMAIN *domain = NULL;
  DB_METHARG *marg;

  if (method != NULL && method->signatures != NULL && arg <= method->signatures->num_args)
    {
      /* argument zero is return value. Note that this behavior eliminates the need for db_method_return_value() */
      if (arg == 0)
    {
      if (method->signatures->value != NULL)
        {
          domain = method->signatures->value->domain;
          sm_filter_domain (domain, NULL);
        }
    }
      else
    {
      for (marg = method->signatures->args; marg != NULL && domain == NULL; marg = marg->next)
        {
          if (marg->index == arg)
        {
          domain = marg->domain;
          sm_filter_domain (domain, NULL);
        }
        }
    }
    }

  return (domain);
}

/*
 * db_method_arg_count() - This function returns the number of arguments
 *    defined for a method.
 * return : number of arguments defined for a method.
 * method(in): method descriptor
 */
int
db_method_arg_count (DB_METHOD * method)
{
  int count = 0;

  if (method != NULL && method->signatures != NULL)
    {
      count = method->signatures->num_args;
    }

  return (count);
}

/*
 *  CONFLICT RESOLUTION ACCESSORS
 */

/*
 * db_get_resolutions() - This function returns a list of all of the
 *    instance-level resolution descriptors for a class. This list includes
 *    resolutions for both attributes and methods. The list can be traversed
 *    with the db_resolution_next() function.
 * return: resolution descriptor
 * obj(in): class or instance
 */
DB_RESOLUTION *
db_get_resolutions (DB_OBJECT * obj)
{
  SM_RESOLUTION *res;
  SM_CLASS *class_;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  res = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {

      res = class_->resolutions;
      while (res != NULL && res->name_space == ID_CLASS)
    res = res->next;

      if (res == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_RESOLUTION *) res);
}

/*
 * db_get_class_resolutions() - This function returns a list of all the
 *    class-level resolution descriptors for a class.
 * return : resolution descriptor
 * obj(in): class or instance
 */
DB_RESOLUTION *
db_get_class_resolutions (DB_OBJECT * obj)
{
  SM_RESOLUTION *res;
  SM_CLASS *class_;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  res = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {

      res = class_->resolutions;
      while (res != NULL && res->name_space != ID_CLASS)
    {
      res = res->next;
    }

      if (res == NULL)
    er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }

  return ((DB_RESOLUTION *) res);
}

/*
 * db_resolution_next() - This function gets the next resolution descriptor in
 *    the list.
 * return : resolution descriptor (or NULL if at end of list)
 * resolution(in): resolution descriptor
 */
DB_RESOLUTION *
db_resolution_next (DB_RESOLUTION * resolution)
{
  DB_RESOLUTION *next = NULL;
  SM_NAME_SPACE name_space;

  /* advance to the next resolution of the current type */
  if (resolution != NULL)
    {
      name_space = resolution->name_space;
      next = resolution->next;
      while (next != NULL && next->name_space != name_space)
    next = next->next;
    }

  return (next);
}

/*
 * db_resolution_class() - Returns the class that was referenced in
 *    the resolution definition (through the "inherit from" statement in SQL).
 * return : class pointer
 * resolution(in) : resolution descriptor
 */
DB_OBJECT *
db_resolution_class (DB_RESOLUTION * resolution)
{
  DB_OBJECT *class_mop = NULL;


  if (resolution != NULL)
    {
      class_mop = resolution->class_mop;
    }

  return (class_mop);
}

/*
 * db_resolution_name() - This function returns the name of the attribute or
 *    method in the resolution definition.
 * return : C string
 * resolution: resolution descriptor
 */
const char *
db_resolution_name (DB_RESOLUTION * resolution)
{
  const char *name = NULL;

  if (resolution != NULL)
    {
      name = resolution->name;
    }

  return (name);
}

/*
 * db_resolution_alias() - This function returns the alias name if one was
 *    defined. The alias name is optional and may be NULL.
 * return : C string (or NULL if no alias)
 * resolution(in): resolution descriptor
 */
const char *
db_resolution_alias (DB_RESOLUTION * resolution)
{
  const char *alias = NULL;

  if (resolution != NULL)
    {
      alias = resolution->alias;
    }

  return (alias);
}

/*
 * db_resolution_isclass() - This function can be called when you are uncertain
 *    whether the resolution descriptor in question is an instance- or
 *    class-level resolution.
 * return : non-zero if this is a class level resolution
 * resolution(in): resolution descriptor
 */
int
db_resolution_isclass (DB_RESOLUTION * resolution)
{
  int isclass = 0;

  if (resolution != NULL && resolution->name_space == ID_CLASS)
    {
      isclass = 1;
    }

  return (isclass);
}


/*
 *  CONSTRAINT ACCESSORS
 */

/*
 * db_get_constraints() - This function returns descriptors for all of the
 *    constraints of a class. The constraint descriptors are maintained in
 *    a linked list so that you can iterate through them using the
 *    db_constraint_next() function.
 * return : constraint descriptor list (or NULL if the object does not
 *          contain any constraints)
 * obj(in): class or instance
 */
DB_CONSTRAINT *
db_get_constraints (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  SM_CLASS_CONSTRAINT *constraints;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  constraints = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      constraints = class_->constraints;
      if (constraints == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_CONSTRAINT *) constraints);
}


/*
 * db_constraint_next() - This function is used to iterate through a list of
 *    constraint descriptors returned by the db_get_constraint() function.
 * return:constraint descriptor (or NULL if end of list)
 * constraint(in): constraint descriptor
 */
DB_CONSTRAINT *
db_constraint_next (DB_CONSTRAINT * constraint)
{
  DB_CONSTRAINT *next = NULL;

  if (constraint != NULL)
    {
      next = constraint->next;
    }

  return (next);
}

/*
 * db_constraint_find_primary_key()- This function is used to return primary key constraint
 * return : constraint descriptor (or NULL if not found)
 * constraint(in): constraint descriptor
 */
DB_CONSTRAINT *
db_constraint_find_primary_key (DB_CONSTRAINT * constraint)
{
  while (constraint != NULL)
    {
      if (constraint->type == SM_CONSTRAINT_PRIMARY_KEY)
    {
      break;
    }

      constraint = db_constraint_next (constraint);
    }

  return constraint;
}


/*
 * db_constraint_type()- This function is used to return the type of constraint
 * return : internal constraint identifier
 * constraint(in): constraint descriptor
 */
DB_CONSTRAINT_TYPE
db_constraint_type (const DB_CONSTRAINT * constraint)
{
  DB_CONSTRAINT_TYPE type = DB_CONSTRAINT_INDEX;

  if (constraint != NULL)
    {
      if (constraint->type == SM_CONSTRAINT_UNIQUE)
    {
      type = DB_CONSTRAINT_UNIQUE;
    }
      else if (constraint->type == SM_CONSTRAINT_INDEX)
    {
      type = DB_CONSTRAINT_INDEX;
    }
      else if (constraint->type == SM_CONSTRAINT_NOT_NULL)
    {
      type = DB_CONSTRAINT_NOT_NULL;
    }
      else if (constraint->type == SM_CONSTRAINT_REVERSE_UNIQUE)
    {
      type = DB_CONSTRAINT_REVERSE_UNIQUE;
    }
      else if (constraint->type == SM_CONSTRAINT_REVERSE_INDEX)
    {
      type = DB_CONSTRAINT_REVERSE_INDEX;
    }
      else if (constraint->type == SM_CONSTRAINT_PRIMARY_KEY)
    {
      if (prm_get_bool_value (PRM_ID_COMPAT_PRIMARY_KEY))
        {
          type = DB_CONSTRAINT_UNIQUE;
        }
      else
        {
          type = DB_CONSTRAINT_PRIMARY_KEY;
        }
    }
      else if (constraint->type == SM_CONSTRAINT_FOREIGN_KEY)
    {
      type = DB_CONSTRAINT_FOREIGN_KEY;
    }
    }

  return (type);
}

/*
 * db_constraint_name() - This function returns the name string
 *    for a constraint.
 * return : C string containing name
 * constraint(in): constraint descriptor
 */
const char *
db_constraint_name (DB_CONSTRAINT * constraint)
{
  const char *name = NULL;

  if (constraint != NULL)
    {
      name = constraint->name;
    }

  return (name);
}


/*
 * db_constraint_attributes() - This function returns an array of attributes
 *    that belong to the constraint. Each element of the NULL-terminated array
 *    is a pointer to an DB_ATTRIBUTE structure.
 * return : NULL terminated array of attribute structure pointers
 * constraint: constraint descriptor
 */
DB_ATTRIBUTE **
db_constraint_attributes (DB_CONSTRAINT * constraint)
{
  SM_ATTRIBUTE **atts = NULL;

  if (constraint != NULL)
    {
      atts = constraint->attributes;
    }

  return ((DB_ATTRIBUTE **) atts);
}

/*
 * db_constraint_asc_desc() - This function returns an array of asc/desc info
 * return : non-NULL terminated integer array
 * constraint: constraint descriptor
 */
const int *
db_constraint_asc_desc (DB_CONSTRAINT * constraint)
{
  const int *asc_desc = NULL;

  if (constraint != NULL)
    {
      asc_desc = constraint->asc_desc;
    }

  return asc_desc;
}

/*
 * db_constraint_prefix_length() - This function returns an array of
 *                prefix length info
 * return non-NULL terminated integer array
 * constraint: constraint descriptor
*/
const int *
db_constraint_prefix_length (DB_CONSTRAINT * constraint)
{
  const int *attrs_prefix_length = NULL;

  if (constraint != NULL)
    {
      attrs_prefix_length = constraint->attrs_prefix_length;
    }

  return attrs_prefix_length;
}

/*
 * db_constraint_index() - This function returns the BTID of index constraint.
 * return : C string containing name
 * constraint(in): constraint descriptor
 */
BTID *
db_constraint_index (DB_CONSTRAINT * constraint, BTID * index)
{
  if (constraint != NULL)
    {
      BTID_COPY (index, &(constraint->index_btid));
    }

  return index;
}

/*
 * db_get_foreign_key_ref_class() - This function returns the MOP of foreign
 *    key referenced class.
 * return : referenced class MOP
 * constraint(in): constraint descriptor
 */
DB_OBJECT *
db_get_foreign_key_ref_class (DB_CONSTRAINT * constraint)
{
  DB_OBJECT *ref_clsop = NULL;

  if (constraint != NULL && constraint->type == SM_CONSTRAINT_FOREIGN_KEY)
    {
      ref_clsop = ws_mop (&(constraint->fk_info->ref_class_oid), NULL);
    }
  return ref_clsop;
}

/*
 * db_get_foreign_key_ref_class() - This function returns the action name
 *    of foreign key.
 * return : C string of action name
 * constraint(in): constraint descriptor
 * type(in) : DELETE or UPDATE action
 */
const char *
db_get_foreign_key_action (DB_CONSTRAINT * constraint, DB_FK_ACTION_TYPE type)
{
  const char *act = NULL;

  if (constraint != NULL && constraint->type == SM_CONSTRAINT_FOREIGN_KEY)
    {
      if (type == DB_FK_DELETE)
    {
      act = classobj_describe_foreign_key_action (constraint->fk_info->delete_action);
    }
      else if (type == DB_FK_UPDATE)
    {
      act = classobj_describe_foreign_key_action (constraint->fk_info->update_action);
    }
    }
  return act;
}


/*
 * METHOD FILE & LOADER COMMAND ACCESSORS
 */

/*
 * db_get_method_files() - Returns a list of method file descriptors
 *    for a class.
 * return : method file descriptor list
 * obj(in): class or instance
 */
DB_METHFILE *
db_get_method_files (DB_OBJECT * obj)
{
  SM_METHOD_FILE *files;
  SM_CLASS *class_;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  files = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      files = class_->method_files;
      if (files == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return ((DB_METHFILE *) files);
}

/*
 * db_methfile_next() - This function returns the next method file descriptor
 *    in the list or NULL if you're at the end of the list.
 * return : method file descriptor
 * methfile(in): method file descriptor
 */
DB_METHFILE *
db_methfile_next (DB_METHFILE * methfile)
{
  DB_METHFILE *next = NULL;

  if (methfile != NULL)
    {
      next = methfile->next;
    }

  return (next);
}

/*
 * db_methfile_name() - This function returns the name of the method file.
 * return : C string of method file name.
 * methfile(in): method file descriptor
 */
const char *
db_methfile_name (DB_METHFILE * methfile)
{
  const char *name = NULL;

  if (methfile != NULL)
    {
      name = methfile->name;
    }

  return (name);
}

/*
 * db_get_loader_commands() - This function returns the dynamic loader command
 *    string defined for a class. If no loader commands are defined, NULL is
 *    returned.
 * return: C string
 * obj(in): class or instance
 */
const char *
db_get_loader_commands (DB_OBJECT * obj)
{
  SM_CLASS *class_;
  const char *commands;

  CHECK_CONNECT_NULL ();
  CHECK_1ARG_NULL (obj);

  commands = NULL;
  if (au_fetch_class (obj, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
    {
      commands = class_->loader_commands;
      if (commands == NULL)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_NO_COMPONENTS, 0);
    }
    }

  return (commands);
}

/*
 * OBJLIST ACCESSORS
 */

/*
 * db_objlist_next() - This returns the "next" field of the DB_OBJLIST
 *    structure. This must be used to traverse an object list.
 * return : next list element or NULL if at the end
 * link(in): list link to follow
 */
DB_OBJLIST *
db_objlist_next (DB_OBJLIST * link)
{
  DB_OBJLIST *next = NULL;

  if (link != NULL)
    {
      next = link->next;
    }

  return next;
}

/*
 * db_objlist_object() - This function returns the object of the DB_OBJLIST
 *    structure.
 * return : object in this list element
 * link(in): object list element
 */
DB_OBJECT *
db_objlist_object (DB_OBJLIST * link)
{
  DB_OBJECT *obj = NULL;

  if (link != NULL)
    {
      obj = link->op;
    }

  return obj;
}

/*
 * db_get_class_num_objs_and_pages() -
 * return : error code
 * classmop(in): class object
 * approximation(in):
 * nobjs(out): number of objects in this classmop
 * npages(out): number of pages in this classmop
 */
int
db_get_class_num_objs_and_pages (DB_OBJECT * classmop, int approximation, int *nobjs, int *npages)
{
  HFID *hfid;
  int error;

  if (classmop == NULL)
    {
      return ER_FAILED;
    }
  hfid = sm_get_ch_heap (classmop);
  if (hfid == NULL)
    {
      return ER_FAILED;
    }

  if (HFID_IS_NULL (hfid))
    {
      /* If heap is invalid, the class wouldn't have a heap file like virtual class */
      *nobjs = 0;
      *npages = 0;
      return NO_ERROR;
    }

  error = heap_get_class_num_objects_pages (hfid, approximation, nobjs, npages);

  return error;
}

/*
 * db_get_class_privilege() -
 * return : error code
 * classmop(in):
 * auth(out):
 */
int
db_get_class_privilege (DB_OBJECT * mop, unsigned int *auth)
{
  if (mop == NULL)
    {
      return ER_FAILED;
    }
  return au_get_class_privilege (mop, auth);
}

/*
 * db_get_btree_statistics() -
 * return : error code
 * cons(in):
 * num_leaf_pages(out):
 * num_total_pages(out):
 * num_keys(out):
 * height(out):
 */
int
db_get_btree_statistics (DB_CONSTRAINT * cons, int *num_leaf_pages, int *num_total_pages, int *num_keys, int *height)
{
  BTID *btid;
  BTREE_STATS stat;
  int errcode;
  int ctype;

  ctype = db_constraint_type (cons);
  if (!DB_IS_CONSTRAINT_INDEX_FAMILY (ctype))
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0);
      return ER_OBJ_INVALID_ARGUMENTS;
    }

  btid = &cons->index_btid;
  assert_release (!BTID_IS_NULL (btid));

  stat.keys = 0;
  stat.pkeys_size = 0;      /* do not request pkeys info */
  stat.pkeys = NULL;

  errcode = btree_get_statistics (btid, &stat);
  if (errcode != NO_ERROR)
    {
      return errcode;
    }

  *num_leaf_pages = stat.leafs;
  *num_total_pages = stat.pages;
  *num_keys = stat.keys;
  *height = stat.height;

  return NO_ERROR;
}

/*
 * db_get_schema_def_dbval() - get "show create table" string for a given class
 * return : error code
 * result(out):
 * name_val(in):
 */
int
db_get_schema_def_dbval (DB_VALUE * result, DB_VALUE * name_val)
{
  DB_TYPE type;
  const char *table_name;
  int error_status = NO_ERROR;

  assert (result != (DB_VALUE *) NULL);
  if (DB_IS_NULL (name_val))
    {
      PRIM_SET_NULL (result);
      return NO_ERROR;
    }

  type = DB_VALUE_DOMAIN_TYPE (name_val);
  if (QSTR_IS_ANY_CHAR (type))
    {
      table_name = db_get_string (name_val);
      assert (table_name != NULL);

      MOP class_op = sm_find_class (table_name);
      if (class_op == NULL)
    {
      goto error;
    }

      if (db_is_class (class_op) == false)
    {
      error_status = ER_OBJ_NOT_A_CLASS;
      goto error;
    }

      string_buffer sb;
      object_printer printer (sb);
      printer.describe_class (class_op);
      db_make_string_copy (result, sb.get_buffer ());
    }
  else
    {
      error_status = ER_QSTR_INVALID_DATA_TYPE;
      goto error;
    }

  return error_status;

error:
  PRIM_SET_NULL (result);
  if (prm_get_bool_value (PRM_ID_RETURN_NULL_ON_FUNCTION_ERRORS))
    {
      return NO_ERROR;
    }
  else if (error_status == NO_ERROR)
    {
      error_status = er_errid ();
    }

  return error_status;
}