Skip to content

File xasl_spawner.cpp

File List > cubrid > src > xasl > xasl_spawner.cpp

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.
 *
 */

/*
 * xasl_spawner.cpp
 */

#include "xasl_spawner.hpp"

#include <cassert>
#include <memory>

#include "dbtype.h"
#include "object_primitive.h"
#include "xasl.h"

// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"

namespace cubxasl
{
  spawner::spawner (cubthread::entry &thread_ref)
    : m_thread_ref (thread_ref)
  {
  }

  spawner::~spawner ()
  {
    for (auto &it : m_cached_ptrs)
      {
    if (it.second.deleter != nullptr)
      {
        it.second.deleter (&m_thread_ref, it.second.ptr, it.second.count);
      }
      }

    m_cached_ptrs.clear();
  }

  PRED_EXPR *
  spawner::spawn (const PRED_EXPR *src)
  {
    PRED_EXPR *dest = nullptr;

    dest = find (src);
    if (dest != nullptr )
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* union */
    switch (src->type)
      {
      case T_PRED:
    if (spawner::spawn (&src->pe.m_pred, &dest->pe.m_pred) != NO_ERROR)
      {
        return nullptr;
      }
    break;

      case T_EVAL_TERM:
    if (spawner::spawn (&src->pe.m_eval_term, &dest->pe.m_eval_term) != NO_ERROR)
      {
        return nullptr;
      }
    break;

      case T_NOT_TERM:
    dest->pe.m_not_term = spawner::spawn (src->pe.m_not_term);
    break;

      default:
    assert (false);
    er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_XASLNODE, 0);
    return nullptr;
      }

    dest->type = src->type;

