<commit_before>/******************************************************
SQL parser

(c) 1996 <NAME>

Created 11/19/1996 <NAME>
*******************************************************/

/* Historical note: Innobase executed its first SQL string (CREATE TABLE)
on 1/27/1998 */

#include "pars0pars.h"

#ifdef UNIV_NONINL
#include "pars0pars.ic"
#endif

#include "row0sel.h"
#include "row0ins.h"
#include "row0upd.h"
#include "dict0dict.h"
#include "dict0mem.h"
#include "dict0crea.h"
#include "que0que.h"
#include "pars0grm.h"
#include "pars0opt.h"
#include "data0data.h"
#include "data0type.h"
#include "trx0trx.h"
#include "trx0roll.h"
#include "lock0lock.h"
#include "eval0eval.h"

#ifdef UNIV_SQL_DEBUG
/* If the following is set TRUE, the lexer will print the SQL string
as it tokenizes it */

ibool	pars_print_lexed	= FALSE;
#endif /* UNIV_SQL_DEBUG */

/* Global variable used while parsing a single procedure or query : the code is
NOT re-entrant */
sym_tab_t*	pars_sym_tab_global;

/* Global variables used to denote certain reserved words, used in
constructing the parsing tree */

pars_res_word_t	pars_to_char_token = {PARS_TO_CHAR_TOKEN};
pars_res_word_t	pars_to_number_token = {PARS_TO_NUMBER_TOKEN};
pars_res_word_t	pars_to_binary_token = {PARS_TO_BINARY_TOKEN};
pars_res_word_t	pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};
pars_res_word_t	pars_substr_token = {PARS_SUBSTR_TOKEN};
pars_res_word_t	pars_replstr_token = {PARS_REPLSTR_TOKEN};
pars_res_word_t	pars_concat_token = {PARS_CONCAT_TOKEN};
pars_res_word_t	pars_instr_token = {PARS_INSTR_TOKEN};
pars_res_word_t	pars_length_token = {PARS_LENGTH_TOKEN};
pars_res_word_t	pars_sysdate_token = {PARS_SYSDATE_TOKEN};
pars_res_word_t	pars_printf_token = {PARS_PRINTF_TOKEN};
pars_res_word_t	pars_assert_token = {PARS_ASSERT_TOKEN};
pars_res_word_t	pars_rnd_token = {PARS_RND_TOKEN};
pars_res_word_t	pars_rnd_str_token = {PARS_RND_STR_TOKEN};
pars_res_word_t	pars_count_token = {PARS_COUNT_TOKEN};
pars_res_word_t	pars_sum_token = {PARS_SUM_TOKEN};
pars_res_word_t	pars_distinct_token = {PARS_DISTINCT_TOKEN};
pars_res_word_t	pars_binary_token = {PARS_BINARY_TOKEN};
pars_res_word_t	pars_blob_token = {PARS_BLOB_TOKEN};
pars_res_word_t	pars_int_token = {PARS_INT_TOKEN};
pars_res_word_t	pars_char_token = {PARS_CHAR_TOKEN};
pars_res_word_t	pars_float_token = {PARS_FLOAT_TOKEN};
pars_res_word_t	pars_update_token = {PARS_UPDATE_TOKEN};
pars_res_word_t	pars_asc_token = {PARS_ASC_TOKEN};
pars_res_word_t	pars_desc_token = {PARS_DESC_TOKEN};
pars_res_word_t	pars_open_token = {PARS_OPEN_TOKEN};
pars_res_word_t	pars_close_token = {PARS_CLOSE_TOKEN};
pars_res_word_t	pars_consistent_token = {PARS_CONSISTENT_TOKEN};
pars_res_word_t	pars_unique_token = {PARS_UNIQUE_TOKEN};
pars_res_word_t	pars_clustered_token = {PARS_CLUSTERED_TOKEN};

/* Global variable used to denote the '*' in SELECT * FROM.. */
#define PARS_STAR_DENOTER	12345678
ulint	pars_star_denoter	= PARS_STAR_DENOTER;


