diff --git a/src/common/backend/parser/parse_utilcmd.cpp b/src/common/backend/parser/parse_utilcmd.cpp index 7c3ac0e17..ab7aa98a6 100644 --- a/src/common/backend/parser/parse_utilcmd.cpp +++ b/src/common/backend/parser/parse_utilcmd.cpp @@ -5283,6 +5283,48 @@ static void transformConstraintAttrs(CreateStmtContext* cxt, List* constraintLis } } +/** + * tableof type is not supported be a column in a table + * @param ctype ctype + */ +static void CheckColumnTableOfType(Type ctype) +{ + Form_pg_type typTup = (Form_pg_type)GETSTRUCT(ctype); + if (typTup->typtype == TYPTYPE_TABLEOF) { + ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmodule(MOD_PLSQL), + errmsg("type \"%s\" is not supported as column type", NameStr(typTup->typname)), + errdetail("\"%s\" is a nest table type", NameStr(typTup->typname)), + errcause("feature not supported"), erraction("check type name"))); + } else if (typTup->typtype == TYPTYPE_COMPOSITE) { + TupleDesc tupleDesc = lookup_rowtype_tupdesc_noerror(HeapTupleGetOid(ctype), typTup->typtypmod, true); + if (tupleDesc == NULL) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("type %u cannot get tupledesc", HeapTupleGetOid(ctype)))); + } + for (int i = 0; i < tupleDesc->natts; i++) { + if (tupleDesc->attrs[i].attisdropped) { + continue; + } + HeapTuple typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(tupleDesc->attrs[i].atttypid)); + if (!HeapTupleIsValid(typeTuple)) { + ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), + errmsg("cache lookup failed for type %u", tupleDesc->attrs[i].atttypid))); + } + CheckColumnTableOfType(typeTuple); + ReleaseSysCache(typeTuple); + } + ReleaseTupleDesc(tupleDesc); + } else if (OidIsValid(typTup->typelem) && typTup->typtype == TYPTYPE_BASE) { + HeapTuple typTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typTup->typelem)); + if (!HeapTupleIsValid(typTuple)) { + ereport(ERROR, + (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for type %u", typTup->typelem))); + } + CheckColumnTableOfType(typTuple); + ReleaseSysCache(typTuple); + } +} + /* * Special handling of type definition for a column */ @@ -5324,6 +5366,7 @@ static void transformColumnType(CreateStmtContext* cxt, ColumnDef* column) erraction("check type name"))); } #endif + CheckColumnTableOfType(ctype); ReleaseSysCache(ctype); } diff --git a/src/test/regress/expected/tableof_unsupported.out b/src/test/regress/expected/tableof_unsupported.out new file mode 100644 index 000000000..9cfc8a93e --- /dev/null +++ b/src/test/regress/expected/tableof_unsupported.out @@ -0,0 +1,16 @@ +------ Prepare ------ +-- create type of TYPTYPE_TABLEOF +create type r0 is (c1 int1, c2 int2); +create type t0 is table of int4; +create type t1 is (c1 int1, c2 t0); +create type t2 is table of r0; +-- create table +create table tableof_unsupported(id t0); +ERROR: type "t0" is not supported as column type +DETAIL: "t0" is a nest table type +create table tableof_unsupported(id t1); +ERROR: type "t0" is not supported as column type +DETAIL: "t0" is a nest table type +create table tableof_unsupported(id t2); +ERROR: type "t2" is not supported as column type +DETAIL: "t2" is a nest table type diff --git a/src/test/regress/sql/tableof_unsupported.sql b/src/test/regress/sql/tableof_unsupported.sql new file mode 100644 index 000000000..f574c6a66 --- /dev/null +++ b/src/test/regress/sql/tableof_unsupported.sql @@ -0,0 +1,12 @@ +------ Prepare ------ +-- create type of TYPTYPE_TABLEOF +create type r0 is (c1 int1, c2 int2); + +create type t0 is table of int4; +create type t1 is (c1 int1, c2 t0); +create type t2 is table of r0; + +-- create table +create table tableof_unsupported(id t0); +create table tableof_unsupported(id t1); +create table tableof_unsupported(id t2); \ No newline at end of file