File method_scan.cpp¶
File List > cubrid > src > method > method_scan.cpp
Go to the documentation of this file
/*
*
* 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.
*
*/
#include "method_scan.hpp"
#include "dbtype.h" /* db_value_* */
#include "list_file.h" /* qfile_ */
#include "object_representation.h" /* OR_ */
#include "pl_session.hpp"
#include "pl_signature.hpp"
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
namespace cubscan
{
namespace method
{
/* Notice: If a member included in a union has a constructor, it can lead to undefined behavior.
* Therefore, the constructor has been removed.
* If necessary, please use constructor() explicitly. */
void
scanner::constructor()
{
m_thread_p = nullptr;
m_method_group = nullptr;
m_list_id = nullptr;
m_arg_count = 0;
m_arg_dom_vector = nullptr;
m_arg_vector = nullptr;
m_dbval_list = nullptr;
memset (&m_scan_id, 0x00, sizeof (m_scan_id));
}
int
scanner::init (cubthread::entry *thread_p, PL_SIGNATURE_ARRAY_TYPE *sig_array, qfile_list_id *list_id)
{
// check initialized
if (m_thread_p != thread_p)
{
m_thread_p = thread_p;
}
if (m_method_group == nullptr) // signature is not initialized
{
m_method_group = new cubmethod::method_invoke_group (sig_array);
if (!m_method_group)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1,
(size_t) sizeof (cubmethod::method_invoke_group));
return ER_OUT_OF_VIRTUAL_MEMORY;
}
}
if (m_list_id == nullptr)
{
m_list_id = list_id;
int arg_count = m_arg_count = m_list_id->type_list.type_cnt;
if (!m_arg_vector)
{
m_arg_vector = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE) * arg_count);
}
if (!m_arg_dom_vector)
{
m_arg_dom_vector = (TP_DOMAIN **) db_private_alloc (thread_p, sizeof (TP_DOMAIN *) * arg_count);
}
for (int i = 0; i < arg_count; i++)
{
db_make_null (&m_arg_vector [i]);
TP_DOMAIN *domain = list_id->type_list.domp[i];
if (domain == NULL || domain->type == NULL)
{
return ER_FAILED;
}
m_arg_dom_vector[i] = domain;
}
}
if (m_dbval_list == nullptr)
{
m_dbval_list = (qproc_db_value_list *) db_private_alloc (thread_p,
sizeof (m_dbval_list[0]) * m_method_group->get_num_methods ());
if (m_dbval_list == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1,
(size_t) sizeof (m_dbval_list[0]) * m_method_group->get_num_methods ());
return ER_OUT_OF_VIRTUAL_MEMORY;
}
}
return NO_ERROR;
}
void
scanner::clear (bool is_final)
{
close_value_array ();
for (int i = 0; m_arg_vector && i < m_arg_count; i++)
{
db_value_clear (&m_arg_vector[i]);
db_make_null (&m_arg_vector[i]);
}
if (is_final)
{
if (m_method_group)
{
m_method_group->reset (true);
m_method_group->end ();
delete m_method_group;
m_method_group = nullptr; // will be destroyed by cubmethod::runtime_context
}
if (m_arg_vector)
{
db_private_free_and_init (m_thread_p, m_arg_vector);
}
if (m_arg_dom_vector)
{
// freeing elements is not required.
// TP_DOMAIN is managed by another module.
db_private_free_and_init (m_thread_p, m_arg_dom_vector);
}
}
}
int
scanner::open ()
{
int error = NO_ERROR;
error = qfile_open_list_scan (m_list_id, &m_scan_id);
// connect
m_method_group->begin ();
return error;
}
int
scanner::close ()
{
int error = NO_ERROR;
clear (false);
qfile_close_scan (m_thread_p, &m_scan_id);
return error;
}
SCAN_CODE
scanner::next_scan (val_list_node &vl)
{
SCAN_CODE scan_code = S_SUCCESS;
next_value_array (vl);
scan_code = get_single_tuple ();
int error = NO_ERROR;
std::vector<std::reference_wrapper<DB_VALUE>> arg_wrapper (m_arg_vector, m_arg_vector + m_arg_count);
if (scan_code == S_SUCCESS && (error = m_method_group->execute (arg_wrapper)) != NO_ERROR)
{
scan_code = S_ERROR;
}
if (scan_code == S_SUCCESS)
{
int num_methods = m_method_group->get_num_methods ();
for (int i = 0; i < num_methods; i++)
{
DB_VALUE *dbval_p = (DB_VALUE *) db_private_alloc (m_thread_p, sizeof (DB_VALUE));
if (dbval_p == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (DB_VALUE));
return S_ERROR;
}
db_make_null (dbval_p);
DB_VALUE &result = m_method_group->get_return_value (i);
db_value_clone (&result, dbval_p);
m_dbval_list[i].val = dbval_p;
db_value_clear (&result);
}
m_method_group->reset (false);
}
if (scan_code == S_ERROR)
{
// PL_SESSION *session = m_method_group->get_session ();
// if (session->is_interrupted ())
// {
// session->set_local_error_for_interrupt ();
// }
// else
if (error !=
ER_SM_INVALID_METHOD_ENV) /* FIXME: error possibly occured in builtin method, It should be handled at CAS */
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SP_EXECUTE_ERROR, 1, m_method_group->get_error_msg ().c_str ());
}
}
// clear
for (int i = 0; i < m_arg_count; i++)
{
db_value_clear (&m_arg_vector[i]);
db_make_null (&m_arg_vector[i]);
}
return scan_code;
}
int
scanner::close_value_array ()
{
db_private_free_and_init (m_thread_p, m_dbval_list);
return NO_ERROR;
}
void
scanner::next_value_array (val_list_node &vl)
{
qproc_db_value_list *dbval_list = m_dbval_list;
vl.val_cnt = m_method_group->get_num_methods ();
for (int n = 0; n < vl.val_cnt; n++)
{
dbval_list->val = nullptr;
dbval_list->next = dbval_list + 1;
dbval_list++;
}
m_dbval_list[vl.val_cnt - 1].next = NULL;
vl.valp = m_dbval_list;
}
SCAN_CODE
scanner::get_single_tuple ()
{
QFILE_TUPLE_RECORD tuple_record = { NULL, 0 };
SCAN_CODE scan_code = qfile_scan_list_next (m_thread_p, &m_scan_id, &tuple_record, PEEK);
if (scan_code == S_SUCCESS)
{
char *ptr;
int length;
OR_BUF buf;
for (int i = 0; i < m_list_id->type_list.type_cnt; i++)
{
QFILE_TUPLE_VALUE_FLAG flag = (QFILE_TUPLE_VALUE_FLAG) qfile_locate_tuple_value (tuple_record.tpl, i, &ptr, &length);
or_init (&buf, ptr, length);
DB_VALUE *value = &m_arg_vector [i];
TP_DOMAIN *domain = m_arg_dom_vector [i];
const PR_TYPE *pr_type = domain->type;
db_make_null (value);
if (flag == V_BOUND)
{
if (pr_type->data_readval (&buf, value, domain, -1, true, NULL, 0) != NO_ERROR)
{
scan_code = S_ERROR;
break;
}
}
else
{
/* If value is NULL, properly initialize the result */
db_value_domain_init (value, pr_type->id, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
}
return scan_code;
}
}
}