diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 1677ddf06bf29433bcca53026ad08bb577ea6be2..6263436531dd6a8a93fb03cc2025ab06c865905b 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -5125,6 +5125,29 @@ void CheckSelectLocking(Query* qry) } } +static bool CheckViewBasedOnCstore(Relation targetrel) +{ + Assert(RelationIsView(targetrel)); + + Query* viewquery = get_view_query(targetrel); + ListCell* l = NULL; + + foreach (l, viewquery->jointree->fromlist) { + RangeTblRef* rtr = (RangeTblRef*)lfirst(l); + RangeTblEntry* base_rte = rt_fetch(rtr->rtindex, viewquery->rtable); + Relation base_rel = try_relation_open(base_rte->relid, AccessShareLock); + + if (RelationIsColStore(base_rel) || (RelationIsView(base_rel) && CheckViewBasedOnCstore(base_rel))) { + heap_close(base_rel, AccessShareLock); + return true; + } + + heap_close(base_rel, AccessShareLock); + } + + return false; +} + /* * Transform a FOR [KEY] UPDATE/SHARE clause * @@ -5187,6 +5210,12 @@ static void transformLockingClause(ParseState* pstate, Query* qry, LockingClause (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with " "column table \"%s\"", rte->eref->aliasname))); + } else if (RelationIsView(rel) && CheckViewBasedOnCstore(rel)) { + heap_close(rel, AccessShareLock); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with " + "view \"%s\" based on column table", rte->eref->aliasname))); } else { if (!RelationIsAstoreFormat(rel) && lc->waitPolicy == LockWaitSkip) { ereport(ERROR, @@ -5253,7 +5282,14 @@ static void transformLockingClause(ParseState* pstate, Query* qry, LockingClause errmsg("SELECT FOR UPDATE/SHARE%s cannot be used with column table \"%s\"", NOKEYUPDATE_KEYSHARE_ERRMSG, rte->eref->aliasname), parser_errposition(pstate, thisrel->location))); - }else { + } else if (RelationIsView(rel) && CheckViewBasedOnCstore(rel)) { + heap_close(rel, AccessShareLock); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("SELECT FOR UPDATE/SHARE%s cannot be used with view \"%s\" based on" + " column table", NOKEYUPDATE_KEYSHARE_ERRMSG, rte->eref->aliasname), + parser_errposition(pstate, thisrel->location))); + } else { if (!RelationIsAstoreFormat(rel) && lc->waitPolicy == LockWaitSkip) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), diff --git a/src/test/regress/expected/disable_vector_engine.out b/src/test/regress/expected/disable_vector_engine.out index ff8fafcdfe6fbc46a324689c927bfa8a8acdde14..799d4d61a5d84635cfe30aaa82de889c7007675a 100644 --- a/src/test/regress/expected/disable_vector_engine.out +++ b/src/test/regress/expected/disable_vector_engine.out @@ -116,6 +116,23 @@ RESET ENABLE_HASHAGG; -- LockRows EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01 FOR UPDATE; ERROR: SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with column table "vector_table_01" +-- LockRows for view +CREATE VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW AS SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01; +CREATE VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 AS SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW; +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW FOR UPDATE; +ERROR: SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with view "vector_table_01_view" based on column table +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW FOR UPDATE OF VECTOR_TABLE_01_VIEW; +ERROR: SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with view "vector_table_01_view" based on column table +LINE 1: ..._VECTOR_ENGINE.VECTOR_TABLE_01_VIEW FOR UPDATE OF VECTOR_TAB... + ^ +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 FOR UPDATE; +ERROR: SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with view "vector_table_01_view1" based on column table +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 FOR UPDATE OF VECTOR_TABLE_01_VIEW1; +ERROR: SELECT FOR UPDATE/SHARE/NO KEY UPDATE/KEY SHARE cannot be used with view "vector_table_01_view1" based on column table +LINE 1: ...VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 FOR UPDATE OF VECTOR_TAB... + ^ +DROP VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1; +DROP VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW; -- CteScan -- HashJoin, MergeJoin, NestLoop, Materialize EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01 T1, DISABLE_VECTOR_ENGINE.VECTOR_TABLE_02 T2 WHERE T1.DEPNAME=T2.DEPNAME; diff --git a/src/test/regress/sql/disable_vector_engine.sql b/src/test/regress/sql/disable_vector_engine.sql index 4a744a3b4fd77ac305787da0cb04006a6c20074a..8f1d9569a402fd71fe276b9db2b19cf719631bca 100644 --- a/src/test/regress/sql/disable_vector_engine.sql +++ b/src/test/regress/sql/disable_vector_engine.sql @@ -60,6 +60,19 @@ RESET ENABLE_HASHAGG; -- LockRows EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01 FOR UPDATE; +-- LockRows for view +CREATE VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW AS SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01; +CREATE VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 AS SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW; + +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW FOR UPDATE; +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW FOR UPDATE OF VECTOR_TABLE_01_VIEW; + +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 FOR UPDATE; +EXPLAIN (COSTS OFF) SELECT * FROM DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1 FOR UPDATE OF VECTOR_TABLE_01_VIEW1; + +DROP VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW1; +DROP VIEW DISABLE_VECTOR_ENGINE.VECTOR_TABLE_01_VIEW; + -- CteScan