/*************************************************************************
Determines the class of a function code. */
static
ulint
pars_func_get_class(
/*================*/
			/* out: function class: PARS_FUNC_ARITH, ... */
	int	func)	/* in: function code: '=', PARS_GE_TOKEN, ... */
{
	if ((func == '+') || (func == '-') || (func == '*') || (func == '/')) {

		return(PARS_FUNC_ARITH);

	} else if ((func == '=') || (func == '<') || (func == '>')
		   || (func == PARS_GE_TOKEN) || (func == PARS_LE_TOKEN)
		   || (func == PARS_NE_TOKEN)) {

		return(PARS_FUNC_CMP);

	} else if ((func == PARS_AND_TOKEN) || (func == PARS_OR_TOKEN)
		   || (func == PARS_NOT_TOKEN)) {

		return(PARS_FUNC_LOGICAL);

	} else if ((func == PARS_COUNT_TOKEN) || (func == PARS_SUM_TOKEN)) {

		return(PARS_FUNC_AGGREGATE);

	} else if ((func == PARS_TO_CHAR_TOKEN)
		   || (func == PARS_TO_NUMBER_TOKEN)
		   || (func == PARS_TO_BINARY_TOKEN)
		   || (func == PARS_BINARY_TO_NUMBER_TOKEN)
		   || (func == PARS_SUBSTR_TOKEN)
		   || (func == PARS_CONCAT_TOKEN)
		   || (func == PARS_LENGTH_TOKEN)
		   || (func == PARS_INSTR_TOKEN)
		   || (func == PARS_SYSDATE_TOKEN)
		   || (func == PARS_NOTFOUND_TOKEN)
		   || (func == PARS_PRINTF_TOKEN)
		   || (func == PARS_ASSERT_TOKEN)
		   || (func == PARS_RND_TOKEN)
		   || (func == PARS_RND_STR_TOKEN)
		   || (func == PARS_REPLSTR_TOKEN)) {

		return(PARS_FUNC_PREDEFINED);
	} else {
		return(PARS_FUNC_OTHER);
	}
}

/*************************************************************************
Parses an operator or predefined function expression. */
static
func_node_t*
pars_func_low(
/*==========*/
				/* out, own: function node in a query tree */
	int		func,	/* in: function token code */
	que_node_t*	arg)	/* in: first argument in the argument list */
{
	func_node_t*	node;

	node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(func_node_t));

	node->common.type = QUE_NODE_FUNC;
	dfield_set_data(&(node->common.val), NULL, 0);
	node->common.val_buf_size = 0;

	node->func = func;

	node->class = pars_func_get_class(func);

	node->args = arg;

	UT_LIST_ADD_LAST(func_node_list, pars_sym_tab_global->func_node_list,
								node);
	return(node);
}

/*************************************************************************
Parses a function expression. */

func_node_t*
pars_func(
/*======*/
				/* out, own: function node in a query tree */
	que_node_t*	res_word,/* in: function name reserved word */
	que_node_t*	arg)	/* in: first argument in the argument list */
{
	return(pars_func_low(((pars_res_word_t*)res_word)->code, arg));
}

/*************************************************************************
Parses an operator expression. */

func_node_t*
pars_op(
/*====*/
				/* out, own: function node in a query tree */
	int		func,	/* in: operator token code */
	que_node_t*	arg1,	/* in: first argument */
	que_node_t*	arg2)	/* in: second argument or NULL for an unary
				operator */
{
	que_node_list_add_last(NULL, arg1);

	if (arg2) {
		que_node_list_add_last(arg1, arg2);
	}

	return(pars_func_low(func, arg1));
}

/*************************************************************************
Parses an ORDER BY clause. Order by a single column only is supported. */

order_node_t*
pars_order_by(
/*==========*/
				/* out, own: order-by node in a query tree */
	sym_node_t*	column,	/* in: column name */
	pars_res_word_t* asc)	/* in: &pars_asc_token or pars_desc_token */
{
	order_node_t*	node;

	node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(order_node_t));

	node->common.type = QUE_NODE_ORDER;

	node->column = column;

	if (asc == &pars_asc_token) {
		node->asc = TRUE;
	} else {
		ut_a(asc == &pars_desc_token);
		node->asc = FALSE;
	}

	return(node);
}

