/******************************************************
SQL parser

(c) 1996 Innobase Oy

Created 11/19/1996 Heikki Tuuri
*******************************************************/

#ifndef pars0pars_h
#define pars0pars_h

#include "univ.i"
#include "que0types.h"
#include "usr0types.h"
#include "pars0types.h"
#include "row0types.h"
#include "trx0types.h"
#include "ut0vec.h"

/* Type of the user functions. The first argument is always InnoDB-supplied
and varies in type, while 'user_arg' is a user-supplied argument. The
meaning of the return type also varies. See the individual use cases, e.g.
the FETCH statement, for details on them. */
typedef void* (*pars_user_func_cb_t)(void* arg, void* user_arg);

extern int	yydebug;

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

#ifdef UNIV_SQL_DEBUG
extern ibool	pars_print_lexed;
#endif /* UNIV_SQL_DEBUG */

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

extern pars_res_word_t	pars_to_char_token;
extern pars_res_word_t	pars_to_number_token;
extern pars_res_word_t	pars_to_binary_token;
extern pars_res_word_t	pars_binary_to_number_token;
extern pars_res_word_t	pars_substr_token;
extern pars_res_word_t	pars_replstr_token;
extern pars_res_word_t	pars_concat_token;
extern pars_res_word_t	pars_length_token;
extern pars_res_word_t	pars_instr_token;
extern pars_res_word_t	pars_sysdate_token;
extern pars_res_word_t	pars_printf_token;
extern pars_res_word_t	pars_assert_token;
extern pars_res_word_t	pars_rnd_token;
extern pars_res_word_t	pars_rnd_str_token;
extern pars_res_word_t	pars_count_token;
extern pars_res_word_t	pars_sum_token;
extern pars_res_word_t	pars_distinct_token;
extern pars_res_word_t	pars_binary_token;
extern pars_res_word_t	pars_blob_token;
extern pars_res_word_t	pars_int_token;
extern pars_res_word_t	pars_char_token;
extern pars_res_word_t	pars_float_token;
extern pars_res_word_t	pars_update_token;
extern pars_res_word_t	pars_asc_token;
extern pars_res_word_t	pars_desc_token;
extern pars_res_word_t	pars_open_token;
extern pars_res_word_t	pars_close_token;
extern pars_res_word_t	pars_share_token;
extern pars_res_word_t	pars_unique_token;
extern pars_res_word_t	pars_clustered_token;

extern ulint		pars_star_denoter;

/* Procedure parameter types */
#define PARS_INPUT	0
#define PARS_OUTPUT	1
#define PARS_NOT_PARAM	2

int
yyparse(void);

/*****************************************************************
Parses an SQL string returning the query graph. */

que_t*
pars_sql(
/*=====*/
				/* out, own: the query graph */
	pars_info_t*	info,	/* in: extra information, or NULL */
	const char*	str);	/* in: SQL string */
/*****************************************************************
Retrieves characters to the lexical analyzer. */

void
pars_get_lex_chars(
/*===============*/
	char*	buf,		/* in/out: buffer where to copy */
	int*	result,		/* out: number of characters copied or EOF */
	int	max_size);	/* in: maximum number of characters which fit
				in the buffer */
/*****************************************************************
Called by yyparse on error. */

void
yyerror(
/*====*/
	const char*	s);	/* in: error message string */
/*************************************************************************
Parses a variable declaration. */

sym_node_t*
pars_variable_declaration(
/*======================*/
				/* out, own: symbol table node of type
				SYM_VAR */
	sym_node_t*	node,	/* in: symbol table node allocated for the
				id of the variable */
	pars_res_word_t* type);	/* in: pointer to a type token */
/*************************************************************************
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 */
/*************************************************************************
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 */
/*************************************************************************
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 */
/*************************************************************************
Parses a select list; creates a query graph node for the whole SELECT
statement. */

sel_node_t*
pars_select_list(
/*=============*/
					/* out, own: select node in a query
					tree */
	que_node_t*	select_list,	/* in: select list */
	sym_node_t*	into_list);	/* in: variables list or NULL */
/*************************************************************************
Parses a cursor declaration. */

que_node_t*
pars_cursor_declaration(
/*====================*/
					/* out: sym_node */
	sym_node_t*	sym_node,	/* in: cursor id node in the symbol
					table */
	sel_node_t*	select_node);	/* in: select node */
