You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2197 lines
54 KiB

20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
  1. /*****************************************************************************
  2. Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /******************************************************
  14. SQL parser
  15. Created 11/19/1996 Heikki Tuuri
  16. *******************************************************/
  17. /* Historical note: Innobase executed its first SQL string (CREATE TABLE)
  18. on 1/27/1998 */
  19. #include "pars0pars.h"
  20. #ifdef UNIV_NONINL
  21. #include "pars0pars.ic"
  22. #endif
  23. #include "row0sel.h"
  24. #include "row0ins.h"
  25. #include "row0upd.h"
  26. #include "dict0dict.h"
  27. #include "dict0mem.h"
  28. #include "dict0crea.h"
  29. #include "que0que.h"
  30. #include "pars0grm.h"
  31. #include "pars0opt.h"
  32. #include "data0data.h"
  33. #include "data0type.h"
  34. #include "trx0trx.h"
  35. #include "trx0roll.h"
  36. #include "lock0lock.h"
  37. #include "eval0eval.h"
  38. #ifdef UNIV_SQL_DEBUG
  39. /* If the following is set TRUE, the lexer will print the SQL string
  40. as it tokenizes it */
  41. ibool pars_print_lexed = FALSE;
  42. #endif /* UNIV_SQL_DEBUG */
  43. /* Global variable used while parsing a single procedure or query : the code is
  44. NOT re-entrant */
  45. UNIV_INTERN sym_tab_t* pars_sym_tab_global;
  46. /* Global variables used to denote certain reserved words, used in
  47. constructing the parsing tree */
  48. UNIV_INTERN pars_res_word_t pars_to_char_token = {PARS_TO_CHAR_TOKEN};
  49. UNIV_INTERN pars_res_word_t pars_to_number_token = {PARS_TO_NUMBER_TOKEN};
  50. UNIV_INTERN pars_res_word_t pars_to_binary_token = {PARS_TO_BINARY_TOKEN};
  51. UNIV_INTERN pars_res_word_t pars_binary_to_number_token = {PARS_BINARY_TO_NUMBER_TOKEN};
  52. UNIV_INTERN pars_res_word_t pars_substr_token = {PARS_SUBSTR_TOKEN};
  53. UNIV_INTERN pars_res_word_t pars_replstr_token = {PARS_REPLSTR_TOKEN};
  54. UNIV_INTERN pars_res_word_t pars_concat_token = {PARS_CONCAT_TOKEN};
  55. UNIV_INTERN pars_res_word_t pars_instr_token = {PARS_INSTR_TOKEN};
  56. UNIV_INTERN pars_res_word_t pars_length_token = {PARS_LENGTH_TOKEN};
  57. UNIV_INTERN pars_res_word_t pars_sysdate_token = {PARS_SYSDATE_TOKEN};
  58. UNIV_INTERN pars_res_word_t pars_printf_token = {PARS_PRINTF_TOKEN};
  59. UNIV_INTERN pars_res_word_t pars_assert_token = {PARS_ASSERT_TOKEN};
  60. UNIV_INTERN pars_res_word_t pars_rnd_token = {PARS_RND_TOKEN};
  61. UNIV_INTERN pars_res_word_t pars_rnd_str_token = {PARS_RND_STR_TOKEN};
  62. UNIV_INTERN pars_res_word_t pars_count_token = {PARS_COUNT_TOKEN};
  63. UNIV_INTERN pars_res_word_t pars_sum_token = {PARS_SUM_TOKEN};
  64. UNIV_INTERN pars_res_word_t pars_distinct_token = {PARS_DISTINCT_TOKEN};
  65. UNIV_INTERN pars_res_word_t pars_binary_token = {PARS_BINARY_TOKEN};
  66. UNIV_INTERN pars_res_word_t pars_blob_token = {PARS_BLOB_TOKEN};
  67. UNIV_INTERN pars_res_word_t pars_int_token = {PARS_INT_TOKEN};
  68. UNIV_INTERN pars_res_word_t pars_char_token = {PARS_CHAR_TOKEN};
  69. UNIV_INTERN pars_res_word_t pars_float_token = {PARS_FLOAT_TOKEN};
  70. UNIV_INTERN pars_res_word_t pars_update_token = {PARS_UPDATE_TOKEN};
  71. UNIV_INTERN pars_res_word_t pars_asc_token = {PARS_ASC_TOKEN};
  72. UNIV_INTERN pars_res_word_t pars_desc_token = {PARS_DESC_TOKEN};
  73. UNIV_INTERN pars_res_word_t pars_open_token = {PARS_OPEN_TOKEN};
  74. UNIV_INTERN pars_res_word_t pars_close_token = {PARS_CLOSE_TOKEN};
  75. UNIV_INTERN pars_res_word_t pars_share_token = {PARS_SHARE_TOKEN};
  76. UNIV_INTERN pars_res_word_t pars_unique_token = {PARS_UNIQUE_TOKEN};
  77. UNIV_INTERN pars_res_word_t pars_clustered_token = {PARS_CLUSTERED_TOKEN};
  78. /* Global variable used to denote the '*' in SELECT * FROM.. */
  79. #define PARS_STAR_DENOTER 12345678
  80. UNIV_INTERN ulint pars_star_denoter = PARS_STAR_DENOTER;
  81. /*************************************************************************
  82. Determines the class of a function code.
  83. @return function class: PARS_FUNC_ARITH, ... */
  84. static
  85. ulint
  86. pars_func_get_class(
  87. /*================*/
  88. int func) /*!< in: function code: '=', PARS_GE_TOKEN, ... */
  89. {
  90. switch (func) {
  91. case '+': case '-': case '*': case '/':
  92. return(PARS_FUNC_ARITH);
  93. case '=': case '<': case '>':
  94. case PARS_GE_TOKEN: case PARS_LE_TOKEN: case PARS_NE_TOKEN:
  95. return(PARS_FUNC_CMP);
  96. case PARS_AND_TOKEN: case PARS_OR_TOKEN: case PARS_NOT_TOKEN:
  97. return(PARS_FUNC_LOGICAL);
  98. case PARS_COUNT_TOKEN: case PARS_SUM_TOKEN:
  99. return(PARS_FUNC_AGGREGATE);
  100. case PARS_TO_CHAR_TOKEN:
  101. case PARS_TO_NUMBER_TOKEN:
  102. case PARS_TO_BINARY_TOKEN:
  103. case PARS_BINARY_TO_NUMBER_TOKEN:
  104. case PARS_SUBSTR_TOKEN:
  105. case PARS_CONCAT_TOKEN:
  106. case PARS_LENGTH_TOKEN:
  107. case PARS_INSTR_TOKEN:
  108. case PARS_SYSDATE_TOKEN:
  109. case PARS_NOTFOUND_TOKEN:
  110. case PARS_PRINTF_TOKEN:
  111. case PARS_ASSERT_TOKEN:
  112. case PARS_RND_TOKEN:
  113. case PARS_RND_STR_TOKEN:
  114. case PARS_REPLSTR_TOKEN:
  115. return(PARS_FUNC_PREDEFINED);
  116. default:
  117. return(PARS_FUNC_OTHER);
  118. }
  119. }
  120. /*************************************************************************
  121. Parses an operator or predefined function expression.
  122. @return own: function node in a query tree */
  123. static
  124. func_node_t*
  125. pars_func_low(
  126. /*==========*/
  127. int func, /*!< in: function token code */
  128. que_node_t* arg) /*!< in: first argument in the argument list */
  129. {
  130. func_node_t* node;
  131. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(func_node_t));
  132. node->common.type = QUE_NODE_FUNC;
  133. dfield_set_data(&(node->common.val), NULL, 0);
  134. node->common.val_buf_size = 0;
  135. node->func = func;
  136. node->class = pars_func_get_class(func);
  137. node->args = arg;
  138. UT_LIST_ADD_LAST(func_node_list, pars_sym_tab_global->func_node_list,
  139. node);
  140. return(node);
  141. }
  142. /*************************************************************************
  143. Parses a function expression.
  144. @return own: function node in a query tree */
  145. UNIV_INTERN
  146. func_node_t*
  147. pars_func(
  148. /*======*/
  149. que_node_t* res_word,/*!< in: function name reserved word */
  150. que_node_t* arg) /*!< in: first argument in the argument list */
  151. {
  152. return(pars_func_low(((pars_res_word_t*)res_word)->code, arg));
  153. }
  154. /*************************************************************************
  155. Parses an operator expression.
  156. @return own: function node in a query tree */
  157. UNIV_INTERN
  158. func_node_t*
  159. pars_op(
  160. /*====*/
  161. int func, /*!< in: operator token code */
  162. que_node_t* arg1, /*!< in: first argument */
  163. que_node_t* arg2) /*!< in: second argument or NULL for an unary
  164. operator */
  165. {
  166. que_node_list_add_last(NULL, arg1);
  167. if (arg2) {
  168. que_node_list_add_last(arg1, arg2);
  169. }
  170. return(pars_func_low(func, arg1));
  171. }
  172. /*************************************************************************
  173. Parses an ORDER BY clause. Order by a single column only is supported.
  174. @return own: order-by node in a query tree */
  175. UNIV_INTERN
  176. order_node_t*
  177. pars_order_by(
  178. /*==========*/
  179. sym_node_t* column, /*!< in: column name */
  180. pars_res_word_t* asc) /*!< in: &pars_asc_token or pars_desc_token */
  181. {
  182. order_node_t* node;
  183. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(order_node_t));
  184. node->common.type = QUE_NODE_ORDER;
  185. node->column = column;
  186. if (asc == &pars_asc_token) {
  187. node->asc = TRUE;
  188. } else {
  189. ut_a(asc == &pars_desc_token);
  190. node->asc = FALSE;
  191. }
  192. return(node);
  193. }
  194. /*************************************************************************
  195. Determine if a data type is a built-in string data type of the InnoDB
  196. SQL parser.
  197. @return TRUE if string data type */
  198. static
  199. ibool
  200. pars_is_string_type(
  201. /*================*/
  202. ulint mtype) /*!< in: main data type */
  203. {
  204. switch (mtype) {
  205. case DATA_VARCHAR: case DATA_CHAR:
  206. case DATA_FIXBINARY: case DATA_BINARY:
  207. return(TRUE);
  208. }
  209. return(FALSE);
  210. }
  211. /*************************************************************************
  212. Resolves the data type of a function in an expression. The argument data
  213. types must already be resolved. */
  214. static
  215. void
  216. pars_resolve_func_data_type(
  217. /*========================*/
  218. func_node_t* node) /*!< in: function node */
  219. {
  220. que_node_t* arg;
  221. ut_a(que_node_get_type(node) == QUE_NODE_FUNC);
  222. arg = node->args;
  223. switch (node->func) {
  224. case PARS_SUM_TOKEN:
  225. case '+': case '-': case '*': case '/':
  226. /* Inherit the data type from the first argument (which must
  227. not be the SQL null literal whose type is DATA_ERROR) */
  228. dtype_copy(que_node_get_data_type(node),
  229. que_node_get_data_type(arg));
  230. ut_a(dtype_get_mtype(que_node_get_data_type(node))
  231. == DATA_INT);
  232. break;
  233. case PARS_COUNT_TOKEN:
  234. ut_a(arg);
  235. dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
  236. break;
  237. case PARS_TO_CHAR_TOKEN:
  238. case PARS_RND_STR_TOKEN:
  239. ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
  240. dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
  241. DATA_ENGLISH, 0);
  242. break;
  243. case PARS_TO_BINARY_TOKEN:
  244. if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
  245. dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
  246. DATA_ENGLISH, 0);
  247. } else {
  248. dtype_set(que_node_get_data_type(node), DATA_BINARY,
  249. 0, 0);
  250. }
  251. break;
  252. case PARS_TO_NUMBER_TOKEN:
  253. case PARS_BINARY_TO_NUMBER_TOKEN:
  254. case PARS_LENGTH_TOKEN:
  255. case PARS_INSTR_TOKEN:
  256. ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
  257. dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
  258. break;
  259. case PARS_SYSDATE_TOKEN:
  260. ut_a(arg == NULL);
  261. dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
  262. break;
  263. case PARS_SUBSTR_TOKEN:
  264. case PARS_CONCAT_TOKEN:
  265. ut_a(pars_is_string_type(que_node_get_data_type(arg)->mtype));
  266. dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
  267. DATA_ENGLISH, 0);
  268. break;
  269. case '>': case '<': case '=':
  270. case PARS_GE_TOKEN:
  271. case PARS_LE_TOKEN:
  272. case PARS_NE_TOKEN:
  273. case PARS_AND_TOKEN:
  274. case PARS_OR_TOKEN:
  275. case PARS_NOT_TOKEN:
  276. case PARS_NOTFOUND_TOKEN:
  277. /* We currently have no iboolean type: use integer type */
  278. dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
  279. break;
  280. case PARS_RND_TOKEN:
  281. ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
  282. dtype_set(que_node_get_data_type(node), DATA_INT, 0, 4);
  283. break;
  284. default:
  285. ut_error;
  286. }
  287. }
  288. /*************************************************************************
  289. Resolves the meaning of variables in an expression and the data types of
  290. functions. It is an error if some identifier cannot be resolved here. */
  291. static
  292. void
  293. pars_resolve_exp_variables_and_types(
  294. /*=================================*/
  295. sel_node_t* select_node, /*!< in: select node or NULL; if
  296. this is not NULL then the variable
  297. sym nodes are added to the
  298. copy_variables list of select_node */
  299. que_node_t* exp_node) /*!< in: expression */
  300. {
  301. func_node_t* func_node;
  302. que_node_t* arg;
  303. sym_node_t* sym_node;
  304. sym_node_t* node;
  305. ut_a(exp_node);
  306. if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
  307. func_node = exp_node;
  308. arg = func_node->args;
  309. while (arg) {
  310. pars_resolve_exp_variables_and_types(select_node, arg);
  311. arg = que_node_get_next(arg);
  312. }
  313. pars_resolve_func_data_type(func_node);
  314. return;
  315. }
  316. ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);
  317. sym_node = exp_node;
  318. if (sym_node->resolved) {
  319. return;
  320. }
  321. /* Not resolved yet: look in the symbol table for a variable
  322. or a cursor or a function with the same name */
  323. node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
  324. while (node) {
  325. if (node->resolved
  326. && ((node->token_type == SYM_VAR)
  327. || (node->token_type == SYM_CURSOR)
  328. || (node->token_type == SYM_FUNCTION))
  329. && node->name
  330. && (sym_node->name_len == node->name_len)
  331. && (ut_memcmp(sym_node->name, node->name,
  332. node->name_len) == 0)) {
  333. /* Found a variable or a cursor declared with
  334. the same name */
  335. break;
  336. }
  337. node = UT_LIST_GET_NEXT(sym_list, node);
  338. }
  339. if (!node) {
  340. fprintf(stderr, "PARSER ERROR: Unresolved identifier %s\n",
  341. sym_node->name);
  342. }
  343. ut_a(node);
  344. sym_node->resolved = TRUE;
  345. sym_node->token_type = SYM_IMPLICIT_VAR;
  346. sym_node->alias = node;
  347. sym_node->indirection = node;
  348. if (select_node) {
  349. UT_LIST_ADD_LAST(col_var_list, select_node->copy_variables,
  350. sym_node);
  351. }
  352. dfield_set_type(que_node_get_val(sym_node),
  353. que_node_get_data_type(node));
  354. }
  355. /*************************************************************************
  356. Resolves the meaning of variables in an expression list. It is an error if
  357. some identifier cannot be resolved here. Resolves also the data types of
  358. functions. */
  359. static
  360. void
  361. pars_resolve_exp_list_variables_and_types(
  362. /*======================================*/
  363. sel_node_t* select_node, /*!< in: select node or NULL */
  364. que_node_t* exp_node) /*!< in: expression list first node, or
  365. NULL */
  366. {
  367. while (exp_node) {
  368. pars_resolve_exp_variables_and_types(select_node, exp_node);
  369. exp_node = que_node_get_next(exp_node);
  370. }
  371. }
  372. /*************************************************************************
  373. Resolves the columns in an expression. */
  374. static
  375. void
  376. pars_resolve_exp_columns(
  377. /*=====================*/
  378. sym_node_t* table_node, /*!< in: first node in a table list */
  379. que_node_t* exp_node) /*!< in: expression */
  380. {
  381. func_node_t* func_node;
  382. que_node_t* arg;
  383. sym_node_t* sym_node;
  384. dict_table_t* table;
  385. sym_node_t* t_node;
  386. ulint n_cols;
  387. ulint i;
  388. ut_a(exp_node);
  389. if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
  390. func_node = exp_node;
  391. arg = func_node->args;
  392. while (arg) {
  393. pars_resolve_exp_columns(table_node, arg);
  394. arg = que_node_get_next(arg);
  395. }
  396. return;
  397. }
  398. ut_a(que_node_get_type(exp_node) == QUE_NODE_SYMBOL);
  399. sym_node = exp_node;
  400. if (sym_node->resolved) {
  401. return;
  402. }
  403. /* Not resolved yet: look in the table list for a column with the
  404. same name */
  405. t_node = table_node;
  406. while (t_node) {
  407. table = t_node->table;
  408. n_cols = dict_table_get_n_cols(table);
  409. for (i = 0; i < n_cols; i++) {
  410. const dict_col_t* col
  411. = dict_table_get_nth_col(table, i);
  412. const char* col_name
  413. = dict_table_get_col_name(table, i);
  414. if ((sym_node->name_len == ut_strlen(col_name))
  415. && (0 == ut_memcmp(sym_node->name, col_name,
  416. sym_node->name_len))) {
  417. /* Found */
  418. sym_node->resolved = TRUE;
  419. sym_node->token_type = SYM_COLUMN;
  420. sym_node->table = table;
  421. sym_node->col_no = i;
  422. sym_node->prefetch_buf = NULL;
  423. dict_col_copy_type(
  424. col,
  425. dfield_get_type(&sym_node
  426. ->common.val));
  427. return;
  428. }
  429. }
  430. t_node = que_node_get_next(t_node);
  431. }
  432. }
  433. /*************************************************************************
  434. Resolves the meaning of columns in an expression list. */
  435. static
  436. void
  437. pars_resolve_exp_list_columns(
  438. /*==========================*/
  439. sym_node_t* table_node, /*!< in: first node in a table list */
  440. que_node_t* exp_node) /*!< in: expression list first node, or
  441. NULL */
  442. {
  443. while (exp_node) {
  444. pars_resolve_exp_columns(table_node, exp_node);
  445. exp_node = que_node_get_next(exp_node);
  446. }
  447. }
  448. /*************************************************************************
  449. Retrieves the table definition for a table name id. */
  450. static
  451. void
  452. pars_retrieve_table_def(
  453. /*====================*/
  454. sym_node_t* sym_node) /*!< in: table node */
  455. {
  456. const char* table_name;
  457. ut_a(sym_node);
  458. ut_a(que_node_get_type(sym_node) == QUE_NODE_SYMBOL);
  459. sym_node->resolved = TRUE;
  460. sym_node->token_type = SYM_TABLE;
  461. table_name = (const char*) sym_node->name;
  462. sym_node->table = dict_table_get_low(table_name);
  463. ut_a(sym_node->table);
  464. }
  465. /*************************************************************************
  466. Retrieves the table definitions for a list of table name ids.
  467. @return number of tables */
  468. static
  469. ulint
  470. pars_retrieve_table_list_defs(
  471. /*==========================*/
  472. sym_node_t* sym_node) /*!< in: first table node in list */
  473. {
  474. ulint count = 0;
  475. if (sym_node == NULL) {
  476. return(count);
  477. }
  478. while (sym_node) {
  479. pars_retrieve_table_def(sym_node);
  480. count++;
  481. sym_node = que_node_get_next(sym_node);
  482. }
  483. return(count);
  484. }
  485. /*************************************************************************
  486. Adds all columns to the select list if the query is SELECT * FROM ... */
  487. static
  488. void
  489. pars_select_all_columns(
  490. /*====================*/
  491. sel_node_t* select_node) /*!< in: select node already containing
  492. the table list */
  493. {
  494. sym_node_t* col_node;
  495. sym_node_t* table_node;
  496. dict_table_t* table;
  497. ulint i;
  498. select_node->select_list = NULL;
  499. table_node = select_node->table_list;
  500. while (table_node) {
  501. table = table_node->table;
  502. for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
  503. const char* col_name = dict_table_get_col_name(
  504. table, i);
  505. col_node = sym_tab_add_id(pars_sym_tab_global,
  506. (byte*)col_name,
  507. ut_strlen(col_name));
  508. select_node->select_list = que_node_list_add_last(
  509. select_node->select_list, col_node);
  510. }
  511. table_node = que_node_get_next(table_node);
  512. }
  513. }
  514. /*************************************************************************
  515. Parses a select list; creates a query graph node for the whole SELECT
  516. statement.
  517. @return own: select node in a query tree */
  518. UNIV_INTERN
  519. sel_node_t*
  520. pars_select_list(
  521. /*=============*/
  522. que_node_t* select_list, /*!< in: select list */
  523. sym_node_t* into_list) /*!< in: variables list or NULL */
  524. {
  525. sel_node_t* node;
  526. node = sel_node_create(pars_sym_tab_global->heap);
  527. node->select_list = select_list;
  528. node->into_list = into_list;
  529. pars_resolve_exp_list_variables_and_types(NULL, into_list);
  530. return(node);
  531. }
  532. /*************************************************************************
  533. Checks if the query is an aggregate query, in which case the selct list must
  534. contain only aggregate function items. */
  535. static
  536. void
  537. pars_check_aggregate(
  538. /*=================*/
  539. sel_node_t* select_node) /*!< in: select node already containing
  540. the select list */
  541. {
  542. que_node_t* exp_node;
  543. func_node_t* func_node;
  544. ulint n_nodes = 0;
  545. ulint n_aggregate_nodes = 0;
  546. exp_node = select_node->select_list;
  547. while (exp_node) {
  548. n_nodes++;
  549. if (que_node_get_type(exp_node) == QUE_NODE_FUNC) {
  550. func_node = exp_node;
  551. if (func_node->class == PARS_FUNC_AGGREGATE) {
  552. n_aggregate_nodes++;
  553. }
  554. }
  555. exp_node = que_node_get_next(exp_node);
  556. }
  557. if (n_aggregate_nodes > 0) {
  558. ut_a(n_nodes == n_aggregate_nodes);
  559. select_node->is_aggregate = TRUE;
  560. } else {
  561. select_node->is_aggregate = FALSE;
  562. }
  563. }
  564. /*************************************************************************
  565. Parses a select statement.
  566. @return own: select node in a query tree */
  567. UNIV_INTERN
  568. sel_node_t*
  569. pars_select_statement(
  570. /*==================*/
  571. sel_node_t* select_node, /*!< in: select node already containing
  572. the select list */
  573. sym_node_t* table_list, /*!< in: table list */
  574. que_node_t* search_cond, /*!< in: search condition or NULL */
  575. pars_res_word_t* for_update, /*!< in: NULL or &pars_update_token */
  576. pars_res_word_t* lock_shared, /*!< in: NULL or &pars_share_token */
  577. order_node_t* order_by) /*!< in: NULL or an order-by node */
  578. {
  579. select_node->state = SEL_NODE_OPEN;
  580. select_node->table_list = table_list;
  581. select_node->n_tables = pars_retrieve_table_list_defs(table_list);
  582. if (select_node->select_list == &pars_star_denoter) {
  583. /* SELECT * FROM ... */
  584. pars_select_all_columns(select_node);
  585. }
  586. if (select_node->into_list) {
  587. ut_a(que_node_list_get_len(select_node->into_list)
  588. == que_node_list_get_len(select_node->select_list));
  589. }
  590. UT_LIST_INIT(select_node->copy_variables);
  591. pars_resolve_exp_list_columns(table_list, select_node->select_list);
  592. pars_resolve_exp_list_variables_and_types(select_node,
  593. select_node->select_list);
  594. pars_check_aggregate(select_node);
  595. select_node->search_cond = search_cond;
  596. if (search_cond) {
  597. pars_resolve_exp_columns(table_list, search_cond);
  598. pars_resolve_exp_variables_and_types(select_node, search_cond);
  599. }
  600. if (for_update) {
  601. ut_a(!lock_shared);
  602. select_node->set_x_locks = TRUE;
  603. select_node->row_lock_mode = LOCK_X;
  604. select_node->consistent_read = FALSE;
  605. select_node->read_view = NULL;
  606. } else if (lock_shared){
  607. select_node->set_x_locks = FALSE;
  608. select_node->row_lock_mode = LOCK_S;
  609. select_node->consistent_read = FALSE;
  610. select_node->read_view = NULL;
  611. } else {
  612. select_node->set_x_locks = FALSE;
  613. select_node->row_lock_mode = LOCK_S;
  614. select_node->consistent_read = TRUE;
  615. }
  616. select_node->order_by = order_by;
  617. if (order_by) {
  618. pars_resolve_exp_columns(table_list, order_by->column);
  619. }
  620. /* The final value of the following fields depend on the environment
  621. where the select statement appears: */
  622. select_node->can_get_updated = FALSE;
  623. select_node->explicit_cursor = NULL;
  624. opt_search_plan(select_node);
  625. return(select_node);
  626. }
  627. /*************************************************************************
  628. Parses a cursor declaration.
  629. @return sym_node */
  630. UNIV_INTERN
  631. que_node_t*
  632. pars_cursor_declaration(
  633. /*====================*/
  634. sym_node_t* sym_node, /*!< in: cursor id node in the symbol
  635. table */
  636. sel_node_t* select_node) /*!< in: select node */
  637. {
  638. sym_node->resolved = TRUE;
  639. sym_node->token_type = SYM_CURSOR;
  640. sym_node->cursor_def = select_node;
  641. select_node->state = SEL_NODE_CLOSED;
  642. select_node->explicit_cursor = sym_node;
  643. return(sym_node);
  644. }
  645. /*************************************************************************
  646. Parses a function declaration.
  647. @return sym_node */
  648. UNIV_INTERN
  649. que_node_t*
  650. pars_function_declaration(
  651. /*======================*/
  652. sym_node_t* sym_node) /*!< in: function id node in the symbol
  653. table */
  654. {
  655. sym_node->resolved = TRUE;
  656. sym_node->token_type = SYM_FUNCTION;
  657. /* Check that the function exists. */
  658. ut_a(pars_info_get_user_func(pars_sym_tab_global->info,
  659. sym_node->name));
  660. return(sym_node);
  661. }
  662. /*************************************************************************
  663. Parses a delete or update statement start.
  664. @return own: update node in a query tree */
  665. UNIV_INTERN
  666. upd_node_t*
  667. pars_update_statement_start(
  668. /*========================*/
  669. ibool is_delete, /*!< in: TRUE if delete */
  670. sym_node_t* table_sym, /*!< in: table name node */
  671. col_assign_node_t* col_assign_list)/*!< in: column assignment list, NULL
  672. if delete */
  673. {
  674. upd_node_t* node;
  675. node = upd_node_create(pars_sym_tab_global->heap);
  676. node->is_delete = is_delete;
  677. node->table_sym = table_sym;
  678. node->col_assign_list = col_assign_list;
  679. return(node);
  680. }
  681. /*************************************************************************
  682. Parses a column assignment in an update.
  683. @return column assignment node */
  684. UNIV_INTERN
  685. col_assign_node_t*
  686. pars_column_assignment(
  687. /*===================*/
  688. sym_node_t* column, /*!< in: column to assign */
  689. que_node_t* exp) /*!< in: value to assign */
  690. {
  691. col_assign_node_t* node;
  692. node = mem_heap_alloc(pars_sym_tab_global->heap,
  693. sizeof(col_assign_node_t));
  694. node->common.type = QUE_NODE_COL_ASSIGNMENT;
  695. node->col = column;
  696. node->val = exp;
  697. return(node);
  698. }
  699. /*************************************************************************
  700. Processes an update node assignment list. */
  701. static
  702. void
  703. pars_process_assign_list(
  704. /*=====================*/
  705. upd_node_t* node) /*!< in: update node */
  706. {
  707. col_assign_node_t* col_assign_list;
  708. sym_node_t* table_sym;
  709. col_assign_node_t* assign_node;
  710. upd_field_t* upd_field;
  711. dict_index_t* clust_index;
  712. sym_node_t* col_sym;
  713. ulint changes_ord_field;
  714. ulint changes_field_size;
  715. ulint n_assigns;
  716. ulint i;
  717. table_sym = node->table_sym;
  718. col_assign_list = node->col_assign_list;
  719. clust_index = dict_table_get_first_index(node->table);
  720. assign_node = col_assign_list;
  721. n_assigns = 0;
  722. while (assign_node) {
  723. pars_resolve_exp_columns(table_sym, assign_node->col);
  724. pars_resolve_exp_columns(table_sym, assign_node->val);
  725. pars_resolve_exp_variables_and_types(NULL, assign_node->val);
  726. #if 0
  727. ut_a(dtype_get_mtype(
  728. dfield_get_type(que_node_get_val(
  729. assign_node->col)))
  730. == dtype_get_mtype(
  731. dfield_get_type(que_node_get_val(
  732. assign_node->val))));
  733. #endif
  734. /* Add to the update node all the columns found in assignment
  735. values as columns to copy: therefore, TRUE */
  736. opt_find_all_cols(TRUE, clust_index, &(node->columns), NULL,
  737. assign_node->val);
  738. n_assigns++;
  739. assign_node = que_node_get_next(assign_node);
  740. }
  741. node->update = upd_create(n_assigns, pars_sym_tab_global->heap);
  742. assign_node = col_assign_list;
  743. changes_field_size = UPD_NODE_NO_SIZE_CHANGE;
  744. for (i = 0; i < n_assigns; i++) {
  745. upd_field = upd_get_nth_field(node->update, i);
  746. col_sym = assign_node->col;
  747. upd_field_set_field_no(upd_field, dict_index_get_nth_col_pos(
  748. clust_index, col_sym->col_no),
  749. clust_index, NULL);
  750. upd_field->exp = assign_node->val;
  751. if (!dict_col_get_fixed_size(
  752. dict_index_get_nth_col(clust_index,
  753. upd_field->field_no),
  754. dict_table_is_comp(node->table))) {
  755. changes_field_size = 0;
  756. }
  757. assign_node = que_node_get_next(assign_node);
  758. }
  759. /* Find out if the update can modify an ordering field in any index */
  760. changes_ord_field = UPD_NODE_NO_ORD_CHANGE;
  761. if (row_upd_changes_some_index_ord_field_binary(node->table,
  762. node->update)) {
  763. changes_ord_field = 0;
  764. }
  765. node->cmpl_info = changes_ord_field | changes_field_size;
  766. }
  767. /*************************************************************************
  768. Parses an update or delete statement.
  769. @return own: update node in a query tree */
  770. UNIV_INTERN
  771. upd_node_t*
  772. pars_update_statement(
  773. /*==================*/
  774. upd_node_t* node, /*!< in: update node */
  775. sym_node_t* cursor_sym, /*!< in: pointer to a cursor entry in
  776. the symbol table or NULL */
  777. que_node_t* search_cond) /*!< in: search condition or NULL */
  778. {
  779. sym_node_t* table_sym;
  780. sel_node_t* sel_node;
  781. plan_t* plan;
  782. table_sym = node->table_sym;
  783. pars_retrieve_table_def(table_sym);
  784. node->table = table_sym->table;
  785. UT_LIST_INIT(node->columns);
  786. /* Make the single table node into a list of table nodes of length 1 */
  787. que_node_list_add_last(NULL, table_sym);
  788. if (cursor_sym) {
  789. pars_resolve_exp_variables_and_types(NULL, cursor_sym);
  790. sel_node = cursor_sym->alias->cursor_def;
  791. node->searched_update = FALSE;
  792. } else {
  793. sel_node = pars_select_list(NULL, NULL);
  794. pars_select_statement(sel_node, table_sym, search_cond, NULL,
  795. &pars_share_token, NULL);
  796. node->searched_update = TRUE;
  797. sel_node->common.parent = node;
  798. }
  799. node->select = sel_node;
  800. ut_a(!node->is_delete || (node->col_assign_list == NULL));
  801. ut_a(node->is_delete || (node->col_assign_list != NULL));
  802. if (node->is_delete) {
  803. node->cmpl_info = 0;
  804. } else {
  805. pars_process_assign_list(node);
  806. }
  807. if (node->searched_update) {
  808. node->has_clust_rec_x_lock = TRUE;
  809. sel_node->set_x_locks = TRUE;
  810. sel_node->row_lock_mode = LOCK_X;
  811. } else {
  812. node->has_clust_rec_x_lock = sel_node->set_x_locks;
  813. }
  814. ut_a(sel_node->n_tables == 1);
  815. ut_a(sel_node->consistent_read == FALSE);
  816. ut_a(sel_node->order_by == NULL);
  817. ut_a(sel_node->is_aggregate == FALSE);
  818. sel_node->can_get_updated = TRUE;
  819. node->state = UPD_NODE_UPDATE_CLUSTERED;
  820. plan = sel_node_get_nth_plan(sel_node, 0);
  821. plan->no_prefetch = TRUE;
  822. if (!dict_index_is_clust(plan->index)) {
  823. plan->must_get_clust = TRUE;
  824. node->pcur = &(plan->clust_pcur);
  825. } else {
  826. node->pcur = &(plan->pcur);
  827. }
  828. return(node);
  829. }
  830. /*************************************************************************
  831. Parses an insert statement.
  832. @return own: update node in a query tree */
  833. UNIV_INTERN
  834. ins_node_t*
  835. pars_insert_statement(
  836. /*==================*/
  837. sym_node_t* table_sym, /*!< in: table name node */
  838. que_node_t* values_list, /*!< in: value expression list or NULL */
  839. sel_node_t* select) /*!< in: select condition or NULL */
  840. {
  841. ins_node_t* node;
  842. dtuple_t* row;
  843. ulint ins_type;
  844. ut_a(values_list || select);
  845. ut_a(!values_list || !select);
  846. if (values_list) {
  847. ins_type = INS_VALUES;
  848. } else {
  849. ins_type = INS_SEARCHED;
  850. }
  851. pars_retrieve_table_def(table_sym);
  852. node = ins_node_create(ins_type, table_sym->table,
  853. pars_sym_tab_global->heap);
  854. row = dtuple_create(pars_sym_tab_global->heap,
  855. dict_table_get_n_cols(node->table));
  856. dict_table_copy_types(row, table_sym->table);
  857. ins_node_set_new_row(node, row);
  858. node->select = select;
  859. if (select) {
  860. select->common.parent = node;
  861. ut_a(que_node_list_get_len(select->select_list)
  862. == dict_table_get_n_user_cols(table_sym->table));
  863. }
  864. node->values_list = values_list;
  865. if (node->values_list) {
  866. pars_resolve_exp_list_variables_and_types(NULL, values_list);
  867. ut_a(que_node_list_get_len(values_list)
  868. == dict_table_get_n_user_cols(table_sym->table));
  869. }
  870. return(node);
  871. }
  872. /*************************************************************************
  873. Set the type of a dfield. */
  874. static
  875. void
  876. pars_set_dfield_type(
  877. /*=================*/
  878. dfield_t* dfield, /*!< in: dfield */
  879. pars_res_word_t* type, /*!< in: pointer to a type
  880. token */
  881. ulint len, /*!< in: length, or 0 */
  882. ibool is_unsigned, /*!< in: if TRUE, column is
  883. UNSIGNED. */
  884. ibool is_not_null) /*!< in: if TRUE, column is
  885. NOT NULL. */
  886. {
  887. ulint flags = 0;
  888. if (is_not_null) {
  889. flags |= DATA_NOT_NULL;
  890. }
  891. if (is_unsigned) {
  892. flags |= DATA_UNSIGNED;
  893. }
  894. if (type == &pars_int_token) {
  895. ut_a(len == 0);
  896. dtype_set(dfield_get_type(dfield), DATA_INT, flags, 4);
  897. } else if (type == &pars_char_token) {
  898. ut_a(len == 0);
  899. dtype_set(dfield_get_type(dfield), DATA_VARCHAR,
  900. DATA_ENGLISH | flags, 0);
  901. } else if (type == &pars_binary_token) {
  902. ut_a(len != 0);
  903. dtype_set(dfield_get_type(dfield), DATA_FIXBINARY,
  904. DATA_BINARY_TYPE | flags, len);
  905. } else if (type == &pars_blob_token) {
  906. ut_a(len == 0);
  907. dtype_set(dfield_get_type(dfield), DATA_BLOB,
  908. DATA_BINARY_TYPE | flags, 0);
  909. } else {
  910. ut_error;
  911. }
  912. }
  913. /*************************************************************************
  914. Parses a variable declaration.
  915. @return own: symbol table node of type SYM_VAR */
  916. UNIV_INTERN
  917. sym_node_t*
  918. pars_variable_declaration(
  919. /*======================*/
  920. sym_node_t* node, /*!< in: symbol table node allocated for the
  921. id of the variable */
  922. pars_res_word_t* type) /*!< in: pointer to a type token */
  923. {
  924. node->resolved = TRUE;
  925. node->token_type = SYM_VAR;
  926. node->param_type = PARS_NOT_PARAM;
  927. pars_set_dfield_type(que_node_get_val(node), type, 0, FALSE, FALSE);
  928. return(node);
  929. }
  930. /*************************************************************************
  931. Parses a procedure parameter declaration.
  932. @return own: symbol table node of type SYM_VAR */
  933. UNIV_INTERN
  934. sym_node_t*
  935. pars_parameter_declaration(
  936. /*=======================*/
  937. sym_node_t* node, /*!< in: symbol table node allocated for the
  938. id of the parameter */
  939. ulint param_type,
  940. /*!< in: PARS_INPUT or PARS_OUTPUT */
  941. pars_res_word_t* type) /*!< in: pointer to a type token */
  942. {
  943. ut_a((param_type == PARS_INPUT) || (param_type == PARS_OUTPUT));
  944. pars_variable_declaration(node, type);
  945. node->param_type = param_type;
  946. return(node);
  947. }
  948. /*************************************************************************
  949. Sets the parent field in a query node list. */
  950. static
  951. void
  952. pars_set_parent_in_list(
  953. /*====================*/
  954. que_node_t* node_list, /*!< in: first node in a list */
  955. que_node_t* parent) /*!< in: parent value to set in all
  956. nodes of the list */
  957. {
  958. que_common_t* common;
  959. common = node_list;
  960. while (common) {
  961. common->parent = parent;
  962. common = que_node_get_next(common);
  963. }
  964. }
  965. /*************************************************************************
  966. Parses an elsif element.
  967. @return elsif node */
  968. UNIV_INTERN
  969. elsif_node_t*
  970. pars_elsif_element(
  971. /*===============*/
  972. que_node_t* cond, /*!< in: if-condition */
  973. que_node_t* stat_list) /*!< in: statement list */
  974. {
  975. elsif_node_t* node;
  976. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(elsif_node_t));
  977. node->common.type = QUE_NODE_ELSIF;
  978. node->cond = cond;
  979. pars_resolve_exp_variables_and_types(NULL, cond);
  980. node->stat_list = stat_list;
  981. return(node);
  982. }
  983. /*************************************************************************
  984. Parses an if-statement.
  985. @return if-statement node */
  986. UNIV_INTERN
  987. if_node_t*
  988. pars_if_statement(
  989. /*==============*/
  990. que_node_t* cond, /*!< in: if-condition */
  991. que_node_t* stat_list, /*!< in: statement list */
  992. que_node_t* else_part) /*!< in: else-part statement list
  993. or elsif element list */
  994. {
  995. if_node_t* node;
  996. elsif_node_t* elsif_node;
  997. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(if_node_t));
  998. node->common.type = QUE_NODE_IF;
  999. node->cond = cond;
  1000. pars_resolve_exp_variables_and_types(NULL, cond);
  1001. node->stat_list = stat_list;
  1002. if (else_part && (que_node_get_type(else_part) == QUE_NODE_ELSIF)) {
  1003. /* There is a list of elsif conditions */
  1004. node->else_part = NULL;
  1005. node->elsif_list = else_part;
  1006. elsif_node = else_part;
  1007. while (elsif_node) {
  1008. pars_set_parent_in_list(elsif_node->stat_list, node);
  1009. elsif_node = que_node_get_next(elsif_node);
  1010. }
  1011. } else {
  1012. node->else_part = else_part;
  1013. node->elsif_list = NULL;
  1014. pars_set_parent_in_list(else_part, node);
  1015. }
  1016. pars_set_parent_in_list(stat_list, node);
  1017. return(node);
  1018. }
  1019. /*************************************************************************
  1020. Parses a while-statement.
  1021. @return while-statement node */
  1022. UNIV_INTERN
  1023. while_node_t*
  1024. pars_while_statement(
  1025. /*=================*/
  1026. que_node_t* cond, /*!< in: while-condition */
  1027. que_node_t* stat_list) /*!< in: statement list */
  1028. {
  1029. while_node_t* node;
  1030. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(while_node_t));
  1031. node->common.type = QUE_NODE_WHILE;
  1032. node->cond = cond;
  1033. pars_resolve_exp_variables_and_types(NULL, cond);
  1034. node->stat_list = stat_list;
  1035. pars_set_parent_in_list(stat_list, node);
  1036. return(node);
  1037. }
  1038. /*************************************************************************
  1039. Parses a for-loop-statement.
  1040. @return for-statement node */
  1041. UNIV_INTERN
  1042. for_node_t*
  1043. pars_for_statement(
  1044. /*===============*/
  1045. sym_node_t* loop_var, /*!< in: loop variable */
  1046. que_node_t* loop_start_limit,/*!< in: loop start expression */
  1047. que_node_t* loop_end_limit, /*!< in: loop end expression */
  1048. que_node_t* stat_list) /*!< in: statement list */
  1049. {
  1050. for_node_t* node;
  1051. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(for_node_t));
  1052. node->common.type = QUE_NODE_FOR;
  1053. pars_resolve_exp_variables_and_types(NULL, loop_var);
  1054. pars_resolve_exp_variables_and_types(NULL, loop_start_limit);
  1055. pars_resolve_exp_variables_and_types(NULL, loop_end_limit);
  1056. node->loop_var = loop_var->indirection;
  1057. ut_a(loop_var->indirection);
  1058. node->loop_start_limit = loop_start_limit;
  1059. node->loop_end_limit = loop_end_limit;
  1060. node->stat_list = stat_list;
  1061. pars_set_parent_in_list(stat_list, node);
  1062. return(node);
  1063. }
  1064. /*************************************************************************
  1065. Parses an exit statement.
  1066. @return exit statement node */
  1067. UNIV_INTERN
  1068. exit_node_t*
  1069. pars_exit_statement(void)
  1070. /*=====================*/
  1071. {
  1072. exit_node_t* node;
  1073. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(exit_node_t));
  1074. node->common.type = QUE_NODE_EXIT;
  1075. return(node);
  1076. }
  1077. /*************************************************************************
  1078. Parses a return-statement.
  1079. @return return-statement node */
  1080. UNIV_INTERN
  1081. return_node_t*
  1082. pars_return_statement(void)
  1083. /*=======================*/
  1084. {
  1085. return_node_t* node;
  1086. node = mem_heap_alloc(pars_sym_tab_global->heap,
  1087. sizeof(return_node_t));
  1088. node->common.type = QUE_NODE_RETURN;
  1089. return(node);
  1090. }
  1091. /*************************************************************************
  1092. Parses an assignment statement.
  1093. @return assignment statement node */
  1094. UNIV_INTERN
  1095. assign_node_t*
  1096. pars_assignment_statement(
  1097. /*======================*/
  1098. sym_node_t* var, /*!< in: variable to assign */
  1099. que_node_t* val) /*!< in: value to assign */
  1100. {
  1101. assign_node_t* node;
  1102. node = mem_heap_alloc(pars_sym_tab_global->heap,
  1103. sizeof(assign_node_t));
  1104. node->common.type = QUE_NODE_ASSIGNMENT;
  1105. node->var = var;
  1106. node->val = val;
  1107. pars_resolve_exp_variables_and_types(NULL, var);
  1108. pars_resolve_exp_variables_and_types(NULL, val);
  1109. ut_a(dtype_get_mtype(dfield_get_type(que_node_get_val(var)))
  1110. == dtype_get_mtype(dfield_get_type(que_node_get_val(val))));
  1111. return(node);
  1112. }
  1113. /*************************************************************************
  1114. Parses a procedure call.
  1115. @return function node */
  1116. UNIV_INTERN
  1117. func_node_t*
  1118. pars_procedure_call(
  1119. /*================*/
  1120. que_node_t* res_word,/*!< in: procedure name reserved word */
  1121. que_node_t* args) /*!< in: argument list */
  1122. {
  1123. func_node_t* node;
  1124. node = pars_func(res_word, args);
  1125. pars_resolve_exp_list_variables_and_types(NULL, args);
  1126. return(node);
  1127. }
  1128. /*************************************************************************
  1129. Parses a fetch statement. into_list or user_func (but not both) must be
  1130. non-NULL.
  1131. @return fetch statement node */
  1132. UNIV_INTERN
  1133. fetch_node_t*
  1134. pars_fetch_statement(
  1135. /*=================*/
  1136. sym_node_t* cursor, /*!< in: cursor node */
  1137. sym_node_t* into_list, /*!< in: variables to set, or NULL */
  1138. sym_node_t* user_func) /*!< in: user function name, or NULL */
  1139. {
  1140. sym_node_t* cursor_decl;
  1141. fetch_node_t* node;
  1142. /* Logical XOR. */
  1143. ut_a(!into_list != !user_func);
  1144. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(fetch_node_t));
  1145. node->common.type = QUE_NODE_FETCH;
  1146. pars_resolve_exp_variables_and_types(NULL, cursor);
  1147. if (into_list) {
  1148. pars_resolve_exp_list_variables_and_types(NULL, into_list);
  1149. node->into_list = into_list;
  1150. node->func = NULL;
  1151. } else {
  1152. pars_resolve_exp_variables_and_types(NULL, user_func);
  1153. node->func = pars_info_get_user_func(pars_sym_tab_global->info,
  1154. user_func->name);
  1155. ut_a(node->func);
  1156. node->into_list = NULL;
  1157. }
  1158. cursor_decl = cursor->alias;
  1159. ut_a(cursor_decl->token_type == SYM_CURSOR);
  1160. node->cursor_def = cursor_decl->cursor_def;
  1161. if (into_list) {
  1162. ut_a(que_node_list_get_len(into_list)
  1163. == que_node_list_get_len(node->cursor_def->select_list));
  1164. }
  1165. return(node);
  1166. }
  1167. /*************************************************************************
  1168. Parses an open or close cursor statement.
  1169. @return fetch statement node */
  1170. UNIV_INTERN
  1171. open_node_t*
  1172. pars_open_statement(
  1173. /*================*/
  1174. ulint type, /*!< in: ROW_SEL_OPEN_CURSOR
  1175. or ROW_SEL_CLOSE_CURSOR */
  1176. sym_node_t* cursor) /*!< in: cursor node */
  1177. {
  1178. sym_node_t* cursor_decl;
  1179. open_node_t* node;
  1180. node = mem_heap_alloc(pars_sym_tab_global->heap, sizeof(open_node_t));
  1181. node->common.type = QUE_NODE_OPEN;
  1182. pars_resolve_exp_variables_and_types(NULL, cursor);
  1183. cursor_decl = cursor->alias;
  1184. ut_a(cursor_decl->token_type == SYM_CURSOR);
  1185. node->op_type = type;
  1186. node->cursor_def = cursor_decl->cursor_def;
  1187. return(node);
  1188. }
  1189. /*************************************************************************
  1190. Parses a row_printf-statement.
  1191. @return row_printf-statement node */
  1192. UNIV_INTERN
  1193. row_printf_node_t*
  1194. pars_row_printf_statement(
  1195. /*======================*/
  1196. sel_node_t* sel_node) /*!< in: select node */
  1197. {
  1198. row_printf_node_t* node;
  1199. node = mem_heap_alloc(pars_sym_tab_global->heap,
  1200. sizeof(row_printf_node_t));
  1201. node->common.type = QUE_NODE_ROW_PRINTF;
  1202. node->sel_node = sel_node;
  1203. sel_node->common.parent = node;
  1204. return(node);
  1205. }
  1206. /*************************************************************************
  1207. Parses a commit statement.
  1208. @return own: commit node struct */
  1209. UNIV_INTERN
  1210. commit_node_t*
  1211. pars_commit_statement(void)
  1212. /*=======================*/
  1213. {
  1214. return(commit_node_create(pars_sym_tab_global->heap));
  1215. }
  1216. /*************************************************************************
  1217. Parses a rollback statement.
  1218. @return own: rollback node struct */
  1219. UNIV_INTERN
  1220. roll_node_t*
  1221. pars_rollback_statement(void)
  1222. /*=========================*/
  1223. {
  1224. return(roll_node_create(pars_sym_tab_global->heap));
  1225. }
  1226. /*************************************************************************
  1227. Parses a column definition at a table creation.
  1228. @return column sym table node */
  1229. UNIV_INTERN
  1230. sym_node_t*
  1231. pars_column_def(
  1232. /*============*/
  1233. sym_node_t* sym_node, /*!< in: column node in the
  1234. symbol table */
  1235. pars_res_word_t* type, /*!< in: data type */
  1236. sym_node_t* len, /*!< in: length of column, or
  1237. NULL */
  1238. void* is_unsigned, /*!< in: if not NULL, column
  1239. is of type UNSIGNED. */
  1240. void* is_not_null) /*!< in: if not NULL, column
  1241. is of type NOT NULL. */
  1242. {
  1243. ulint len2;
  1244. if (len) {
  1245. len2 = eval_node_get_int_val(len);
  1246. } else {
  1247. len2 = 0;
  1248. }
  1249. pars_set_dfield_type(que_node_get_val(sym_node), type, len2,
  1250. is_unsigned != NULL, is_not_null != NULL);
  1251. return(sym_node);
  1252. }
  1253. /*************************************************************************
  1254. Parses a table creation operation.
  1255. @return table create subgraph */
  1256. UNIV_INTERN
  1257. tab_node_t*
  1258. pars_create_table(
  1259. /*==============*/
  1260. sym_node_t* table_sym, /*!< in: table name node in the symbol
  1261. table */
  1262. sym_node_t* column_defs, /*!< in: list of column names */
  1263. void* not_fit_in_memory __attribute__((unused)))
  1264. /*!< in: a non-NULL pointer means that
  1265. this is a table which in simulations
  1266. should be simulated as not fitting
  1267. in memory; thread is put to sleep
  1268. to simulate disk accesses; NOTE that
  1269. this flag is not stored to the data
  1270. dictionary on disk, and the database
  1271. will forget about non-NULL value if
  1272. it has to reload the table definition
  1273. from disk */
  1274. {
  1275. dict_table_t* table;
  1276. sym_node_t* column;
  1277. tab_node_t* node;
  1278. const dtype_t* dtype;
  1279. ulint n_cols;
  1280. n_cols = que_node_list_get_len(column_defs);
  1281. /* As the InnoDB SQL parser is for internal use only,
  1282. for creating some system tables, this function will only
  1283. create tables in the old (not compact) record format. */
  1284. table = dict_mem_table_create(table_sym->name, 0, n_cols, 0);
  1285. #ifdef UNIV_DEBUG
  1286. if (not_fit_in_memory != NULL) {
  1287. table->does_not_fit_in_memory = TRUE;
  1288. }
  1289. #endif /* UNIV_DEBUG */
  1290. column = column_defs;
  1291. while (column) {
  1292. dtype = dfield_get_type(que_node_get_val(column));
  1293. dict_mem_table_add_col(table, table->heap,
  1294. column->name, dtype->mtype,
  1295. dtype->prtype, dtype->len);
  1296. column->resolved = TRUE;
  1297. column->token_type = SYM_COLUMN;
  1298. column = que_node_get_next(column);
  1299. }
  1300. node = tab_create_graph_create(table, pars_sym_tab_global->heap);
  1301. table_sym->resolved = TRUE;
  1302. table_sym->token_type = SYM_TABLE;
  1303. return(node);
  1304. }
  1305. /*************************************************************************
  1306. Parses an index creation operation.
  1307. @return index create subgraph */
  1308. UNIV_INTERN
  1309. ind_node_t*
  1310. pars_create_index(
  1311. /*==============*/
  1312. pars_res_word_t* unique_def, /*!< in: not NULL if a unique index */
  1313. pars_res_word_t* clustered_def, /*!< in: not NULL if a clustered index */
  1314. sym_node_t* index_sym, /*!< in: index name node in the symbol
  1315. table */
  1316. sym_node_t* table_sym, /*!< in: table name node in the symbol
  1317. table */
  1318. sym_node_t* column_list) /*!< in: list of column names */
  1319. {
  1320. dict_index_t* index;
  1321. sym_node_t* column;
  1322. ind_node_t* node;
  1323. ulint n_fields;
  1324. ulint ind_type;
  1325. n_fields = que_node_list_get_len(column_list);
  1326. ind_type = 0;
  1327. if (unique_def) {
  1328. ind_type = ind_type | DICT_UNIQUE;
  1329. }
  1330. if (clustered_def) {
  1331. ind_type = ind_type | DICT_CLUSTERED;
  1332. }
  1333. index = dict_mem_index_create(table_sym->name, index_sym->name, 0,
  1334. ind_type, n_fields);
  1335. column = column_list;
  1336. while (column) {
  1337. dict_mem_index_add_field(index, column->name, 0);
  1338. column->resolved = TRUE;
  1339. column->token_type = SYM_COLUMN;
  1340. column = que_node_get_next(column);
  1341. }
  1342. node = ind_create_graph_create(index, pars_sym_tab_global->heap);
  1343. table_sym->resolved = TRUE;
  1344. table_sym->token_type = SYM_TABLE;
  1345. index_sym->resolved = TRUE;
  1346. index_sym->token_type = SYM_TABLE;
  1347. return(node);
  1348. }
  1349. /*************************************************************************
  1350. Parses a procedure definition.
  1351. @return query fork node */
  1352. UNIV_INTERN
  1353. que_fork_t*
  1354. pars_procedure_definition(
  1355. /*======================*/
  1356. sym_node_t* sym_node, /*!< in: procedure id node in the symbol
  1357. table */
  1358. sym_node_t* param_list, /*!< in: parameter declaration list */
  1359. que_node_t* stat_list) /*!< in: statement list */
  1360. {
  1361. proc_node_t* node;
  1362. que_fork_t* fork;
  1363. que_thr_t* thr;
  1364. mem_heap_t* heap;
  1365. heap = pars_sym_tab_global->heap;
  1366. fork = que_fork_create(NULL, NULL, QUE_FORK_PROCEDURE, heap);
  1367. fork->trx = NULL;
  1368. thr = que_thr_create(fork, heap);
  1369. node = mem_heap_alloc(heap, sizeof(proc_node_t));
  1370. node->common.type = QUE_NODE_PROC;
  1371. node->common.parent = thr;
  1372. sym_node->token_type = SYM_PROCEDURE_NAME;
  1373. sym_node->resolved = TRUE;
  1374. node->proc_id = sym_node;
  1375. node->param_list = param_list;
  1376. node->stat_list = stat_list;
  1377. pars_set_parent_in_list(stat_list, node);
  1378. node->sym_tab = pars_sym_tab_global;
  1379. thr->child = node;
  1380. pars_sym_tab_global->query_graph = fork;
  1381. return(fork);
  1382. }
  1383. /*****************************************************************
  1384. Parses a stored procedure call, when this is not within another stored
  1385. procedure, that is, the client issues a procedure call directly.
  1386. In MySQL/InnoDB, stored InnoDB procedures are invoked via the
  1387. parsed procedure tree, not via InnoDB SQL, so this function is not used.
  1388. @return query graph */
  1389. UNIV_INTERN
  1390. que_fork_t*
  1391. pars_stored_procedure_call(
  1392. /*=======================*/
  1393. sym_node_t* sym_node __attribute__((unused)))
  1394. /*!< in: stored procedure name */
  1395. {
  1396. ut_error;
  1397. return(NULL);
  1398. }
  1399. /*****************************************************************
  1400. Retrieves characters to the lexical analyzer. */
  1401. UNIV_INTERN
  1402. void
  1403. pars_get_lex_chars(
  1404. /*===============*/
  1405. char* buf, /*!< in/out: buffer where to copy */
  1406. int* result, /*!< out: number of characters copied or EOF */
  1407. int max_size) /*!< in: maximum number of characters which fit
  1408. in the buffer */
  1409. {
  1410. int len;
  1411. len = pars_sym_tab_global->string_len
  1412. - pars_sym_tab_global->next_char_pos;
  1413. if (len == 0) {
  1414. #ifdef YYDEBUG
  1415. /* fputs("SQL string ends\n", stderr); */
  1416. #endif
  1417. *result = 0;
  1418. return;
  1419. }
  1420. if (len > max_size) {
  1421. len = max_size;
  1422. }
  1423. #ifdef UNIV_SQL_DEBUG
  1424. if (pars_print_lexed) {
  1425. if (len >= 5) {
  1426. len = 5;
  1427. }
  1428. fwrite(pars_sym_tab_global->sql_string
  1429. + pars_sym_tab_global->next_char_pos,
  1430. 1, len, stderr);
  1431. }
  1432. #endif /* UNIV_SQL_DEBUG */
  1433. ut_memcpy(buf, pars_sym_tab_global->sql_string
  1434. + pars_sym_tab_global->next_char_pos, len);
  1435. *result = len;
  1436. pars_sym_tab_global->next_char_pos += len;
  1437. }
  1438. /*****************************************************************
  1439. Called by yyparse on error. */
  1440. UNIV_INTERN
  1441. void
  1442. yyerror(
  1443. /*====*/
  1444. const char* s __attribute__((unused)))
  1445. /*!< in: error message string */
  1446. {
  1447. ut_ad(s);
  1448. fputs("PARSER ERROR: Syntax error in SQL string\n", stderr);
  1449. ut_error;
  1450. }
  1451. /*****************************************************************
  1452. Parses an SQL string returning the query graph.
  1453. @return own: the query graph */
  1454. UNIV_INTERN
  1455. que_t*
  1456. pars_sql(
  1457. /*=====*/
  1458. pars_info_t* info, /*!< in: extra information, or NULL */
  1459. const char* str) /*!< in: SQL string */
  1460. {
  1461. sym_node_t* sym_node;
  1462. mem_heap_t* heap;
  1463. que_t* graph;
  1464. ut_ad(str);
  1465. heap = mem_heap_create(256);
  1466. /* Currently, the parser is not reentrant: */
  1467. ut_ad(mutex_own(&(dict_sys->mutex)));
  1468. pars_sym_tab_global = sym_tab_create(heap);
  1469. pars_sym_tab_global->string_len = strlen(str);
  1470. pars_sym_tab_global->sql_string = mem_heap_dup(
  1471. heap, str, pars_sym_tab_global->string_len + 1);
  1472. pars_sym_tab_global->next_char_pos = 0;
  1473. pars_sym_tab_global->info = info;
  1474. yyparse();
  1475. sym_node = UT_LIST_GET_FIRST(pars_sym_tab_global->sym_list);
  1476. while (sym_node) {
  1477. ut_a(sym_node->resolved);
  1478. sym_node = UT_LIST_GET_NEXT(sym_list, sym_node);
  1479. }
  1480. graph = pars_sym_tab_global->query_graph;
  1481. graph->sym_tab = pars_sym_tab_global;
  1482. graph->info = info;
  1483. /* fprintf(stderr, "SQL graph size %lu\n", mem_heap_get_size(heap)); */
  1484. return(graph);
  1485. }
  1486. /**********************************************************************
  1487. Completes a query graph by adding query thread and fork nodes
  1488. above it and prepares the graph for running. The fork created is of
  1489. type QUE_FORK_MYSQL_INTERFACE.
  1490. @return query thread node to run */
  1491. UNIV_INTERN
  1492. que_thr_t*
  1493. pars_complete_graph_for_exec(
  1494. /*=========================*/
  1495. que_node_t* node, /*!< in: root node for an incomplete
  1496. query graph */
  1497. trx_t* trx, /*!< in: transaction handle */
  1498. mem_heap_t* heap) /*!< in: memory heap from which allocated */
  1499. {
  1500. que_fork_t* fork;
  1501. que_thr_t* thr;
  1502. fork = que_fork_create(NULL, NULL, QUE_FORK_MYSQL_INTERFACE, heap);
  1503. fork->trx = trx;
  1504. thr = que_thr_create(fork, heap);
  1505. thr->child = node;
  1506. que_node_set_parent(node, thr);
  1507. trx->graph = NULL;
  1508. return(thr);
  1509. }
  1510. /********************************************************************
  1511. Create parser info struct.
  1512. @return own: info struct */
  1513. UNIV_INTERN
  1514. pars_info_t*
  1515. pars_info_create(void)
  1516. /*==================*/
  1517. {
  1518. pars_info_t* info;
  1519. mem_heap_t* heap;
  1520. heap = mem_heap_create(512);
  1521. info = mem_heap_alloc(heap, sizeof(*info));
  1522. info->heap = heap;
  1523. info->funcs = NULL;
  1524. info->bound_lits = NULL;
  1525. info->bound_ids = NULL;
  1526. info->graph_owns_us = TRUE;
  1527. return(info);
  1528. }
  1529. /********************************************************************
  1530. Free info struct and everything it contains. */
  1531. UNIV_INTERN
  1532. void
  1533. pars_info_free(
  1534. /*===========*/
  1535. pars_info_t* info) /*!< in, own: info struct */
  1536. {
  1537. mem_heap_free(info->heap);
  1538. }
  1539. /********************************************************************
  1540. Add bound literal. */
  1541. UNIV_INTERN
  1542. void
  1543. pars_info_add_literal(
  1544. /*==================*/
  1545. pars_info_t* info, /*!< in: info struct */
  1546. const char* name, /*!< in: name */
  1547. const void* address, /*!< in: address */
  1548. ulint length, /*!< in: length of data */
  1549. ulint type, /*!< in: type, e.g. DATA_FIXBINARY */
  1550. ulint prtype) /*!< in: precise type, e.g.
  1551. DATA_UNSIGNED */
  1552. {
  1553. pars_bound_lit_t* pbl;
  1554. ut_ad(!pars_info_get_bound_lit(info, name));
  1555. pbl = mem_heap_alloc(info->heap, sizeof(*pbl));
  1556. pbl->name = name;
  1557. pbl->address = address;
  1558. pbl->length = length;
  1559. pbl->type = type;
  1560. pbl->prtype = prtype;
  1561. if (!info->bound_lits) {
  1562. info->bound_lits = ib_vector_create(info->heap, 8);
  1563. }
  1564. ib_vector_push(info->bound_lits, pbl);
  1565. }
  1566. /********************************************************************
  1567. Equivalent to pars_info_add_literal(info, name, str, strlen(str),
  1568. DATA_VARCHAR, DATA_ENGLISH). */
  1569. UNIV_INTERN
  1570. void
  1571. pars_info_add_str_literal(
  1572. /*======================*/
  1573. pars_info_t* info, /*!< in: info struct */
  1574. const char* name, /*!< in: name */
  1575. const char* str) /*!< in: string */
  1576. {
  1577. pars_info_add_literal(info, name, str, strlen(str),
  1578. DATA_VARCHAR, DATA_ENGLISH);
  1579. }
  1580. /********************************************************************
  1581. Equivalent to:
  1582. char buf[4];
  1583. mach_write_to_4(buf, val);
  1584. pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
  1585. except that the buffer is dynamically allocated from the info struct's
  1586. heap. */
  1587. UNIV_INTERN
  1588. void
  1589. pars_info_add_int4_literal(
  1590. /*=======================*/
  1591. pars_info_t* info, /*!< in: info struct */
  1592. const char* name, /*!< in: name */
  1593. lint val) /*!< in: value */
  1594. {
  1595. byte* buf = mem_heap_alloc(info->heap, 4);
  1596. mach_write_to_4(buf, val);
  1597. pars_info_add_literal(info, name, buf, 4, DATA_INT, 0);
  1598. }
  1599. /********************************************************************
  1600. Equivalent to:
  1601. char buf[8];
  1602. mach_write_to_8(buf, val);
  1603. pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
  1604. except that the buffer is dynamically allocated from the info struct's
  1605. heap. */
  1606. UNIV_INTERN
  1607. void
  1608. pars_info_add_dulint_literal(
  1609. /*=========================*/
  1610. pars_info_t* info, /*!< in: info struct */
  1611. const char* name, /*!< in: name */
  1612. dulint val) /*!< in: value */
  1613. {
  1614. byte* buf = mem_heap_alloc(info->heap, 8);
  1615. mach_write_to_8(buf, val);
  1616. pars_info_add_literal(info, name, buf, 8, DATA_FIXBINARY, 0);
  1617. }
  1618. /********************************************************************
  1619. Add user function. */
  1620. UNIV_INTERN
  1621. void
  1622. pars_info_add_function(
  1623. /*===================*/
  1624. pars_info_t* info, /*!< in: info struct */
  1625. const char* name, /*!< in: function name */
  1626. pars_user_func_cb_t func, /*!< in: function address */
  1627. void* arg) /*!< in: user-supplied argument */
  1628. {
  1629. pars_user_func_t* puf;
  1630. ut_ad(!pars_info_get_user_func(info, name));
  1631. puf = mem_heap_alloc(info->heap, sizeof(*puf));
  1632. puf->name = name;
  1633. puf->func = func;
  1634. puf->arg = arg;
  1635. if (!info->funcs) {
  1636. info->funcs = ib_vector_create(info->heap, 8);
  1637. }
  1638. ib_vector_push(info->funcs, puf);
  1639. }
  1640. /********************************************************************
  1641. Add bound id. */
  1642. UNIV_INTERN
  1643. void
  1644. pars_info_add_id(
  1645. /*=============*/
  1646. pars_info_t* info, /*!< in: info struct */
  1647. const char* name, /*!< in: name */
  1648. const char* id) /*!< in: id */
  1649. {
  1650. pars_bound_id_t* bid;
  1651. ut_ad(!pars_info_get_bound_id(info, name));
  1652. bid = mem_heap_alloc(info->heap, sizeof(*bid));
  1653. bid->name = name;
  1654. bid->id = id;
  1655. if (!info->bound_ids) {
  1656. info->bound_ids = ib_vector_create(info->heap, 8);
  1657. }
  1658. ib_vector_push(info->bound_ids, bid);
  1659. }
  1660. /********************************************************************
  1661. Get user function with the given name.
  1662. @return user func, or NULL if not found */
  1663. UNIV_INTERN
  1664. pars_user_func_t*
  1665. pars_info_get_user_func(
  1666. /*====================*/
  1667. pars_info_t* info, /*!< in: info struct */
  1668. const char* name) /*!< in: function name to find*/
  1669. {
  1670. ulint i;
  1671. ib_vector_t* vec;
  1672. if (!info || !info->funcs) {
  1673. return(NULL);
  1674. }
  1675. vec = info->funcs;
  1676. for (i = 0; i < ib_vector_size(vec); i++) {
  1677. pars_user_func_t* puf = ib_vector_get(vec, i);
  1678. if (strcmp(puf->name, name) == 0) {
  1679. return(puf);
  1680. }
  1681. }
  1682. return(NULL);
  1683. }
  1684. /********************************************************************
  1685. Get bound literal with the given name.
  1686. @return bound literal, or NULL if not found */
  1687. UNIV_INTERN
  1688. pars_bound_lit_t*
  1689. pars_info_get_bound_lit(
  1690. /*====================*/
  1691. pars_info_t* info, /*!< in: info struct */
  1692. const char* name) /*!< in: bound literal name to find */
  1693. {
  1694. ulint i;
  1695. ib_vector_t* vec;
  1696. if (!info || !info->bound_lits) {
  1697. return(NULL);
  1698. }
  1699. vec = info->bound_lits;
  1700. for (i = 0; i < ib_vector_size(vec); i++) {
  1701. pars_bound_lit_t* pbl = ib_vector_get(vec, i);
  1702. if (strcmp(pbl->name, name) == 0) {
  1703. return(pbl);
  1704. }
  1705. }
  1706. return(NULL);
  1707. }
  1708. /********************************************************************
  1709. Get bound id with the given name.
  1710. @return bound id, or NULL if not found */
  1711. UNIV_INTERN
  1712. pars_bound_id_t*
  1713. pars_info_get_bound_id(
  1714. /*===================*/
  1715. pars_info_t* info, /*!< in: info struct */
  1716. const char* name) /*!< in: bound id name to find */
  1717. {
  1718. ulint i;
  1719. ib_vector_t* vec;
  1720. if (!info || !info->bound_ids) {
  1721. return(NULL);
  1722. }
  1723. vec = info->bound_ids;
  1724. for (i = 0; i < ib_vector_size(vec); i++) {
  1725. pars_bound_id_t* bid = ib_vector_get(vec, i);
  1726. if (strcmp(bid->name, name) == 0) {
  1727. return(bid);
  1728. }
  1729. }
  1730. return(NULL);
  1731. }