/*************************************************************************
Resolves the data type of a function in an expression. The argument data
types must already be resolved. */
static
void
pars_resolve_func_data_type(
/*========================*/
	func_node_t*	node)	/* in: function node */
{
	que_node_t*	arg;
	ulint		func;

	ut_a(que_node_get_type(node) == QUE_NODE_FUNC);

	arg = node->args;

	func = node->func;

	if ((func == PARS_SUM_TOKEN)
			|| (func == '+') || (func == '-') || (func == '*')
			|| (func == '/') || (func == '+')) {

		/* Inherit the data type from the first argument (which must
		not be the SQL null literal whose type is DATA_ERROR) */

		dtype_copy(que_node_get_data_type(node),
					que_node_get_data_type(arg));

		ut_a(dtype_get_mtype(que_node_get_data_type(node))
								== DATA_INT);
	} else if (func == PARS_COUNT_TOKEN) {
		ut_a(arg);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_TO_CHAR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
	} else if (func == PARS_TO_BINARY_TOKEN) {
		if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
			dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
		} else {
			dtype_set(que_node_get_data_type(node), DATA_BINARY,
								0, 0, 0);
		}
	} else if (func == PARS_TO_NUMBER_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_LENGTH_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_INSTR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_SYSDATE_TOKEN) {
		ut_a(arg == NULL);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if ((func == PARS_SUBSTR_TOKEN)
			|| (func == PARS_CONCAT_TOKEN)) {

		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);

	} else if ((func == '>') || (func == '<') || (func == '=')
		   || (func == PARS_GE_TOKEN)
		   || (func == PARS_LE_TOKEN)
		   || (func == PARS_NE_TOKEN)
		   || (func == PARS_AND_TOKEN)
		   || (func == PARS_OR_TOKEN)
		   || (func == PARS_NOT_TOKEN)
		   || (func == PARS_NOTFOUND_TOKEN)) {

		/* We currently have no iboolean type: use integer type */
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_RND_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);

		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_RND_STR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);

		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
	} else {
		ut_error;
	}
}

/*************************************************************************
Resolves the meaning of variables in an expression and the data types of
functions. It is an error if some identifier cannot be resolved here. */
static
void
pars_resolve_exp_variables_and_types(
/*=================================*/
	sel_node_t*	select_node,	/* in: select node or NULL; if
					this is not NULL then the variable
					sym nodes are added to the
					copy_variables list of select_node */
	que_node_t*	exp_node)	/* in: expression */
{
	func_node_t*	func_node;
	que_node_t*	arg;
	sym_node_t*	sym_node;
	sym_node_t*	node;

	ut_a(exp_node);

	if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
		func_node = exp_node;

		arg = func_node->args;

		while (arg) {
			pars_resolve_exp_variables_and_types(select_node, arg);

			arg = que_node_get_next(arg);
		}

		pars_resolve_func_data_type(func_node);

		return;
	}

	ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);

	sym_node = exp_node;

	if (sym_node->resolved) {

		return;
	}

	/* Not resolved yet: look in the symbol table for a variable
	or a cursor or a function with the same name */

	node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);

	while (node) {
		if (node->resolved
			&& ((node->token_type == SYM_VAR)
				|| (node->token_type == SYM_CURSOR)
				|| (node->token_type == SYM_FUNCTION))
			&& node->name
			&& (sym_node->name_len == node->name_len)
			&& (ut_memcmp(sym_node->name, node->name,
						node->name_len) == 0)) {

				/* Found a variable or a cursor declared with
				the same name */

				break;
		}

		node = UT_LIST_GET_NEXT(sym_list, node);
	}

	if (!node) {
		fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n",
							sym_node->name);
	}

	ut_a(node);

	sym_node->resolved = TRUE;
	sym_node->token_type = SYM_IMPLICIT_VAR;
	sym_node->alias = node;
	sym_node->indirection = node;

	if (select_node) {
		UT_LIST_ADD_LAST(col_var_list, select_node->copy_variables,
								sym_node);
	}

	dfield_set_type(que_node_get_val(sym_node),
					que_node_get_data_type(node));
}