/*************************************************************************
Parses a function declaration. */

que_node_t*
pars_function_declaration(
/*======================*/
					/* out: sym_node */
	sym_node_t*	sym_node);	/* in: function id node in the symbol
					table */
/*************************************************************************
Parses a select statement. */

sel_node_t*
pars_select_statement(
/*==================*/
					/* out, own: select node in a query
					tree */
	sel_node_t*	select_node,	/* in: select node already containing
					the select list */
	sym_node_t*	table_list,	/* in: table list */
	que_node_t*	search_cond,	/* in: search condition or NULL */
	pars_res_word_t* for_update,	/* in: NULL or &pars_update_token */
	pars_res_word_t* consistent_read,/* in: NULL or
						&pars_consistent_token */
	order_node_t*	order_by);	/* in: NULL or an order-by node */
/*************************************************************************
Parses a column assignment in an update. */

col_assign_node_t*
pars_column_assignment(
/*===================*/
				/* out: column assignment node */
	sym_node_t*	column,	/* in: column to assign */
	que_node_t*	exp);	/* in: value to assign */
/*************************************************************************
Parses a delete or update statement start. */

upd_node_t*
pars_update_statement_start(
/*========================*/
					/* out, own: update node in a query
					tree */
	ibool		is_delete,	/* in: TRUE if delete */
	sym_node_t*	table_sym,	/* in: table name node */
	col_assign_node_t* col_assign_list);/* in: column assignment list, NULL
					if delete */
/*************************************************************************
Parses an update or delete statement. */

upd_node_t*
pars_update_statement(
/*==================*/
					/* out, own: update node in a query
					tree */
	upd_node_t*	node,		/* in: update node */
	sym_node_t*	cursor_sym,	/* in: pointer to a cursor entry in
					the symbol table or NULL */
	que_node_t*	search_cond);	/* in: search condition or NULL */
/*************************************************************************
Parses an insert statement. */

ins_node_t*
pars_insert_statement(
/*==================*/
					/* out, own: update node in a query
					tree */
	sym_node_t*	table_sym,	/* in: table name node */
	que_node_t*	values_list,	/* in: value expression list or NULL */
	sel_node_t*	select);	/* in: select condition or NULL */
/*************************************************************************
Parses a procedure parameter declaration. */

sym_node_t*
pars_parameter_declaration(
/*=======================*/
				/* out, own: symbol table node of type
				SYM_VAR */
	sym_node_t*	node,	/* in: symbol table node allocated for the
				id of the parameter */
	ulint		param_type,
				/* in: PARS_INPUT or PARS_OUTPUT */
	pars_res_word_t* type);	/* in: pointer to a type token */
/*************************************************************************
Parses an elsif element. */

elsif_node_t*
pars_elsif_element(
/*===============*/
					/* out: elsif node */
	que_node_t*	cond,		/* in: if-condition */
	que_node_t*	stat_list);	/* in: statement list */
/*************************************************************************
Parses an if-statement. */

if_node_t*
pars_if_statement(
/*==============*/
					/* out: if-statement node */
	que_node_t*	cond,		/* in: if-condition */
	que_node_t*	stat_list,	/* in: statement list */
	que_node_t*	else_part);	/* in: else-part statement list */
/*************************************************************************
Parses a for-loop-statement. */

for_node_t*
pars_for_statement(
/*===============*/
					/* out: for-statement node */
	sym_node_t*	loop_var,	/* in: loop variable */
	que_node_t*	loop_start_limit,/* in: loop start expression */
	que_node_t*	loop_end_limit,	/* in: loop end expression */
	que_node_t*	stat_list);	/* in: statement list */
/*************************************************************************
Parses a while-statement. */

while_node_t*
pars_while_statement(
/*=================*/
					/* out: while-statement node */
	que_node_t*	cond,		/* in: while-condition */
	que_node_t*	stat_list);	/* in: statement list */
/*************************************************************************
Parses an exit statement. */

exit_node_t*
pars_exit_statement(void);
/*=====================*/
					/* out: exit statement node */
/*************************************************************************
Parses a return-statement. */

return_node_t*
pars_return_statement(void);
/*=======================*/
					/* out: return-statement node */
/*************************************************************************
Parses a procedure call. */

func_node_t*
pars_procedure_call(
/*================*/
				/* out: function node */
	que_node_t*	res_word,/* in: procedure name reserved word */
	que_node_t*	args);	/* in: argument list */
