File access_json_table.cpp¶
File List > cubrid > src > xasl > access_json_table.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.
*
*/
//
// access_json_table.cpp - implementation of structures required to access json table spec type.
//
#include "access_json_table.hpp"
#include "db_json.hpp"
#include "dbtype.h"
#include "error_code.h"
#include "error_manager.h"
#include "memory_private_allocator.hpp"
#include "memory_reference_store.hpp"
#include "object_primitive.h"
#include <cassert>
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
namespace cubxasl
{
namespace json_table
{
int
column::trigger_on_error (const JSON_DOC &input, const TP_DOMAIN_STATUS &status_cast, db_value &value_out)
{
(void) pr_clear_value (&value_out);
(void) db_make_null (&value_out);
switch (m_on_error.m_behavior)
{
case JSON_TABLE_RETURN_NULL:
er_clear ();
return NO_ERROR;
case JSON_TABLE_THROW_ERROR:
{
cubmem::private_unique_ptr<char> unique_ptr_json_body (db_json_get_raw_json_body_from_document (&input), NULL);
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_JSON_TABLE_ON_ERROR_INCOMP_DOMAIN, 4,
unique_ptr_json_body.get (), m_path, m_column_name,
pr_type_name (TP_DOMAIN_TYPE (m_domain)));
return ER_JSON_TABLE_ON_ERROR_INCOMP_DOMAIN;
}
case JSON_TABLE_DEFAULT_VALUE:
assert (m_on_error.m_default_value != NULL);
er_clear ();
if (pr_clone_value (m_on_error.m_default_value, &value_out) != NO_ERROR)
{
assert (false);
}
return NO_ERROR;
default:
assert (false);
return ER_FAILED;
}
}
int
column::trigger_on_empty (db_value &value_out)
{
(void) pr_clear_value (&value_out);
(void) db_make_null (&value_out);
switch (m_on_empty.m_behavior)
{
case JSON_TABLE_RETURN_NULL:
return NO_ERROR;
case JSON_TABLE_THROW_ERROR:
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_JSON_TABLE_ON_EMPTY_ERROR, 1, m_column_name);
return ER_JSON_TABLE_ON_EMPTY_ERROR;
case JSON_TABLE_DEFAULT_VALUE:
assert (m_on_empty.m_default_value != NULL);
if (pr_clone_value (m_on_empty.m_default_value, &value_out) != NO_ERROR)
{
assert (false);
}
return NO_ERROR;
default:
assert (false);
return ER_FAILED;
}
}
column::column (void)
{
init ();
}
void
column::init ()
{
m_domain = NULL;
m_path = NULL;
m_column_name = NULL;
m_output_value_pointer = NULL;
m_function = json_table_column_function::JSON_TABLE_EXTRACT;
m_on_error.m_default_value = NULL;
m_on_error.m_behavior = json_table_column_behavior_type::JSON_TABLE_RETURN_NULL;
m_on_empty.m_default_value = NULL;
m_on_empty.m_behavior = json_table_column_behavior_type::JSON_TABLE_RETURN_NULL;
}
int
column::evaluate_extract (const JSON_DOC &input)
{
int error_code = NO_ERROR;
JSON_DOC_STORE docp;
TP_DOMAIN_STATUS status_cast = TP_DOMAIN_STATUS::DOMAIN_COMPATIBLE;
error_code = db_json_extract_document_from_path (&input, m_path, docp);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
assert (db_value_is_null (m_output_value_pointer));
return ER_FAILED;
}
if (docp.is_null ())
{
error_code = trigger_on_empty (*m_output_value_pointer);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
}
return error_code;
}
// clear previous output_value
pr_clear_value (m_output_value_pointer);
db_make_json_from_doc_store_and_release (*m_output_value_pointer, docp);
status_cast = tp_value_cast (m_output_value_pointer, m_output_value_pointer, m_domain, false);
if (status_cast != TP_DOMAIN_STATUS::DOMAIN_COMPATIBLE)
{
error_code = trigger_on_error (input, status_cast, *m_output_value_pointer);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
}
}
return error_code;
}
int
column::evaluate_exists (const JSON_DOC &input)
{
int error_code = NO_ERROR;
bool result = false;
TP_DOMAIN_STATUS status_cast = TP_DOMAIN_STATUS::DOMAIN_COMPATIBLE;
error_code = db_json_contains_path (&input, std::vector<std::string> (1, m_path), false, result);
if (error_code != NO_ERROR)
{
ASSERT_ERROR ();
assert (db_value_is_null (m_output_value_pointer));
return ER_FAILED;
}
db_make_short (m_output_value_pointer, result ? 1 : 0);
status_cast = tp_value_cast (m_output_value_pointer, m_output_value_pointer, m_domain, false);
if (status_cast != TP_DOMAIN_STATUS::DOMAIN_COMPATIBLE)
{
return ER_FAILED;
}
return error_code;
}
int
column::evaluate_ordinality (size_t ordinality)
{
assert (m_domain->type->id == DB_TYPE_INTEGER);
db_make_int (m_output_value_pointer, (int) ordinality);
return NO_ERROR;
}
int
column::evaluate (const JSON_DOC &input, size_t ordinality)
{
assert (m_output_value_pointer != NULL);
pr_clear_value (m_output_value_pointer);
db_make_null (m_output_value_pointer);
int error_code = NO_ERROR;
switch (m_function)
{
case json_table_column_function::JSON_TABLE_EXTRACT:
error_code = evaluate_extract (input);
break;
case json_table_column_function::JSON_TABLE_EXISTS:
error_code = evaluate_exists (input);
break;
case json_table_column_function::JSON_TABLE_ORDINALITY:
error_code = evaluate_ordinality (ordinality);
break;
default:
return ER_FAILED;
}
return error_code;
}
void
column::clear_xasl (bool is_final_clear /* = true */)
{
if (is_final_clear)
{
(void) pr_clear_value (m_on_empty.m_default_value);
(void) pr_clear_value (m_on_error.m_default_value);
}
if (m_output_value_pointer != NULL)
{
(void) pr_clear_value (m_output_value_pointer);
(void) db_make_null (m_output_value_pointer);
}
}
node::node (void)
{
init ();
}
void
node::init ()
{
m_path = NULL;
init_ordinality ();
m_output_columns = NULL;
m_output_columns_size = 0;
m_nested_nodes = NULL;
m_nested_nodes_size = 0;
m_id = 0;
m_iterator = NULL;
m_is_iterable_node = false;
}
void
node::clear_columns (bool is_final_clear)
{
init_ordinality ();
for (size_t i = 0; i < m_output_columns_size; ++i)
{
m_output_columns[i].clear_xasl (is_final_clear);
}
}
void
node::clear_iterators (bool is_final_clear)
{
if (is_final_clear)
{
db_json_delete_json_iterator (m_iterator);
}
else
{
db_json_clear_json_iterator (m_iterator);
}
for (size_t i = 0; i < m_nested_nodes_size; ++i)
{
m_nested_nodes[i].clear_iterators (is_final_clear);
}
}
void
node::clear_xasl (bool is_final_clear /* = true */)
{
clear_columns (is_final_clear);
for (size_t i = 0; i < m_nested_nodes_size; ++i)
{
m_nested_nodes[i].clear_xasl (is_final_clear);
}
}
void
node::init_iterator ()
{
if (m_is_iterable_node)
{
m_iterator = db_json_create_iterator (DB_JSON_TYPE::DB_JSON_ARRAY);
}
}
void
node::init_ordinality()
{
m_ordinality = 1;
}
spec_node::spec_node ()
{
init ();
}
void
spec_node::init ()
{
m_root_node = NULL;
m_json_reguvar = NULL;
m_node_count = 0;
}
void
spec_node::clear_xasl (bool is_final_clear /* = true */)
{
// todo reguvar
m_root_node->clear_xasl (is_final_clear);
}
} // namespace json_table
} // namespace cubxasl