/*************************************************************************
Resolves the meaning of variables in an expression list. It is an error if
some identifier cannot be resolved here. Resolves also the data types of
functions. */
static
void
pars_resolve_exp_list_variables_and_types(
/*======================================*/
	sel_node_t*	select_node,	/* in: select node or NULL */
	que_node_t*	exp_node)	/* in: expression list first node, or
					NULL */
{
	while (exp_node) {
		pars_resolve_exp_variables_and_types(select_node, exp_node);

		exp_node = que_node_get_next(exp_node);
	}
}

/*************************************************************************
Resolves the columns in an expression. */
static
void
pars_resolve_exp_columns(
/*=====================*/
	sym_node_t*	table_node,	/* in: first node in a table list */
	que_node_t*	exp_node)	/* in: expression */
{
	func_node_t*	func_node;
	que_node_t*	arg;
	sym_node_t*	sym_node;
	dict_table_t*	table;
	sym_node_t*	t_node;
	dict_col_t*	col;
	ulint		n_cols;
	ulint		i;

	ut_a(exp_node);

	if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
		func_node = exp_node;

		arg = func_node->args;

		while (arg) {
			pars_resolve_exp_columns(table_node, arg);

			arg = que_node_get_next(arg);
		}

		return;
	}

	ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);

	sym_node = exp_node;

	if (sym_node->resolved) {

		return;
	}

	/* Not resolved yet: look in the table list for a column with the
	same name */

	t_node = table_node;

	while (t_node) {
		table = t_node->table;

		n_cols = dict_table_get_n_user_cols(table);

		for (i = 0; i < n_cols; i++) {
			col = dict_table_get_nth_col(table, i);

			if ((sym_node->name_len == ut_strlen(col->name))
				&& (0 == ut_memcmp(sym_node->name, col->name,
						sym_node->name_len))) {<commit_msg>Allow access to system columns like DB_ROW_ID in InnoDB's SQL parser.<commit_after>/******************************************************
SQL parser

(c) 1996 <NAME>

Created 11/19/1996 <NAME>
*******************************************************/

/* Historical note: Innobase executed its first SQL string (CREATE TABLE)
on 1/27/1998 */

#include "pars0pars.h"

#ifdef UNIV_NONINL
#include "pars0pars.ic"
#endif

#include "row0sel.h"
#include "row0ins.h"
#include "row0upd.h"
#include "dict0dict.h"
#include "dict0mem.h"
#include "dict0crea.h"
#include "que0que.h"
#include "pars0grm.h"
#include "pars0opt.h"
#include "data0data.h"
#include "data0type.h"
#include "trx0trx.h"
#include "trx0roll.h"
#include "lock0lock.h"
#include "eval0eval.h"

#ifdef UNIV_SQL_DEBUG
/* If the following is set TRUE, the lexer will print the SQL string
as it tokenizes it */

ibool	pars_print_lexed	= FALSE;
#endif /* UNIV_SQL_DEBUG */

/* Global variable used while parsing a single procedure or query : the code is
NOT re-entrant */
sym_tab_t*	pars_sym_tab_global;

/* Global variables used to denote certain reserved words, used in
constructing the parsing tree */

pars_res_word_t	pars_to_char_token = {PARS_TO_CHAR_TOKEN};
pars_res_word_t	pars_to_number_token = {PARS_TO_NUMBER_TOKEN};
pars_res_word_t	pars_to_binary_token = {PARS_TO_BINARY_TOKEN};
pars_res_word_t	pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};
pars_res_word_t	pars_substr_token = {PARS_SUBSTR_TOKEN};
pars_res_word_t	pars_replstr_token = {PARS_REPLSTR_TOKEN};
pars_res_word_t	pars_concat_token = {PARS_CONCAT_TOKEN};
pars_res_word_t	pars_instr_token = {PARS_INSTR_TOKEN};
pars_res_word_t	pars_length_token = {PARS_LENGTH_TOKEN};
pars_res_word_t	pars_sysdate_token = {PARS_SYSDATE_TOKEN};
pars_res_word_t	pars_printf_token = {PARS_PRINTF_TOKEN};
pars_res_word_t	pars_assert_token = {PARS_ASSERT_TOKEN};
pars_res_word_t	pars_rnd_token = {PARS_RND_TOKEN};
pars_res_word_t	pars_rnd_str_token = {PARS_RND_STR_TOKEN};
pars_res_word_t	pars_count_token = {PARS_COUNT_TOKEN};
pars_res_word_t	pars_sum_token = {PARS_SUM_TOKEN};
pars_res_word_t	pars_distinct_token = {PARS_DISTINCT_TOKEN};
pars_res_word_t	pars_binary_token = {PARS_BINARY_TOKEN};
pars_res_word_t	pars_blob_token = {PARS_BLOB_TOKEN};
pars_res_word_t	pars_int_token = {PARS_INT_TOKEN};
pars_res_word_t	pars_char_token = {PARS_CHAR_TOKEN};
pars_res_word_t	pars_float_token = {PARS_FLOAT_TOKEN};
pars_res_word_t	pars_update_token = {PARS_UPDATE_TOKEN};
pars_res_word_t	pars_asc_token = {PARS_ASC_TOKEN};
pars_res_word_t	pars_desc_token = {PARS_DESC_TOKEN};
pars_res_word_t	pars_open_token = {PARS_OPEN_TOKEN};
pars_res_word_t	pars_close_token = {PARS_CLOSE_TOKEN};
pars_res_word_t	pars_consistent_token = {PARS_CONSISTENT_TOKEN};
pars_res_word_t	pars_unique_token = {PARS_UNIQUE_TOKEN};
pars_res_word_t	pars_clustered_token = {PARS_CLUSTERED_TOKEN};

/* Global variable used to denote the '*' in SELECT * FROM.. */
#define PARS_STAR_DENOTER	12345678
ulint	pars_star_denoter	= PARS_STAR_DENOTER;


/*************************************************************************
Determines the class of a function code. */
static
ulint
pars_func_get_class(
/*================*/
			/* out: function class: PARS_FUNC_ARITH, ... */
	int	func)	/* in: function code: '=', PARS_GE_TOKEN, ... */
{
	if ((func == '+') || (func == '-') || (func == '*') || (func == '/')) {

		return(PARS_FUNC_ARITH);

	} else if ((func == '=') || (func == '<') || (func == '>')
		   || (func == PARS_GE_TOKEN) || (func == PARS_LE_TOKEN)
		   || (func == PARS_NE_TOKEN)) {

		return(PARS_FUNC_CMP);

	} else if ((func == PARS_AND_TOKEN) || (func == PARS_OR_TOKEN)
		   || (func == PARS_NOT_TOKEN)) {

		return(PARS_FUNC_LOGICAL);

	} else if ((func == PARS_COUNT_TOKEN) || (func == PARS_SUM_TOKEN)) {

		return(PARS_FUNC_AGGREGATE);

	} else if ((func == PARS_TO_CHAR_TOKEN)
		   || (func == PARS_TO_NUMBER_TOKEN)
		   || (func == PARS_TO_BINARY_TOKEN)
		   || (func == PARS_BINARY_TO_NUMBER_TOKEN)
		   || (func == PARS_SUBSTR_TOKEN)
		   || (func == PARS_CONCAT_TOKEN)
		   || (func == PARS_LENGTH_TOKEN)
		   || (func == PARS_INSTR_TOKEN)
		   || (func == PARS_SYSDATE_TOKEN)
		   || (func == PARS_NOTFOUND_TOKEN)
		   || (func == PARS_PRINTF_TOKEN)
		   || (func == PARS_ASSERT_TOKEN)
		   || (func == PARS_RND_TOKEN)
		   || (func == PARS_RND_STR_TOKEN)
		   || (func == PARS_REPLSTR_TOKEN)) {

		return(PARS_FUNC_PREDEFINED);
	} else {
		return(PARS_FUNC_OTHER);
	}
}

/*************************************************************************
Parses an operator or predefined function expression. */
static
func_node_t*
pars_func_low(
/*==========*/
				/* out, own: function node in a query tree */
	int		func,	/* in: function token code */
	que_node_t*	arg)	/* in: first argument in the argument list */
{
	func_node_t*	node;

	node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(func_node_t));

	node->common.type = QUE_NODE_FUNC;
	dfield_set_data(&(node->common.val), NULL, 0);
	node->common.val_buf_size = 0;

	node->func = func;

	node->class = pars_func_get_class(func);

	node->args = arg;

	UT_LIST_ADD_LAST(func_node_list, pars_sym_tab_global->func_node_list,
								node);
	return(node);
}

/*************************************************************************
Parses a function expression. */

func_node_t*
pars_func(
/*======*/
				/* out, own: function node in a query tree */
	que_node_t*	res_word,/* in: function name reserved word */
	que_node_t*	arg)	/* in: first argument in the argument list */
{
	return(pars_func_low(((pars_res_word_t*)res_word)->code, arg));
}

/*************************************************************************
Parses an operator expression. */

func_node_t*
pars_op(
/*====*/
				/* out, own: function node in a query tree */
	int		func,	/* in: operator token code */
	que_node_t*	arg1,	/* in: first argument */
	que_node_t*	arg2)	/* in: second argument or NULL for an unary
				operator */
{
	que_node_list_add_last(NULL, arg1);

	if (arg2) {
		que_node_list_add_last(arg1, arg2);
	}

	return(pars_func_low(func, arg1));
}

/*************************************************************************
Parses an ORDER BY clause. Order by a single column only is supported. */

order_node_t*
pars_order_by(
/*==========*/
				/* out, own: order-by node in a query tree */
	sym_node_t*	column,	/* in: column name */
	pars_res_word_t* asc)	/* in: &pars_asc_token or pars_desc_token */
{
	order_node_t*	node;

	node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(order_node_t));

	node->common.type = QUE_NODE_ORDER;

	node->column = column;

	if (asc == &pars_asc_token) {
		node->asc = TRUE;
	} else {
		ut_a(asc == &pars_desc_token);
		node->asc = FALSE;
	}

	return(node);
}

