mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +01:00
Fixed CORE-4322 - Engine crashes when use aggregate or window functions in recursive query. Vlad, please review.
This commit is contained in:
parent
dc03c09415
commit
9350f941dc
@ -2242,6 +2242,8 @@ C --
|
||||
PARAMETER (GDS__dsql_grant_failed = 336397319)
|
||||
INTEGER*4 GDS__dsql_revoke_failed
|
||||
PARAMETER (GDS__dsql_revoke_failed = 336397320)
|
||||
INTEGER*4 GDS__dsql_cte_recursive_aggregate
|
||||
PARAMETER (GDS__dsql_cte_recursive_aggregate = 336397321)
|
||||
INTEGER*4 GDS__gsec_cant_open_db
|
||||
PARAMETER (GDS__gsec_cant_open_db = 336723983)
|
||||
INTEGER*4 GDS__gsec_switches_error
|
||||
|
@ -1128,6 +1128,7 @@ const
|
||||
gds_dsql_alter_user_failed = 336397318;
|
||||
gds_dsql_grant_failed = 336397319;
|
||||
gds_dsql_revoke_failed = 336397320;
|
||||
gds_dsql_cte_recursive_aggregate = 336397321;
|
||||
gds_gsec_cant_open_db = 336723983;
|
||||
gds_gsec_switches_error = 336723984;
|
||||
gds_gsec_no_op_spec = 336723985;
|
||||
|
@ -667,8 +667,6 @@ SelectExprNode* DsqlCompilerScratch::pass1RecursiveCte(SelectExprNode* input)
|
||||
Arg::Gds(isc_dsql_cte_wrong_clause) << input->alias <<
|
||||
Arg::Str("HAVING"));
|
||||
}
|
||||
// hvlad: we need also forbid any aggregate function here
|
||||
// but for now i have no idea how to do it simple
|
||||
|
||||
if (!dsqlAll)
|
||||
{
|
||||
|
@ -1723,6 +1723,7 @@ static RseNode* pass1_rse(DsqlCompilerScratch* dsqlScratch, RecordSourceNode* in
|
||||
string save_alias;
|
||||
RseNode* rseNode = input->as<RseNode>();
|
||||
const bool isRecursive = rseNode && (rseNode->dsqlFlags & RecordSourceNode::DFLAG_RECURSIVE);
|
||||
AutoSetRestore<USHORT> autoScopeLevel(&dsqlScratch->scopeLevel, dsqlScratch->scopeLevel);
|
||||
|
||||
if (isRecursive)
|
||||
{
|
||||
@ -1730,6 +1731,10 @@ static RseNode* pass1_rse(DsqlCompilerScratch* dsqlScratch, RecordSourceNode* in
|
||||
save_alias = dsqlScratch->recursiveCtx->ctx_alias;
|
||||
|
||||
dsqlScratch->recursiveCtx->ctx_alias = *dsqlScratch->getNextCTEAlias();
|
||||
|
||||
// ASF: We need to reset the scope level to the same value found in the non-recursive
|
||||
// part of the query, to verify usage of aggregate functions correctly. See CORE-4322.
|
||||
dsqlScratch->scopeLevel = dsqlScratch->recursiveCtx->ctx_scope_level;
|
||||
}
|
||||
|
||||
RseNode* ret = pass1_rse_impl(dsqlScratch, input, order, rows, updateLock, flags);
|
||||
@ -1877,12 +1882,34 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
|
||||
rse->dsqlSelectList = pass1_sel_list(dsqlScratch, selectList);
|
||||
--dsqlScratch->inSelectList;
|
||||
|
||||
if (inputRse->dsqlFlags & RecordSourceNode::DFLAG_RECURSIVE)
|
||||
{
|
||||
if (Aggregate2Finder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_EQUAL, false,
|
||||
rse->dsqlSelectList))
|
||||
{
|
||||
// Recursive member of CTE cannot use aggregate function
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
Arg::Gds(isc_dsql_cte_recursive_aggregate));
|
||||
}
|
||||
}
|
||||
|
||||
// Process ORDER clause, if any
|
||||
if (order)
|
||||
{
|
||||
++dsqlScratch->inOrderByClause;
|
||||
rse->dsqlOrder = PASS1_sort(dsqlScratch, order, selectList);
|
||||
--dsqlScratch->inOrderByClause;
|
||||
|
||||
if (inputRse->dsqlFlags & RecordSourceNode::DFLAG_RECURSIVE)
|
||||
{
|
||||
if (Aggregate2Finder::find(dsqlScratch->scopeLevel, FIELD_MATCH_TYPE_EQUAL, false,
|
||||
rse->dsqlOrder))
|
||||
{
|
||||
// Recursive member of CTE cannot use aggregate function
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
Arg::Gds(isc_dsql_cte_recursive_aggregate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A GROUP BY, HAVING, or any aggregate function in the select list
|
||||
|
@ -1117,6 +1117,7 @@ static const struct {
|
||||
{"dsql_alter_user_failed", 336397318},
|
||||
{"dsql_grant_failed", 336397319},
|
||||
{"dsql_revoke_failed", 336397320},
|
||||
{"dsql_cte_recursive_aggregate", 336397321},
|
||||
{"gsec_cant_open_db", 336723983},
|
||||
{"gsec_switches_error", 336723984},
|
||||
{"gsec_no_op_spec", 336723985},
|
||||
|
@ -1151,6 +1151,7 @@ const ISC_STATUS isc_dsql_create_user_failed = 336397317L;
|
||||
const ISC_STATUS isc_dsql_alter_user_failed = 336397318L;
|
||||
const ISC_STATUS isc_dsql_grant_failed = 336397319L;
|
||||
const ISC_STATUS isc_dsql_revoke_failed = 336397320L;
|
||||
const ISC_STATUS isc_dsql_cte_recursive_aggregate = 336397321L;
|
||||
const ISC_STATUS isc_gsec_cant_open_db = 336723983L;
|
||||
const ISC_STATUS isc_gsec_switches_error = 336723984L;
|
||||
const ISC_STATUS isc_gsec_no_op_spec = 336723985L;
|
||||
@ -1252,7 +1253,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1196;
|
||||
const ISC_STATUS isc_err_max = 1197;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2373,6 +2374,7 @@ const ISC_STATUS isc_err_max = 1196;
|
||||
#define isc_dsql_alter_user_failed 336397318L
|
||||
#define isc_dsql_grant_failed 336397319L
|
||||
#define isc_dsql_revoke_failed 336397320L
|
||||
#define isc_dsql_cte_recursive_aggregate 336397321L
|
||||
#define isc_gsec_cant_open_db 336723983L
|
||||
#define isc_gsec_switches_error 336723984L
|
||||
#define isc_gsec_no_op_spec 336723985L
|
||||
@ -2474,7 +2476,7 @@ const ISC_STATUS isc_err_max = 1196;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1196
|
||||
#define isc_err_max 1197
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1120,6 +1120,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{336397318, "ALTER USER @1 failed"}, /* dsql_alter_user_failed */
|
||||
{336397319, "GRANT failed"}, /* dsql_grant_failed */
|
||||
{336397320, "REVOKE failed"}, /* dsql_revoke_failed */
|
||||
{336397321, "Recursive member of CTE cannot use aggregate or window function"}, /* dsql_cte_recursive_aggregate */
|
||||
{336723983, "unable to open database"}, /* gsec_cant_open_db */
|
||||
{336723984, "error in switch specifications"}, /* gsec_switches_error */
|
||||
{336723985, "no operation specified"}, /* gsec_no_op_spec */
|
||||
|
@ -1116,6 +1116,7 @@ static const struct {
|
||||
{336397318, -901}, /* 1030 dsql_alter_user_failed */
|
||||
{336397319, -901}, /* 1031 dsql_grant_failed */
|
||||
{336397320, -901}, /* 1032 dsql_revoke_failed */
|
||||
{336397321, -104}, /* 1033 dsql_cte_recursive_aggregate */
|
||||
{336723983, -901}, /* 15 gsec_cant_open_db */
|
||||
{336723984, -901}, /* 16 gsec_switches_error */
|
||||
{336723985, -901}, /* 17 gsec_no_op_spec */
|
||||
|
@ -1116,6 +1116,7 @@ static const struct {
|
||||
{336397318, "42000"}, // 1030 dsql_alter_user_failed
|
||||
{336397319, "42000"}, // 1031 dsql_grant_failed
|
||||
{336397320, "42000"}, // 1032 dsql_revoke_failed
|
||||
{336397321, "42000"}, // 1033 dsql_cte_recursive_aggregate
|
||||
{336723983, "00000"}, // 15 gsec_cant_open_db
|
||||
{336723984, "00000"}, // 16 gsec_switches_error
|
||||
{336723985, "00000"}, // 17 gsec_no_op_spec
|
||||
|
@ -10,7 +10,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
|
||||
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
|
||||
('1996-11-07 13:38:41', 'TEST', 11, 4)
|
||||
('2012-06-23 05:40:21', 'GBAK', 12, 352)
|
||||
('2012-02-18 20:00:00', 'SQLERR', 13, 1033)
|
||||
('2014-01-26 23:00:00', 'SQLERR', 13, 1034)
|
||||
('1996-11-07 13:38:42', 'SQLWARN', 14, 613)
|
||||
('2006-09-10 03:04:31', 'JRD_BUGCHK', 15, 307)
|
||||
('2014-01-13 15:41:16', 'ISQL', 17, 184)
|
||||
|
@ -2551,6 +2551,7 @@ ERROR: Backup incomplete', NULL, NULL);
|
||||
('dsql_alter_user_failed', 'getMainErrorCode', 'DdlNodes.h', NULL, 13, 1030, NULL, 'ALTER USER @1 failed', NULL, NULL);
|
||||
('dsql_grant_failed', 'getMainErrorCode', 'DdlNodes.h', NULL, 13, 1031, NULL, 'GRANT failed', NULL, NULL);
|
||||
('dsql_revoke_failed', 'getMainErrorCode', 'DdlNodes.h', NULL, 13, 1032, NULL, 'REVOKE failed', NULL, NULL);
|
||||
('dsql_cte_recursive_aggregate', 'pass1_rse_impl', 'dsql.cpp', NULL, 13, 1033, NULL, 'Recursive member of CTE cannot use aggregate or window function', NULL, NULL);
|
||||
-- SQLWARN
|
||||
(NULL, NULL, NULL, NULL, 14, 100, NULL, 'Row not found for fetch, update or delete, or the result of a query is an empty table.', NULL, NULL);
|
||||
(NULL, NULL, NULL, NULL, 14, 101, NULL, 'segment buffer length shorter than expected', NULL, NULL);
|
||||
|
@ -1110,6 +1110,7 @@ COMMIT WORK;
|
||||
(-901, '42', '000', 13, 1030, 'dsql_alter_user_failed', NULL, NULL);
|
||||
(-901, '42', '000', 13, 1031, 'dsql_grant_failed', NULL, NULL);
|
||||
(-901, '42', '000', 13, 1032, 'dsql_revoke_failed', NULL, NULL);
|
||||
(-104, '42', '000', 13, 1033, 'dsql_cte_recursive_aggregate', NULL, NULL)
|
||||
-- GSEC
|
||||
(-901, '00', '000', 18, 15, 'gsec_cant_open_db', NULL, NULL)
|
||||
(-901, '00', '000', 18, 16, 'gsec_switches_error', NULL, NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user