static void phql_parse_with_token(void* phql_parser, int opcode, int parsercode, phql_scanner_token *token, phql_parser_status *parser_status){ phql_parser_token *pToken; pToken = emalloc(sizeof(phql_parser_token)); pToken->opcode = opcode; pToken->token = token->value; pToken->token_len = token->len; pToken->free_flag = 1; phql_(phql_parser, parsercode, pToken, parser_status); token->value = NULL; token->len = 0; }
/** * Executes a PHQL parser/tokenizer */ int phql_internal_parse_phql(zval *result, char *phql, unsigned int phql_length, zval *error_msg) { zend_phalcon_globals *phalcon_globals_ptr = PHALCON_VGLOBAL; phql_parser_status *parser_status = NULL; int scanner_status, status = SUCCESS, error_length; phql_scanner_state *state; phql_scanner_token token; void* phql_parser; char *error; zval unique_id = {}; if (!phql) { PHALCON_STR(error_msg, "PHQL statement cannot be NULL"); return FAILURE; } ZVAL_LONG(&unique_id, zend_inline_hash_func(phql, phql_length)); phalcon_orm_get_prepared_ast(result, &unique_id); if (Z_TYPE_P(result) == IS_ARRAY) { return SUCCESS; } phql_parser = phql_Alloc(phql_wrapper_alloc); if (unlikely(!phql_parser)) { PHALCON_STR(error_msg, "Memory allocation error"); return FAILURE; } parser_status = emalloc(sizeof(phql_parser_status)); state = emalloc(sizeof(phql_scanner_state)); parser_status->status = PHQL_PARSING_OK; parser_status->scanner_state = state; ZVAL_UNDEF(&parser_status->ret); parser_status->syntax_error = NULL; parser_status->token = &token; parser_status->enable_literals = phalcon_globals_ptr->orm.enable_literals; parser_status->phql = phql; parser_status->phql_length = phql_length; state->active_token = 0; state->start = phql; state->start_length = 0; state->end = state->start; token.value = NULL; token.len = 0; while (0 <= (scanner_status = phql_get_token(state, &token))) { /* Calculate the 'start' length */ state->start_length = (phql + phql_length - state->start); state->active_token = token.opcode; /* Parse the token found */ switch (token.opcode) { case PHQL_T_IGNORE: break; case PHQL_T_ADD: phql_(phql_parser, PHQL_PLUS, NULL, parser_status); break; case PHQL_T_SUB: phql_(phql_parser, PHQL_MINUS, NULL, parser_status); break; case PHQL_T_MUL: phql_(phql_parser, PHQL_TIMES, NULL, parser_status); break; case PHQL_T_DIV: phql_(phql_parser, PHQL_DIVIDE, NULL, parser_status); break; case PHQL_T_MOD: phql_(phql_parser, PHQL_MOD, NULL, parser_status); break; case PHQL_T_AND: phql_(phql_parser, PHQL_AND, NULL, parser_status); break; case PHQL_T_OR: phql_(phql_parser, PHQL_OR, NULL, parser_status); break; case PHQL_T_EQUALS: phql_(phql_parser, PHQL_EQUALS, NULL, parser_status); break; case PHQL_T_NOTEQUALS: phql_(phql_parser, PHQL_NOTEQUALS, NULL, parser_status); break; case PHQL_T_LESS: phql_(phql_parser, PHQL_LESS, NULL, parser_status); break; case PHQL_T_GREATER: phql_(phql_parser, PHQL_GREATER, NULL, parser_status); break; case PHQL_T_GREATEREQUAL: phql_(phql_parser, PHQL_GREATEREQUAL, NULL, parser_status); break; case PHQL_T_LESSEQUAL: phql_(phql_parser, PHQL_LESSEQUAL, NULL, parser_status); break; case PHQL_T_IDENTIFIER: phql_parse_with_token(phql_parser, PHQL_T_IDENTIFIER, PHQL_IDENTIFIER, &token, parser_status); break; case PHQL_T_DOT: phql_(phql_parser, PHQL_DOT, NULL, parser_status); break; case PHQL_T_COMMA: phql_(phql_parser, PHQL_COMMA, NULL, parser_status); break; case PHQL_T_PARENTHESES_OPEN: phql_(phql_parser, PHQL_PARENTHESES_OPEN, NULL, parser_status); break; case PHQL_T_PARENTHESES_CLOSE: phql_(phql_parser, PHQL_PARENTHESES_CLOSE, NULL, parser_status); break; case PHQL_T_LIKE: phql_(phql_parser, PHQL_LIKE, NULL, parser_status); break; case PHQL_T_ILIKE: phql_(phql_parser, PHQL_ILIKE, NULL, parser_status); break; case PHQL_T_NOT: phql_(phql_parser, PHQL_NOT, NULL, parser_status); break; case PHQL_T_BITWISE_AND: phql_(phql_parser, PHQL_BITWISE_AND, NULL, parser_status); break; case PHQL_T_BITWISE_OR: phql_(phql_parser, PHQL_BITWISE_OR, NULL, parser_status); break; case PHQL_T_BITWISE_NOT: phql_(phql_parser, PHQL_BITWISE_NOT, NULL, parser_status); break; case PHQL_T_BITWISE_XOR: phql_(phql_parser, PHQL_BITWISE_XOR, NULL, parser_status); break; case PHQL_T_AGAINST: phql_(phql_parser, PHQL_AGAINST, NULL, parser_status); break; case PHQL_T_CASE: phql_(phql_parser, PHQL_CASE, NULL, parser_status); break; case PHQL_T_WHEN: phql_(phql_parser, PHQL_WHEN, NULL, parser_status); break; case PHQL_T_THEN: phql_(phql_parser, PHQL_THEN, NULL, parser_status); break; case PHQL_T_END: phql_(phql_parser, PHQL_END, NULL, parser_status); break; case PHQL_T_ELSE: phql_(phql_parser, PHQL_ELSE, NULL, parser_status); break; case PHQL_T_INTEGER: if (parser_status->enable_literals) { phql_parse_with_token(phql_parser, PHQL_T_INTEGER, PHQL_INTEGER, &token, parser_status); } else { PHALCON_STR(error_msg, "Literals are disabled in PHQL statements"); parser_status->status = PHQL_PARSING_FAILED; } break; case PHQL_T_DOUBLE: if (parser_status->enable_literals) { phql_parse_with_token(phql_parser, PHQL_T_DOUBLE, PHQL_DOUBLE, &token, parser_status); } else { PHALCON_STR(error_msg, "Literals are disabled in PHQL statements"); parser_status->status = PHQL_PARSING_FAILED; } break; case PHQL_T_STRING: if (parser_status->enable_literals) { phql_parse_with_token(phql_parser, PHQL_T_STRING, PHQL_STRING, &token, parser_status); } else { PHALCON_STR(error_msg, "Literals are disabled in PHQL statements"); parser_status->status = PHQL_PARSING_FAILED; } break; case PHQL_T_TRUE: if (parser_status->enable_literals) { phql_(phql_parser, PHQL_TRUE, NULL, parser_status); } else { PHALCON_STR(error_msg, "Literals are disabled in PHQL statements"); parser_status->status = PHQL_PARSING_FAILED; } break; case PHQL_T_FALSE: if (parser_status->enable_literals) { phql_(phql_parser, PHQL_FALSE, NULL, parser_status); } else { PHALCON_STR(error_msg, "Literals are disabled in PHQL statements"); parser_status->status = PHQL_PARSING_FAILED; } break; case PHQL_T_NPLACEHOLDER: phql_parse_with_token(phql_parser, PHQL_T_NPLACEHOLDER, PHQL_NPLACEHOLDER, &token, parser_status); break; case PHQL_T_SPLACEHOLDER: phql_parse_with_token(phql_parser, PHQL_T_SPLACEHOLDER, PHQL_SPLACEHOLDER, &token, parser_status); break; case PHQL_T_BPLACEHOLDER: phql_parse_with_token(phql_parser, PHQL_T_BPLACEHOLDER, PHQL_BPLACEHOLDER, &token, parser_status); break; case PHQL_T_FROM: phql_(phql_parser, PHQL_FROM, NULL, parser_status); break; case PHQL_T_UPDATE: phql_(phql_parser, PHQL_UPDATE, NULL, parser_status); break; case PHQL_T_SET: phql_(phql_parser, PHQL_SET, NULL, parser_status); break; case PHQL_T_WHERE: phql_(phql_parser, PHQL_WHERE, NULL, parser_status); break; case PHQL_T_DELETE: phql_(phql_parser, PHQL_DELETE, NULL, parser_status); break; case PHQL_T_INSERT: phql_(phql_parser, PHQL_INSERT, NULL, parser_status); break; case PHQL_T_INTO: phql_(phql_parser, PHQL_INTO, NULL, parser_status); break; case PHQL_T_VALUES: phql_(phql_parser, PHQL_VALUES, NULL, parser_status); break; case PHQL_T_SELECT: phql_(phql_parser, PHQL_SELECT, NULL, parser_status); break; case PHQL_T_AS: phql_(phql_parser, PHQL_AS, NULL, parser_status); break; case PHQL_T_ORDER: phql_(phql_parser, PHQL_ORDER, NULL, parser_status); break; case PHQL_T_BY: phql_(phql_parser, PHQL_BY, NULL, parser_status); break; case PHQL_T_LIMIT: phql_(phql_parser, PHQL_LIMIT, NULL, parser_status); break; case PHQL_T_OFFSET: phql_(phql_parser, PHQL_OFFSET, NULL, parser_status); break; case PHQL_T_GROUP: phql_(phql_parser, PHQL_GROUP, NULL, parser_status); break; case PHQL_T_HAVING: phql_(phql_parser, PHQL_HAVING, NULL, parser_status); break; case PHQL_T_ASC: phql_(phql_parser, PHQL_ASC, NULL, parser_status); break; case PHQL_T_DESC: phql_(phql_parser, PHQL_DESC, NULL, parser_status); break; case PHQL_T_IN: phql_(phql_parser, PHQL_IN, NULL, parser_status); break; case PHQL_T_ON: phql_(phql_parser, PHQL_ON, NULL, parser_status); break; case PHQL_T_INNER: phql_(phql_parser, PHQL_INNER, NULL, parser_status); break; case PHQL_T_JOIN: phql_(phql_parser, PHQL_JOIN, NULL, parser_status); break; case PHQL_T_LEFT: phql_(phql_parser, PHQL_LEFT, NULL, parser_status); break; case PHQL_T_RIGHT: phql_(phql_parser, PHQL_RIGHT, NULL, parser_status); break; case PHQL_T_CROSS: phql_(phql_parser, PHQL_CROSS, NULL, parser_status); break; case PHQL_T_FULL: phql_(phql_parser, PHQL_FULL, NULL, parser_status); break; case PHQL_T_OUTER: phql_(phql_parser, PHQL_OUTER, NULL, parser_status); break; case PHQL_T_IS: phql_(phql_parser, PHQL_IS, NULL, parser_status); break; case PHQL_T_NULL: phql_(phql_parser, PHQL_NULL, NULL, parser_status); break; case PHQL_T_BETWEEN: phql_(phql_parser, PHQL_BETWEEN, NULL, parser_status); break; case PHQL_T_DISTINCT: phql_(phql_parser, PHQL_DISTINCT, NULL, parser_status); break; case PHQL_T_ALL: phql_(phql_parser, PHQL_ALL, NULL, parser_status); break; case PHQL_T_CAST: phql_(phql_parser, PHQL_CAST, NULL, parser_status); break; case PHQL_T_CONVERT: phql_(phql_parser, PHQL_CONVERT, NULL, parser_status); break; case PHQL_T_USING: phql_(phql_parser, PHQL_USING, NULL, parser_status); break; case PHQL_T_EXISTS: phql_(phql_parser, PHQL_EXISTS, NULL, parser_status); break; case PHQL_T_TS_MATCHES: phql_(phql_parser, PHQL_TS_MATCHES, NULL, parser_status); break; case PHQL_T_TS_OR: phql_(phql_parser, PHQL_TS_OR, NULL, parser_status); break; case PHQL_T_TS_AND: phql_(phql_parser, PHQL_TS_AND, NULL, parser_status); break; case PHQL_T_TS_NEGATE: phql_(phql_parser, PHQL_TS_NEGATE, NULL, parser_status); break; case PHQL_T_TS_CONTAINS_ANOTHER: phql_(phql_parser, PHQL_TS_CONTAINS_ANOTHER, NULL, parser_status); break; case PHQL_T_TS_CONTAINS_IN: phql_(phql_parser, PHQL_TS_CONTAINS_IN, NULL, parser_status); break; case PHQL_T_FOR: phql_(phql_parser, PHQL_FOR, NULL, parser_status); break; default: parser_status->status = PHQL_PARSING_FAILED; error_length = sizeof(char) * 32; error = emalloc(error_length); snprintf(error, error_length, "Scanner: Unknown opcode %c", token.opcode); error[error_length - 1] = '\0'; PHALCON_STR(error_msg, error); efree(error); break; } if (parser_status->status != PHQL_PARSING_OK) { status = FAILURE; break; } state->end = state->start; } if (status != FAILURE) { switch (scanner_status) { case PHQL_SCANNER_RETCODE_ERR: case PHQL_SCANNER_RETCODE_IMPOSSIBLE: if (Z_TYPE_P(error_msg) > IS_NULL) { phql_scanner_error_msg(parser_status, error_msg); } status = FAILURE; break; default: phql_(phql_parser, 0, NULL, parser_status); } } state->active_token = 0; state->start = NULL; if (parser_status->status != PHQL_PARSING_OK) { status = FAILURE; if (parser_status->syntax_error) { if (Z_TYPE_P(error_msg) <= IS_NULL) { PHALCON_STR(error_msg, parser_status->syntax_error); } efree(parser_status->syntax_error); } } phql_Free(phql_parser, phql_wrapper_free); if (status != FAILURE) { if (parser_status->status == PHQL_PARSING_OK) { if (Z_TYPE_P(&parser_status->ret) == IS_ARRAY) { /** * Set a unique id for the parsed ast */ if (phalcon_globals_ptr->orm.cache_level >= 1) { add_assoc_long(&parser_status->ret, "id", Z_LVAL(unique_id)); } ZVAL_COPY(result, &parser_status->ret); /** * Store the parsed definition in the cache */ phalcon_orm_set_prepared_ast(&unique_id, result); } else { array_init(result); } } } efree(parser_status); efree(state); return status; }