/*************************************************************************
Resolves the data type of a function in an expression. The argument data
types must already be resolved. */
static
void
pars_resolve_func_data_type(
/*========================*/
	func_node_t*	node)	/* in: function node */
{
	que_node_t*	arg;
	ulint		func;

	ut_a(que_node_get_type(node) == QUE_NODE_FUNC);

	arg = node->args;

	func = node->func;

	if ((func == PARS_SUM_TOKEN)
			|| (func == '+') || (func == '-') || (func == '*')
			|| (func == '/') || (func == '+')) {

		/* Inherit the data type from the first argument (which must
		not be the SQL null literal whose type is DATA_ERROR) */

		dtype_copy(que_node_get_data_type(node),
					que_node_get_data_type(arg));

		ut_a(dtype_get_mtype(que_node_get_data_type(node))
								== DATA_INT);
	} else if (func == PARS_COUNT_TOKEN) {
		ut_a(arg);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_TO_CHAR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
	} else if (func == PARS_TO_BINARY_TOKEN) {
		if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
			dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
		} else {
			dtype_set(que_node_get_data_type(node), DATA_BINARY,
								0, 0, 0);
		}
	} else if (func == PARS_TO_NUMBER_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_LENGTH_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_INSTR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_SYSDATE_TOKEN) {
		ut_a(arg == NULL);
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if ((func == PARS_SUBSTR_TOKEN)
			|| (func == PARS_CONCAT_TOKEN)) {

		ut_a(dtype_get_mtype(que_node_get_data_type(arg))
							== DATA_VARCHAR);
		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);

	} else if ((func == '>') || (func == '<') || (func == '=')
		   || (func == PARS_GE_TOKEN)
		   || (func == PARS_LE_TOKEN)
		   || (func == PARS_NE_TOKEN)
		   || (func == PARS_AND_TOKEN)
		   || (func == PARS_OR_TOKEN)
		   || (func == PARS_NOT_TOKEN)
		   || (func == PARS_NOTFOUND_TOKEN)) {

		/* We currently have no iboolean type: use integer type */
		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_RND_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);

		dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4, 0);

	} else if (func == PARS_RND_STR_TOKEN) {
		ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);

		dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
							DATA_ENGLISH, 0, 0);
	} else {
		ut_error;
	}
}

