/*------------------------------------------------------------------------- * * qualify_type_stmt.c * Functions specialized in fully qualifying all type statements. These * functions are dispatched from qualify.c * * Fully qualifying type statements consists of adding the schema name * to the subject of the types as well as any other branch of the * parsetree. * * Goal would be that the deparser functions for these statements can * serialize the statement without any external lookups. * * Copyright (c) Citus Data, Inc. * *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/heapam.h" #include "access/htup_details.h" #include "catalog/namespace.h" #include "catalog/objectaddress.h" #include "catalog/pg_type.h" #include "distributed/deparser.h" #include "distributed/metadata/namespace.h" #include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "utils/syscache.h" #include "utils/lsyscache.h" static char * GetTypeNamespaceNameByNameList(List *names); static Oid TypeOidGetNamespaceOid(Oid typeOid); /* * GetTypeNamespaceNameByNameList resolved the schema name of a type by its namelist. */ static char * GetTypeNamespaceNameByNameList(List *names) { TypeName *typeName = makeTypeNameFromNameList(names); Oid typeOid = LookupTypeNameOid(NULL, typeName, false); Oid namespaceOid = TypeOidGetNamespaceOid(typeOid); char *nspname = get_namespace_name_or_temp(namespaceOid); return nspname; } /* * TypeOidGetNamespaceOid resolves the namespace oid for a type identified by its type oid */ static Oid TypeOidGetNamespaceOid(Oid typeOid) { HeapTuple typeTuple = SearchSysCache1(TYPEOID, typeOid); if (!HeapTupleIsValid(typeTuple)) { elog(ERROR, "citus cache lookup failed"); return InvalidOid; } Form_pg_type typeData = (Form_pg_type) GETSTRUCT(typeTuple); Oid typnamespace = typeData->typnamespace; ReleaseSysCache(typeTuple); return typnamespace; } void QualifyRenameTypeStmt(Node *node) { RenameStmt *stmt = castNode(RenameStmt, node); List *names = (List *) stmt->object; Assert(stmt->renameType == OBJECT_TYPE); if (list_length(names) == 1) { /* not qualified, lookup name and add namespace name to names */ char *nspname = GetTypeNamespaceNameByNameList(names); names = list_make2(makeString(nspname), linitial(names)); stmt->object = (Node *) names; } } void QualifyRenameTypeAttributeStmt(Node *node) { RenameStmt *stmt = castNode(RenameStmt, node); Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->relationType == OBJECT_TYPE); if (stmt->relation->schemaname == NULL) { List *names = list_make1(makeString(stmt->relation->relname)); char *nspname = GetTypeNamespaceNameByNameList(names); stmt->relation->schemaname = nspname; } } void QualifyAlterEnumStmt(Node *node) { AlterEnumStmt *stmt = castNode(AlterEnumStmt, node); List *names = stmt->typeName; if (list_length(names) == 1) { /* not qualified, lookup name and add namespace name to names */ char *nspname = GetTypeNamespaceNameByNameList(names); names = list_make2(makeString(nspname), linitial(names)); stmt->typeName = names; } } void QualifyAlterTypeStmt(Node *node) { AlterTableStmt *stmt = castNode(AlterTableStmt, node); Assert(stmt->relkind == OBJECT_TYPE); if (stmt->relation->schemaname == NULL) { List *names = MakeNameListFromRangeVar(stmt->relation); char *nspname = GetTypeNamespaceNameByNameList(names); stmt->relation->schemaname = nspname; } } void QualifyCompositeTypeStmt(Node *node) { CompositeTypeStmt *stmt = castNode(CompositeTypeStmt, node); if (stmt->typevar->schemaname == NULL) { Oid creationSchema = RangeVarGetCreationNamespace(stmt->typevar); stmt->typevar->schemaname = get_namespace_name(creationSchema); } } void QualifyCreateEnumStmt(Node *node) { CreateEnumStmt *stmt = castNode(CreateEnumStmt, node); if (list_length(stmt->typeName) == 1) { char *objname = NULL; Oid creationSchema = QualifiedNameGetCreationNamespace(stmt->typeName, &objname); stmt->typeName = list_make2(makeString(get_namespace_name(creationSchema)), linitial(stmt->typeName)); } } void QualifyAlterTypeSchemaStmt(Node *node) { AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node); Assert(stmt->objectType == OBJECT_TYPE); List *names = (List *) stmt->object; if (list_length(names) == 1) { /* not qualified with schema, lookup type and its schema s*/ char *nspname = GetTypeNamespaceNameByNameList(names); names = list_make2(makeString(nspname), linitial(names)); stmt->object = (Node *) names; } } void QualifyAlterTypeOwnerStmt(Node *node) { AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); Assert(stmt->objectType == OBJECT_TYPE); List *names = (List *) stmt->object; if (list_length(names) == 1) { /* not qualified with schema, lookup type and its schema s*/ char *nspname = GetTypeNamespaceNameByNameList(names); names = list_make2(makeString(nspname), linitial(names)); stmt->object = (Node *) names; } }