    return dest;
  }

  int
  spawner::spawn (const PRED *src, PRED *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->lhs = spawner::spawn (src->lhs);
    dest->rhs = spawner::spawn (src->rhs);
    dest->bool_op = src->bool_op;

    return er_errid ();
  }

  int
  spawner::spawn (const EVAL_TERM *src, EVAL_TERM *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    /* union*/
    switch (src->et_type)
      {
      case T_COMP_EVAL_TERM:
    if (spawner::spawn (&src->et.et_comp, &dest->et.et_comp) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      case T_ALSM_EVAL_TERM:
    if (spawner::spawn (&src->et.et_alsm, &dest->et.et_alsm) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      case T_LIKE_EVAL_TERM:
    if (spawner::spawn (&src->et.et_like, &dest->et.et_like) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      case T_RLIKE_EVAL_TERM:
    if (spawner::spawn (&src->et.et_rlike, &dest->et.et_rlike) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      default:
    assert (false);
    er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_XASLNODE, 0);
    return ER_QPROC_INVALID_XASLNODE;
      }

    dest->et_type = src->et_type;

    return er_errid ();
  }

  int
  spawner::spawn (const COMP_EVAL_TERM *src, COMP_EVAL_TERM *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->lhs = spawner::spawn (src->lhs);
    dest->rhs = spawner::spawn (src->rhs);
    dest->rel_op = src->rel_op;
    dest->type = src->type;

    return er_errid ();
  }

  int
  spawner::spawn (const ALSM_EVAL_TERM *src, ALSM_EVAL_TERM *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->elem = spawner::spawn (src->elem);
    dest->elemset = spawner::spawn (src->elemset);
    dest->eq_flag = src->eq_flag;
    dest->rel_op = src->rel_op;
    dest->item_type = src->item_type;

    return er_errid ();
  }

  int
  spawner::spawn (const LIKE_EVAL_TERM *src, LIKE_EVAL_TERM *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->src = spawner::spawn (src->src);
    dest->pattern = spawner::spawn (src->pattern);
    dest->esc_char = spawner::spawn (src->esc_char);

    return er_errid ();
  }

  int
  spawner::spawn (const RLIKE_EVAL_TERM *src, RLIKE_EVAL_TERM *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->src = spawner::spawn (src->src);
    dest->pattern = spawner::spawn (src->pattern);
    dest->case_sensitive = spawner::spawn (src->case_sensitive);

    /* TODO: unsupported */
    dest->compiled_regex = spawn (src->compiled_regex);

    return er_errid ();
  }

  cub_compiled_regex *
  spawner::spawn (const cub_compiled_regex *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  REGU_VARIABLE *
  spawner::spawn (const REGU_VARIABLE *src)
  {
    REGU_VARIABLE *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    if (spawn (src, dest) != NO_ERROR)
      {
    return nullptr;
      }

    return dest;
  }

  int
  spawner::spawn (const REGU_VARIABLE *src, REGU_VARIABLE *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->type = src->type;
    dest->flags = src->flags;
    dest->domain = tp_domain_copy (src->domain, true);  /* TODO: check freed */
    dest->original_domain = dest->domain;
    dest->vfetch_to = spawn (src->vfetch_to);

    /* TODO: unsupported */
    assert_release_error (src->xasl == nullptr);
    dest->xasl = nullptr;

    /* union */
    switch (src->type)
      {
      case TYPE_DBVAL:
    /* always returns NO_ERROR */
    pr_clone_value (&src->value.dbval, &dest->value.dbval);
    break;

      case TYPE_CONSTANT:
      case TYPE_ORDERBY_NUM:
    dest->value.dbvalptr = spawn (src->value.dbvalptr);
    break;

      case TYPE_INARITH:
      case TYPE_OUTARITH:
    dest->value.arithptr = spawn (src->value.arithptr);
    break;

      case TYPE_ATTR_ID:
      case TYPE_CLASS_ATTR_ID:
      case TYPE_SHARED_ATTR_ID:
    if (spawn (&src->value.attr_descr, &dest->value.attr_descr) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      case TYPE_POSITION:
    if (spawn (&src->value.pos_descr, &dest->value.pos_descr) != NO_ERROR)
      {
        return er_errid ();
      }
    break;

      case TYPE_LIST_ID:
    dest->value.srlist_id = spawn (src->value.srlist_id);
    break;

      case TYPE_POS_VALUE:
    dest->value.val_pos = src->value.val_pos;
    break;

      case TYPE_OID:
      case TYPE_CLASSOID:
    /* TODO: unsupported */
    assert_release_error (false);
    return er_errid ();

      case TYPE_FUNC:
    dest->value.funcp = spawn (dest->value.funcp);
    break;

      case TYPE_REGUVAL_LIST:
    dest->value.reguval_list = spawn (src->value.reguval_list);
    break;

      case TYPE_REGU_VAR_LIST:
    dest->value.regu_var_list = spawn (src->value.regu_var_list);
    break;

      case TYPE_SP:
    dest->value.sp_ptr = spawn (src->value.sp_ptr);
    break;

      default:
    assert (false);
    er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_XASLNODE, 0);
    return ER_QPROC_INVALID_XASLNODE;
      }

    return er_errid ();
  }

  DB_VALUE *
  spawner::spawn (const DB_VALUE *src)
  {
    DB_VALUE *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* always returns NO_ERROR */
    pr_clone_value (src, dest);

    return dest;
  }

  ARITH_TYPE *
  spawner::spawn (const ARITH_TYPE *src)
  {
    ARITH_TYPE *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    dest->domain = tp_domain_copy (src->domain, true);  /* TODO: check freed */
    dest->original_domain = dest->domain;
    dest->value = spawn (src->value);
    dest->leftptr = spawn (src->leftptr);
    dest->rightptr = spawn (src->rightptr);
    dest->thirdptr = spawn (src->thirdptr);
    dest->opcode = src->opcode;
    dest->misc_operand = src->misc_operand;

    /* ref: stx_build_arith_type */
    switch (src->opcode)
      {
      case T_IF:
      case T_CASE:
      case T_DECODE:
      case T_PREDICATE:
    dest->pred = spawn (src->pred);
    break;

      default:
    assert_release_error (src->pred == nullptr);
    dest->pred = nullptr;
    break;
      }

    dest->rand_seed = spawn (src->rand_seed);

    return dest;
  }

  struct drand48_data *
  spawner::spawn (const struct drand48_data *src)
  {
    struct drand48_data *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    memcpy (dest, src, sizeof (struct drand48_data));

    return dest;
  }

  int
  spawner::spawn (const ATTR_DESCR *src, ATTR_DESCR *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->id = src->id;
    dest->type = src->type;

    /* TODO: unsupported */
    dest->cache_attrinfo = spawn (src->cache_attrinfo);

    /* TODO: unsupported */
    assert_release_error (src->cache_dbvalp == nullptr);
    dest->cache_dbvalp = nullptr;

    return er_errid ();
  }

  HEAP_CACHE_ATTRINFO *
  spawner::spawn (const HEAP_CACHE_ATTRINFO *src)
  {
    HEAP_CACHE_ATTRINFO *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    dest->class_oid = src->class_oid;
    dest->last_cacheindex = src->last_cacheindex;
    dest->read_cacheindex = src->read_cacheindex;

    /* TODO: unsupported */
    dest->last_classrepr = spawn (src->last_classrepr);
    dest->read_classrepr = spawn (src->read_classrepr);

    dest->inst_oid = src->inst_oid;
    dest->inst_chn = src->inst_chn;
    dest->num_values = src->num_values;

    assert_release_error (find (src->values, src->num_values) == nullptr);
    dest->values = alloc (src->values, src->num_values);
    if (dest->values != nullptr)
      {
    for (int i = 0; i < src->num_values; i++)
      {
        if (spawn (&src->values[i], &dest->values[i]) != NO_ERROR)
          {
        return nullptr;
          }
      }
      }

    return dest;
  }

  OR_CLASSREP *
  spawner::spawn (const OR_CLASSREP *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  int
  spawner::spawn (const HEAP_ATTRVALUE *src, HEAP_ATTRVALUE *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->attrid = src->attrid;
    dest->state = src->state;
    dest->do_increment = src->do_increment;
    dest->attr_type = src->attr_type;

    /* TODO: unsupported */
    dest->last_attrepr = spawn (src->last_attrepr);
    dest->read_attrepr = spawn (src->read_attrepr);

    pr_clone_value (&src->dbvalue, &dest->dbvalue);

    return er_errid ();
  }

  OR_ATTRIBUTE *
  spawner::spawn (const OR_ATTRIBUTE *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  int
  spawner::spawn (const QFILE_TUPLE_VALUE_POSITION *src, QFILE_TUPLE_VALUE_POSITION *dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->dom = tp_domain_copy (src->dom, true);    /* TODO: check freed */
    dest->original_domain = dest->dom;
    dest->pos_no = src->pos_no;

    return er_errid ();
  }

  QFILE_SORTED_LIST_ID *
  spawner::spawn (const QFILE_SORTED_LIST_ID *src)
  {
    QFILE_SORTED_LIST_ID *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* TODO: unsupported */
    dest->list_id = spawn (src->list_id);

    dest->sorted = src->sorted;

    return dest;
  }

  QFILE_LIST_ID *
  spawner::spawn (const QFILE_LIST_ID *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  FUNCTION_TYPE *
  spawner::spawn (const FUNCTION_TYPE *src)
  {
    FUNCTION_TYPE *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    dest->value = spawn (src->value);
    dest->operand = spawn (src->operand);
    dest->ftype = src->ftype;

    /* TODO: unsupported */
    dest->tmp_obj = spawn (src->tmp_obj);

    return dest;
  }

  function_tmp_obj *
  spawner::spawn (const function_tmp_obj *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  REGU_VALUE_LIST *
  spawner::spawn (const REGU_VALUE_LIST *src)
  {
    REGU_VALUE_LIST *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    const REGU_VALUE_ITEM *current = src->regu_list;
    REGU_VALUE_ITEM **tail = &dest->regu_list;
    int i = 0;

    while (current != nullptr && i < src->count)
      {
    /* ref: stx_build_regu_value_list*/
    switch (current->value->type)
      {
      case TYPE_DBVAL:
      case TYPE_INARITH:
      case TYPE_POS_VALUE:
        assert (false);
        er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_XASLNODE, 0);
        return nullptr;

      default:
        /* fall through */
        break;
      }

    REGU_VALUE_ITEM *item = spawn (current);
    if (item == nullptr)
      {
        return nullptr;
      }

    *tail = item;
    tail = &item->next;

    current = current->next;
    i++;
      }

    assert_release_error (i == src->count);

    dest->current_value = dest->regu_list;
    dest->count = src->count;

    return dest;
  }

  REGU_VALUE_ITEM *
  spawner::spawn (const REGU_VALUE_ITEM *src)
  {
    REGU_VALUE_ITEM *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    dest->value = spawn (src->value);
    dest->next = nullptr;

    return dest;
  }

  REGU_VARIABLE_LIST
  spawner::spawn (const REGU_VARIABLE_LIST src)
  {
    REGU_VARIABLE_LIST current = src;
    int count = 0;

    while (current != nullptr)
      {
    count++;
    current = current->next;
      }
    current = src;

    /* ref: stx_restore_regu_variable_list */
    REGU_VARIABLE_LIST dest = nullptr;

    dest = find (src, count);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src, count);
    if (dest == nullptr)
      {
    return nullptr;
      }

    REGU_VARIABLE_LIST *tail = &dest;
    int i = 0;

    while (current != nullptr && i < count)
      {
    REGU_VARIABLE_LIST item = &dest[i];

    if (spawn (&current->value, &item->value) != NO_ERROR)
      {
        return nullptr;
      }

    *tail = item;
    tail = &item->next;

    current = current->next;
    i++;
      }

    assert_release_error (i == count);

    return dest;
  }

  SP_TYPE *
  spawner::spawn (const SP_TYPE *src)
  {
    SP_TYPE *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* TODO: unsupported */
    dest->sig = spawn (src->sig);

    dest->args = spawn (src->args);
    dest->value = spawn (src->value);

    return dest;
  }

  PL_SIGNATURE_TYPE *
  spawner::spawn (const PL_SIGNATURE_TYPE *src)
  {
    /* TODO: unsupported */
    assert_release_error (src == nullptr);
    return nullptr;
  }

  VAL_LIST *
  spawner::spawn (const VAL_LIST *src)
  {
    VAL_LIST *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* ref: stx_build_val_list */
    assert_release_error (find (src->valp, src->val_cnt) == nullptr);
    dest->valp = alloc (src->valp, src->val_cnt);
    if (dest->valp == nullptr)
      {
    return nullptr;
      }

    QPROC_DB_VALUE_LIST current = src->valp;
    QPROC_DB_VALUE_LIST *tail = &dest->valp;
    int i = 0;

    while (current != nullptr && i < src->val_cnt)
      {
    QPROC_DB_VALUE_LIST item = &dest->valp[i];

    if (spawn (current, item) != NO_ERROR)
      {
        return nullptr;
      }

    *tail = item;
    tail = &item->next;

    current = current->next;
    i++;
      }

    assert_release_error (i == src->val_cnt);

    dest->val_cnt = src->val_cnt;

    return dest;
  }

  int
  spawner::spawn (const QPROC_DB_VALUE_LIST src, QPROC_DB_VALUE_LIST dest)
  {
    if (!is_valid_argument (src, dest))
      {
    return er_errid ();
      }

    dest->next = nullptr;
    dest->val = spawn (src->val);
    dest->dom = tp_domain_copy (src->dom, true);    /* TODO: check freed */

    return er_errid ();
  }

  VAL_DESCR *
  spawner::spawn (const VAL_DESCR *src)
  {
    VAL_DESCR *dest = nullptr;

    dest = find (src);
    if (dest != nullptr)
      {
    return dest;
      }

    dest = alloc (src);
    if (dest == nullptr)
      {
    return nullptr;
      }

    /* ref: xqmgr_execute_query */
    assert_release_error (find (src->dbval_ptr, src->dbval_cnt) == nullptr);
    dest->dbval_ptr = alloc (src->dbval_ptr, src->dbval_cnt);
    if (dest->dbval_ptr != nullptr)
      {
    for (int i = 0; i < src->dbval_cnt; i++)
      {
        /* always returns NO_ERROR */
        pr_clone_value (&src->dbval_ptr[i], &dest->dbval_ptr[i]);
      }
      }

    dest->dbval_cnt = src->dbval_cnt;
    dest->sys_datetime = src->sys_datetime;
    dest->sys_epochtime = src->sys_epochtime;
    dest->lrand = src->lrand;
    dest->drand = src->drand;

    /* TODO: unsupported */
#if 0
    assert_release_error (src->xasl_state == nullptr);
#endif
    dest->xasl_state = NULL;

    return dest;
  }

  bool
  spawner::is_valid_argument (const void *src, const void *dest)
  {
    if (src == nullptr)
      {
    return false;
      }

    if (dest == nullptr)
      {
    assert_release_error (false);
    return false;
      }

    return true;
  }
};