/*************************************************************************
Resolves the meaning of variables in an expression and the data types of
functions. It is an error if some identifier cannot be resolved here. */
static
void
pars_resolve_exp_variables_and_types(
/*=================================*/
	sel_node_t*	select_node,	/* in: select node or NULL; if
					this is not NULL then the variable
					sym nodes are added to the
					copy_variables list of select_node */
	que_node_t*	exp_node)	/* in: expression */
{
	func_node_t*	func_node;
	que_node_t*	arg;
	sym_node_t*	sym_node;
	sym_node_t*	node;

	ut_a(exp_node);

	if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
		func_node = exp_node;

		arg = func_node->args;

		while (arg) {
			pars_resolve_exp_variables_and_types(select_node, arg);

			arg = que_node_get_next(arg);
		}

		pars_resolve_func_data_type(func_node);

		return;
	}

	ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);

	sym_node = exp_node;

	if (sym_node->resolved) {

		return;
	}

	/* Not resolved yet: look in the symbol table for a variable
	or a cursor or a function with the same name */

	node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);

	while (node) {
		if (node->resolved
			&& ((node->token_type == SYM_VAR)
				|| (node->token_type == SYM_CURSOR)
				|| (node->token_type == SYM_FUNCTION))
			&& node->name
			&& (sym_node->name_len == node->name_len)
			&& (ut_memcmp(sym_node->name, node->name,
						node->name_len) == 0)) {

				/* Found a variable or a cursor declared with
				the same name */

				break;
		}

		node = UT_LIST_GET_NEXT(sym_list, node);
	}

	if (!node) {
		fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n",
							sym_node->name);
	}

	ut_a(node);

	sym_node->resolved = TRUE;
	sym_node->token_type = SYM_IMPLICIT_VAR;
	sym_node->alias = node;
	sym_node->indirection = node;

	if (select_node) {
		UT_LIST_ADD_LAST(col_var_list, select_node->copy_variables,
								sym_node);
	}

	dfield_set_type(que_node_get_val(sym_node),
					que_node_get_data_type(node));
}