/*************************************************************************
Parses an assignment statement. */

assign_node_t*
pars_assignment_statement(
/*======================*/
				/* out: assignment statement node */
	sym_node_t*	var,	/* in: variable to assign */
	que_node_t*	val);	/* in: value to assign */
/*************************************************************************
Parses a fetch statement. into_list or user_func (but not both) must be
non-NULL. */

fetch_node_t*
pars_fetch_statement(
/*=================*/
					/* out: fetch statement node */
	sym_node_t*	cursor,		/* in: cursor node */
	sym_node_t*	into_list,	/* in: variables to set, or NULL */
	sym_node_t*	user_func);	/* in: user function name, or NULL */
/*************************************************************************
Parses an open or close cursor statement. */

open_node_t*
pars_open_statement(
/*================*/
				/* out: fetch statement node */
	ulint		type,	/* in: ROW_SEL_OPEN_CURSOR
				or ROW_SEL_CLOSE_CURSOR */
	sym_node_t*	cursor);	/* in: cursor node */
/*************************************************************************
Parses a row_printf-statement. */

row_printf_node_t*
pars_row_printf_statement(
/*======================*/
					/* out: row_printf-statement node */
	sel_node_t*	sel_node);	/* in: select node */
/*************************************************************************
Parses a commit statement. */

commit_node_t*
pars_commit_statement(void);
/*=======================*/
/*************************************************************************
Parses a rollback statement. */

roll_node_t*
pars_rollback_statement(void);
/*=========================*/
/*************************************************************************
Parses a column definition at a table creation. */

sym_node_t*
pars_column_def(
/*============*/
						/* out: column sym table
						node */
	sym_node_t*		sym_node,	/* in: column node in the
						symbol table */
	pars_res_word_t*	type,		/* in: data type */
	sym_node_t*		len,		/* in: length of column, or
						NULL */
	void*			is_unsigned,	/* in: if not NULL, column
						is of type UNSIGNED. */
	void*			is_not_null);	/* in: if not NULL, column
						is of type NOT NULL. */
/*************************************************************************
Parses a table creation operation. */

tab_node_t*
pars_create_table(
/*==============*/
					/* out: table create subgraph */
	sym_node_t*	table_sym,	/* in: table name node in the symbol
					table */
	sym_node_t*	column_defs,	/* in: list of column names */
	void*		not_fit_in_memory);/* in: a non-NULL pointer means that
					this is a table which in simulations
					should be simulated as not fitting
					in memory; thread is put to sleep
					to simulate disk accesses; NOTE that
					this flag is not stored to the data
					dictionary on disk, and the database
					will forget about non-NULL value if
					it has to reload the table definition
					from disk */
/*************************************************************************
Parses an index creation operation. */

ind_node_t*
pars_create_index(
/*==============*/
					/* out: index create subgraph */
	pars_res_word_t* unique_def,	/* in: not NULL if a unique index */
	pars_res_word_t* clustered_def,	/* in: not NULL if a clustered index */
	sym_node_t*	index_sym,	/* in: index name node in the symbol
					table */
	sym_node_t*	table_sym,	/* in: table name node in the symbol
					table */
	sym_node_t*	column_list);	/* in: list of column names */
/*************************************************************************
Parses a procedure definition. */

que_fork_t*
pars_procedure_definition(
/*======================*/
					/* out: query fork node */
	sym_node_t*	sym_node,	/* in: procedure id node in the symbol
					table */
	sym_node_t*	param_list,	/* in: parameter declaration list */
	que_node_t*	stat_list);	/* in: statement list */

/*****************************************************************
Parses a stored procedure call, when this is not within another stored
procedure, that is, the client issues a procedure call directly.
In MySQL/InnoDB, stored InnoDB procedures are invoked via the
parsed procedure tree, not via InnoDB SQL, so this function is not used. */

que_fork_t*
pars_stored_procedure_call(
/*=======================*/
					/* out: query graph */
	sym_node_t*	sym_node);	/* in: stored procedure name */
/**********************************************************************
Completes a query graph by adding query thread and fork nodes
above it and prepares the graph for running. The fork created is of
type QUE_FORK_MYSQL_INTERFACE. */

que_thr_t*
pars_complete_graph_for_exec(
/*=========================*/
				/* out: query thread node to run */
	que_node_t*	node,	/* in: root node for an incomplete
				query graph */
	trx_t*		trx,	/* in: transaction handle */
	mem_heap_t*	heap);	/* in: memory heap from which allocated */

/********************************************************************
Create parser info struct.*/

pars_info_t*
pars_info_create(void);
/*==================*/
		/* out, own: info struct */

/********************************************************************
Free info struct and everything it contains.*/

void
pars_info_free(
/*===========*/
	pars_info_t*	info);	/* in: info struct */

/********************************************************************
Add bound literal. */

void
pars_info_add_literal(
/*==================*/
	pars_info_t*	info,		/* in: info struct */
	const char*	name,		/* in: name */
	const void*	address,	/* in: address */
	ulint		length,		/* in: length of data */
	ulint		type,		/* in: type, e.g. DATA_FIXBINARY */
	ulint		prtype);	/* in: precise type, e.g.
					DATA_UNSIGNED */

/********************************************************************
Equivalent to pars_info_add_literal(info, name, str, strlen(str),
DATA_VARCHAR, DATA_ENGLISH). */

void
pars_info_add_str_literal(
/*======================*/
	pars_info_t*	info,		/* in: info struct */
	const char*	name,		/* in: name */
	const char*	str);		/* in: string */

/********************************************************************
Equivalent to:

char buf[4];
mach_write_to_4(buf, val);
pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);

except that the buffer is dynamically allocated from the info struct's
heap. */

void
pars_info_add_int4_literal(
/*=======================*/
	pars_info_t*	info,		/* in: info struct */
	const char*	name,		/* in: name */
	lint		val);		/* in: value */

/********************************************************************
Equivalent to:

char buf[8];
mach_write_to_8(buf, val);
pars_info_add_literal(info, name, buf, 8, DATA_BINARY, 0);

except that the buffer is dynamically allocated from the info struct's
heap. */

void
pars_info_add_dulint_literal(
/*=========================*/
	pars_info_t*	info,		/* in: info struct */
	const char*	name,		/* in: name */
	dulint		val);		/* in: value */
/********************************************************************
Add user function. */

void
pars_info_add_function(
/*===================*/
	pars_info_t*		info,	/* in: info struct */
	const char*		name,	/* in: function name */
	pars_user_func_cb_t	func,	/* in: function address */
	void*			arg);	/* in: user-supplied argument */

/********************************************************************
Add bound id. */

void
pars_info_add_id(
/*=============*/
	pars_info_t*	info,		/* in: info struct */
	const char*	name,		/* in: name */
	const char*	id);		/* in: id */

/********************************************************************
Get user function with the given name.*/

pars_user_func_t*
pars_info_get_user_func(
/*====================*/
					/* out: user func, or NULL if not
					found */
	pars_info_t*		info,	/* in: info struct */
	const char*		name);	/* in: function name to find*/

/********************************************************************
Get bound literal with the given name.*/

pars_bound_lit_t*
pars_info_get_bound_lit(
/*====================*/
					/* out: bound literal, or NULL if
					not found */
	pars_info_t*		info,	/* in: info struct */
	const char*		name);	/* in: bound literal name to find */

/********************************************************************
Get bound id with the given name.*/

pars_bound_id_t*
pars_info_get_bound_id(
/*===================*/
					/* out: bound id, or NULL if not
					found */
	pars_info_t*		info,	/* in: info struct */
	const char*		name);	/* in: bound id name to find */


/* Extra information supplied for pars_sql(). */
struct pars_info_struct {
	mem_heap_t*	heap;		/* our own memory heap */

	ib_vector_t*	funcs;		/* user functions, or NUll
					(pars_user_func_t*) */
	ib_vector_t*	bound_lits;	/* bound literals, or NULL
					(pars_bound_lit_t*) */
	ib_vector_t*	bound_ids;	/* bound ids, or NULL
					(pars_bound_id_t*) */

	ibool		graph_owns_us;	/* if TRUE (which is the default),
					que_graph_free() will free us */
};

/* User-supplied function and argument. */
struct pars_user_func_struct {
	const char*		name;		/* function name */
	pars_user_func_cb_t	func;		/* function address */
	void*			arg;		/* user-supplied argument */
};

/* Bound literal. */
struct pars_bound_lit_struct {
	const char*	name;		/* name */
	const void*	address;	/* address */
	ulint		length;		/* length of data */
	ulint		type;		/* type, e.g. DATA_FIXBINARY */
	ulint		prtype;		/* precise type, e.g. DATA_UNSIGNED */
};