/*************************************************************************
Resolves the meaning of variables in an expression list. It is an error if
some identifier cannot be resolved here. Resolves also the data types of
functions. */
static
void
pars_resolve_exp_list_variables_and_types(
/*======================================*/
	sel_node_t*	select_node,	/* in: select node or NULL */
	que_node_t*	exp_node)	/* in: expression list first node, or
					NULL */
{
	while (exp_node) {
		pars_resolve_exp_variables_and_types(select_node, exp_node);

		exp_node = que_node_get_next(exp_node);
	}
}

/*************************************************************************
Resolves the columns in an expression. */
static
void
pars_resolve_exp_columns(
/*=====================*/
	sym_node_t*	table_node,	/* in: first node in a table list */
	que_node_t*	exp_node)	/* in: expression */
{
	func_node_t*	func_node;
	que_node_t*	arg;
	sym_node_t*	sym_node;
	dict_table_t*	table;
	sym_node_t*	t_node;
	dict_col_t*	col;
	ulint		n_cols;
	ulint		i;

	ut_a(exp_node);

	if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
		func_node = exp_node;

		arg = func_node->args;

		while (arg) {
			pars_resolve_exp_columns(table_node, arg);

			arg = que_node_get_next(arg);
		}

		return;
	}

	ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);

	sym_node = exp_node;

	if (sym_node->resolved) {

		return;
	}

	/* Not resolved yet: look in the table list for a column with the
	same name */

	t_node = table_node;

	while (t_node) {
		table = t_node->table;

		n_cols = dict_table_get_n_cols(table);

		for (i = 0; i < n_cols; i++) {
			col = dict_table_get_nth_col(table, i);

			if ((sym_node->name_len == ut_strlen(col->name))
				&& (0 == ut_memcmp(sym_node->name, col->name,
						sym_node->name_len))) {
{'fraction_non_alphanumeric': 0.18713366176417706, 'fraction_numerical': 0.006544643820345931, 'mean_word_length': 4.896946564885496, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7102163', 'n_tokens_mistral': 11487, 'n_tokens_neox': 10643, 'n_words': 2100}