/* Bound id. */
struct pars_bound_id_struct {
	const char*	name;		/* name */
	const char*	id;		/* id */
};

/* Struct used to denote a reserved word in a parsing tree */
struct pars_res_word_struct{
	int	code;	/* the token code for the reserved word from
			pars0grm.h */
};

/* A predefined function or operator node in a parsing tree; this construct
is also used for some non-functions like the assignment ':=' */
struct func_node_struct{
	que_common_t	common;	/* type: QUE_NODE_FUNC */
	int		func;	/* token code of the function name */
	ulint		class;	/* class of the function */
	que_node_t*	args;	/* argument(s) of the function */
	UT_LIST_NODE_T(func_node_t) cond_list;
				/* list of comparison conditions; defined
				only for comparison operator nodes except,
				presently, for OPT_SCROLL_TYPE ones */
	UT_LIST_NODE_T(func_node_t) func_node_list;
				/* list of function nodes in a parsed
				query graph */
};

/* An order-by node in a select */
struct order_node_struct{
	que_common_t	common;	/* type: QUE_NODE_ORDER */
	sym_node_t*	column;	/* order-by column */
	ibool		asc;	/* TRUE if ascending, FALSE if descending */
};

/* Procedure definition node */
struct proc_node_struct{
	que_common_t	common;		/* type: QUE_NODE_PROC */
	sym_node_t*	proc_id;	/* procedure name symbol in the symbol
					table of this same procedure */
	sym_node_t*	param_list;	/* input and output parameters */
	que_node_t*	stat_list;	/* statement list */
	sym_tab_t*	sym_tab;	/* symbol table of this procedure */
};

/* elsif-element node */
struct elsif_node_struct{
	que_common_t	common;		/* type: QUE_NODE_ELSIF */
	que_node_t*	cond;		/* if condition */
	que_node_t*	stat_list;	/* statement list */
};

/* if-statement node */
struct if_node_struct{
	que_common_t	common;		/* type: QUE_NODE_IF */
	que_node_t*	cond;		/* if condition */
	que_node_t*	stat_list;	/* statement list */
	que_node_t*	else_part;	/* else-part statement list */
	elsif_node_t*	elsif_list;	/* elsif element list */
};

/* while-statement node */
struct while_node_struct{
	que_common_t	common;		/* type: QUE_NODE_WHILE */
	que_node_t*	cond;		/* while condition */
	que_node_t*	stat_list;	/* statement list */
};

/* for-loop-statement node */
struct for_node_struct{
	que_common_t	common;		/* type: QUE_NODE_FOR */
	sym_node_t*	loop_var;	/* loop variable: this is the
					dereferenced symbol from the
					variable declarations, not the
					symbol occurrence in the for loop
					definition */
	que_node_t*	loop_start_limit;/* initial value of loop variable */
	que_node_t*	loop_end_limit;	/* end value of loop variable */
	lint		loop_end_value;	/* evaluated value for the end value:
					it is calculated only when the loop
					is entered, and will not change within
					the loop */
	que_node_t*	stat_list;	/* statement list */
};

/* exit statement node */
struct exit_node_struct{
	que_common_t	common;		/* type: QUE_NODE_EXIT */
};

/* return-statement node */
struct return_node_struct{
	que_common_t	common;		/* type: QUE_NODE_RETURN */
};

/* Assignment statement node */
struct assign_node_struct{
	que_common_t	common;		/* type: QUE_NODE_ASSIGNMENT */
	sym_node_t*	var;		/* variable to set */
	que_node_t*	val;		/* value to assign */
};

/* Column assignment node */
struct col_assign_node_struct{
	que_common_t	common;		/* type: QUE_NODE_COL_ASSIGN */
	sym_node_t*	col;		/* column to set */
	que_node_t*	val;		/* value to assign */
};

/* Classes of functions */
#define PARS_FUNC_ARITH		1	/* +, -, *, / */
#define	PARS_FUNC_LOGICAL	2
#define PARS_FUNC_CMP		3
#define	PARS_FUNC_PREDEFINED	4	/* TO_NUMBER, SUBSTR, ... */
#define	PARS_FUNC_AGGREGATE	5	/* COUNT, DISTINCT, SUM */
#define	PARS_FUNC_OTHER		6	/* these are not real functions,
					e.g., := */

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

#endif
