/* * Remove the master standby. * * gp_remove_master_standby() * * Returns: * true upon success otherwise false */ Datum gp_remove_master_standby(PG_FUNCTION_ARGS) { int numDel; cqContext cqc; mirroring_sanity_check(SUPERUSER | MASTER_ONLY | UTILITY_MODE, "gp_remove_master_standby"); if (!standby_exists()) elog(ERROR, "no master standby defined"); Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock); numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel), cql("DELETE FROM gp_segment_configuration " " WHERE role = :1", CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG))); elog(LOG, "Remove standby, count : %d.", numDel); heap_close(rel, NoLock); update_gp_master_mirroring("Not Configured"); PG_RETURN_BOOL(true); }
/* * Activate a standby. To do this, we need to change * * 1. Check that we're actually the standby * 2. Remove standby from gp_segment_configuration. * * gp_activate_standby() * * Returns: * true upon success, otherwise throws error. */ Datum gp_activate_standby(PG_FUNCTION_ARGS) { cqContext cqc; int numDel; mirroring_sanity_check(SUPERUSER | UTILITY_MODE | STANDBY_ONLY, PG_FUNCNAME_MACRO); if (!AmIStandby()) elog(ERROR, "%s must be run on the standby master", PG_FUNCNAME_MACRO); /* remove standby from gp_segment_configuration */ Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock); numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel), cql("DELETE FROM gp_segment_configuration " " WHERE role = :1", CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG))); elog(LOG, "Remove standby while activating it, count : %d.", numDel); heap_close(rel, NoLock); /* done */ PG_RETURN_BOOL(true); }
/* * Does a compression algorithm exist by the name of `compresstype'? */ bool compresstype_is_valid(char *comptype) { NameData compname; bool found = false; compname = comptype_to_name(comptype); found = (0 != caql_getcount( NULL, cql("SELECT COUNT(*) FROM pg_compression " " WHERE compname = :1 ", NameGetDatum(&compname)))); /* * FIXME: This is a hack. Should implement related handlers and register * in system tables instead. snappy handlers have already been implemented * but not registerd in system tables (see comment in GetCompressionImplement() * for details). */ if(!found) { if(strcmp(comptype, "snappy") == 0 || strcmp(comptype, "gzip") == 0) found = true; } return found; }
/* * Removes the policy of a table from the gp_distribution_policy table * * Callers must check that there actually *is* a policy for the relation. */ void GpPolicyRemove(Oid tbloid) { Relation gp_policy_rel; cqContext cqc; /* * Open and lock the gp_distribution_policy catalog. */ gp_policy_rel = heap_open(GpPolicyRelationId, RowExclusiveLock); /* Delete the policy entry from the catalog. */ if (0 == caql_getcount( caql_addrel(cqclr(&cqc), gp_policy_rel), cql("DELETE FROM gp_distribution_policy " " WHERE localoid = :1 ", ObjectIdGetDatum(tbloid)))) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("distribution policy for relation \"%d\" does not exist", tbloid))); } /* * Close the gp_distribution_policy relcache entry without unlocking. * We have updated the catalog: consequently the lock must be held until * end of transaction. */ heap_close(gp_policy_rel, NoLock); } /* GpPolicyRemove */
/* * Removes the policy of a table from the gp_distribution_policy table * Does nothing if the policy doesn't exist. */ void GpPolicyRemove(Oid tbloid) { Relation gp_policy_rel; cqContext cqc; /* * Open and lock the gp_distribution_policy catalog. */ gp_policy_rel = heap_open(GpPolicyRelationId, RowExclusiveLock); /* Delete the policy entry from the catalog. */ (void) caql_getcount( caql_addrel(cqclr(&cqc), gp_policy_rel), cql("DELETE FROM gp_distribution_policy " " WHERE localoid = :1 ", ObjectIdGetDatum(tbloid))); /* * Close the gp_distribution_policy relcache entry without unlocking. * We have updated the catalog: consequently the lock must be held until * end of transaction. */ heap_close(gp_policy_rel, NoLock); } /* GpPolicyRemove */
/* * Tell the caller whether a standby master is defined in the system. */ static bool standby_exists() { return caql_getcount( NULL, cql("SELECT COUNT(*) FROM gp_segment_configuration " " WHERE role = :1 ", CharGetDatum(SEGMENT_ROLE_STANDBY_CONFIG))) > 0; }
/* * RemoveFastSequenceEntry * * Remove all entries associated with the given object id. * * If the given objid is an invalid OID, this function simply * returns. * * It is okay for the given valid objid to have no entries in * gp_fastsequence. */ void RemoveFastSequenceEntry(Oid objid) { if (!OidIsValid(objid)) return; (void) caql_getcount( NULL, cql("DELETE FROM gp_fastsequence " " WHERE objid = :1 ", ObjectIdGetDatum(objid))); }
/* * TypeRename * This renames a type * * Note: any associated array type is *not* renamed; caller must make * another call to handle that case. Currently this is only used for * renaming types associated with tables, for which there are no arrays. */ void TypeRename(Oid typeOid, const char *newTypeName) { Relation pg_type_desc; HeapTuple tuple; Form_pg_type form; cqContext *pcqCtx; cqContext cqc, cqc2; pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock); pcqCtx = caql_addrel(cqclr(&cqc), pg_type_desc); tuple = caql_getfirst( pcqCtx, cql("SELECT * FROM pg_type " " WHERE oid = :1 " " FOR UPDATE ", ObjectIdGetDatum(typeOid))); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type with OID \"%d\" does not exist", typeOid))); form = (Form_pg_type) GETSTRUCT(tuple); if (namestrcmp(&(form->typname), newTypeName)) { if (caql_getcount( caql_addrel(cqclr(&cqc2), pg_type_desc), cql("SELECT COUNT(*) FROM pg_type " " WHERE typname = :1 " " AND typnamespace = :2 ", CStringGetDatum((char *) newTypeName), ObjectIdGetDatum(form->typnamespace)))) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", newTypeName))); } namestrcpy(&(form->typname), newTypeName); caql_update_current(pcqCtx, tuple); /* update the system catalog indexes (implicit) */ } heap_freetuple(tuple); heap_close(pg_type_desc, RowExclusiveLock); }
/* * RemoveConversionById * * Remove a tuple from pg_conversion by Oid. This function is solely * called inside catalog/dependency.c */ void RemoveConversionById(Oid conversionOid) { if (0 == caql_getcount( NULL, cql("DELETE FROM pg_conversion " " WHERE oid = :1 ", ObjectIdGetDatum(conversionOid)))) { elog(ERROR, "could not find tuple for conversion %u", conversionOid); } }
/* * Master function to remove a segment from all catalogs */ static void remove_segment(int16 order) { cqContext cqc; int numDel; if(order == MASTER_ORDER_ID || order == STANDBY_ORDER_ID) return; /* remove this segment from gp_segment_configuration */ Relation rel = heap_open(GpSegmentConfigRelationId, AccessExclusiveLock); numDel= caql_getcount(caql_addrel(cqclr(&cqc), rel), cql("DELETE FROM gp_segment_configuration " " WHERE registration_order = :1", Int16GetDatum(order))); elog(LOG, "Remove segment successfully! Count : %d. Registration order : %d", numDel, order); heap_close(rel, NoLock); }
void ExtProtocolDeleteByOid(Oid protOid) { Relation rel; cqContext cqc; /* * Search pg_extprotocol. We use a heapscan here even though there is an * index on oid, on the theory that pg_extprotocol will usually have just a * few entries and so an indexed lookup is a waste of effort. */ rel = heap_open(ExtprotocolRelationId, RowExclusiveLock); if (0 == caql_getcount( caql_addrel(cqclr(&cqc), rel), cql("DELETE FROM pg_extprotocol " " WHERE oid = :1 ", ObjectIdGetDatum(protOid)))) { elog(ERROR, "protocol %u could not be found", protOid); } heap_close(rel, NoLock); }
/* * Apply encoding conversion on src and return it. The encoding * conversion function is chosen from the pg_conversion system catalog * marked as "default". If it is not found in the schema search path, * it's taken from pg_catalog schema. If it even is not in the schema, * warn and return src. * * If conversion occurs, a palloc'd null-terminated string is returned. * In the case of no conversion, src is returned. * * CAUTION: although the presence of a length argument means that callers * can pass non-null-terminated strings, care is required because the same * string will be passed back if no conversion occurs. Such callers *must* * check whether result == src and handle that case differently. * * Note: we try to avoid raising error, since that could get us into * infinite recursion when this function is invoked during error message * sending. It should be OK to raise error for overlength strings though, * since the recursion will come with a shorter message. */ unsigned char * pg_do_encoding_conversion(unsigned char *src, int len, int src_encoding, int dest_encoding) { unsigned char *result; Oid proc; if (!IsTransactionState()) return src; if (src_encoding == dest_encoding) return src; if (src_encoding == PG_SQL_ASCII || dest_encoding == PG_SQL_ASCII) return src; if (len <= 0) return src; proc = FindDefaultConversionProc(src_encoding, dest_encoding); if (!OidIsValid(proc)) { ereport(LOG, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist", pg_encoding_to_char(src_encoding), pg_encoding_to_char(dest_encoding)))); return src; } /* * XXX we should avoid throwing errors in OidFunctionCall. Otherwise we * are going into infinite loop! So we have to make sure that the * function exists before calling OidFunctionCall. */ /* XXX: would have been function_exists() */ if (!(caql_getcount( NULL, cql("SELECT COUNT(*) FROM pg_proc " " WHERE oid = :1 ", ObjectIdGetDatum(proc))) > 0)) { elog(LOG, "cache lookup failed for function %u", proc); return src; } /* * Allocate space for conversion result, being wary of integer overflow */ if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("out of memory"), errdetail("String of %d bytes is too long for encoding conversion.", len))); result = palloc(len * MAX_CONVERSION_GROWTH + 1); OidFunctionCall5(proc, Int32GetDatum(src_encoding), Int32GetDatum(dest_encoding), CStringGetDatum((char *)src), CStringGetDatum((char *)result), Int32GetDatum(len)); return result; }
/* ---------------- * NamespaceCreate * --------------- */ Oid NamespaceCreate(const char *nspName, Oid ownerId, Oid forceOid) { Relation nspdesc; HeapTuple tup; Oid nspoid; bool nulls[Natts_pg_namespace]; Datum values[Natts_pg_namespace]; NameData nname; int i; cqContext cqc; cqContext cqc2; cqContext *pcqCtx; /* sanity checks */ if (!nspName) elog(ERROR, "no namespace name supplied"); nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock); pcqCtx = caql_beginscan( caql_addrel(cqclr(&cqc), nspdesc), cql("INSERT INTO pg_namespace", NULL)); /* make sure there is no existing namespace of same name in the current database */ if (caql_getcount( caql_addrel(cqclr(&cqc2), nspdesc), cql("SELECT COUNT(*) FROM pg_namespace " " WHERE nspname = :1 and nspdboid = :2", PointerGetDatum((char *) nspName), ObjectIdGetDatum((Oid) NSPDBOID_CURRENT)))) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_SCHEMA), errmsg("schema \"%s\" already exists", nspName))); } /* initialize nulls and values */ for (i = 0; i < Natts_pg_namespace; i++) { nulls[i] = false; values[i] = (Datum) 0; } namestrcpy(&nname, nspName); values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname); values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId); nulls[Anum_pg_namespace_nspacl - 1] = true; values[Anum_pg_namespace_nspdboid - 1] = ObjectIdGetDatum((Oid) NSPDBOID_CURRENT); tup = caql_form_tuple(pcqCtx, values, nulls); if (forceOid != InvalidOid) HeapTupleSetOid(tup, forceOid); /* override heap_insert's OID * selection */ /* insert a new tuple */ nspoid = caql_insert(pcqCtx, tup); /* implicit update of index as well */ Assert(OidIsValid(nspoid)); caql_endscan(pcqCtx); heap_close(nspdesc, RowExclusiveLock); /* Record dependency on owner */ recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); return nspoid; }
/* * Rename a tablespace */ void RenameTableSpace(const char *oldname, const char *newname) { Relation rel; Oid tablespaceoid; cqContext cqc; cqContext cqc2; cqContext *pcqCtx; HeapTuple newtuple; Form_pg_tablespace newform; /* Search pg_tablespace */ rel = heap_open(TableSpaceRelationId, RowExclusiveLock); pcqCtx = caql_addrel(cqclr(&cqc), rel); newtuple = caql_getfirst( pcqCtx, cql("SELECT * FROM pg_tablespace " " WHERE spcname = :1 " " FOR UPDATE ", CStringGetDatum(oldname))); if (!HeapTupleIsValid(newtuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("tablespace \"%s\" does not exist", oldname))); newform = (Form_pg_tablespace) GETSTRUCT(newtuple); /* Must be owner */ tablespaceoid = HeapTupleGetOid(newtuple); if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId())) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname); /* Validate new name */ if (!allowSystemTableModsDDL && IsReservedName(newname)) { ereport(ERROR, (errcode(ERRCODE_RESERVED_NAME), errmsg("unacceptable tablespace name \"%s\"", newname), errdetail("The prefix \"%s\" is reserved for system tablespaces.", GetReservedPrefix(newname)))); } /* Make sure the new name doesn't exist */ if (caql_getcount( caql_addrel(cqclr(&cqc2), rel), /* rely on rowexclusive */ cql("SELECT COUNT(*) FROM pg_tablespace " " WHERE spcname = :1 ", CStringGetDatum(newname)))) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("tablespace \"%s\" already exists", newname))); /* OK, update the entry */ namestrcpy(&(newform->spcname), newname); caql_update_current(pcqCtx, newtuple); /* and Update indexes (implicit) */ /* MPP-6929: metadata tracking */ if (Gp_role == GP_ROLE_DISPATCH) MetaTrackUpdObject(TableSpaceRelationId, tablespaceoid, GetUserId(), "ALTER", "RENAME" ); heap_close(rel, NoLock); }
/* * ExtProtocolCreateWithOid */ Oid ExtProtocolCreateWithOid(const char *protocolName, List *readfuncName, List *writefuncName, List *validatorfuncName, Oid protOid, bool trusted) { Relation rel; HeapTuple tup; bool nulls[Natts_pg_extprotocol]; Datum values[Natts_pg_extprotocol]; Oid readfn = InvalidOid; Oid writefn = InvalidOid; Oid validatorfn = InvalidOid; NameData prtname; int i; ObjectAddress myself, referenced; Oid ownerId = GetUserId(); cqContext cqc; cqContext cqc2; cqContext *pcqCtx; /* sanity checks (caller should have caught these) */ if (!protocolName) elog(ERROR, "no protocol name supplied"); if (!readfuncName && !writefuncName) elog(ERROR, "protocol must have at least one of readfunc or writefunc"); /* * Until we add system protocols to pg_extprotocol, make sure no * protocols with the same name are created. */ if (strcasecmp(protocolName, "file") == 0 || strcasecmp(protocolName, "http") == 0 || strcasecmp(protocolName, "gpfdist") == 0 || strcasecmp(protocolName, "gpfdists") == 0) { ereport(ERROR, (errcode(ERRCODE_RESERVED_NAME), errmsg("protocol \"%s\" already exists", protocolName), errhint("pick a different protocol name"))); } rel = heap_open(ExtprotocolRelationId, RowExclusiveLock); pcqCtx = caql_beginscan( caql_addrel(cqclr(&cqc), rel), cql("INSERT INTO pg_extprotocol", NULL)); /* make sure there is no existing protocol of same name */ if (caql_getcount( caql_addrel(cqclr(&cqc2), rel), cql("SELECT COUNT(*) FROM pg_extprotocol " " WHERE ptcname = :1 ", CStringGetDatum((char *) protocolName)))) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("protocol \"%s\" already exists", protocolName))); } /* * function checks: if supplied, check existence and correct signature in the catalog */ if (readfuncName) readfn = ValidateProtocolFunction(readfuncName, EXTPTC_FUNC_READER); if (writefuncName) writefn = ValidateProtocolFunction(writefuncName, EXTPTC_FUNC_WRITER); if (validatorfuncName) validatorfn = ValidateProtocolFunction(validatorfuncName, EXTPTC_FUNC_VALIDATOR); /* * Everything looks okay. Try to create the pg_extprotocol entry for the * protocol. (This could fail if there's already a conflicting entry.) */ /* initialize nulls and values */ for (i = 0; i < Natts_pg_extprotocol; i++) { nulls[i] = false; values[i] = (Datum) 0; } namestrcpy(&prtname, protocolName); values[Anum_pg_extprotocol_ptcname - 1] = NameGetDatum(&prtname); values[Anum_pg_extprotocol_ptcreadfn - 1] = ObjectIdGetDatum(readfn); values[Anum_pg_extprotocol_ptcwritefn - 1] = ObjectIdGetDatum(writefn); values[Anum_pg_extprotocol_ptcvalidatorfn - 1] = ObjectIdGetDatum(validatorfn); values[Anum_pg_extprotocol_ptcowner - 1] = ObjectIdGetDatum(ownerId); values[Anum_pg_extprotocol_ptctrusted - 1] = BoolGetDatum(trusted); nulls[Anum_pg_extprotocol_ptcacl - 1] = true; tup = caql_form_tuple(pcqCtx, values, nulls); if (protOid != (Oid) 0) HeapTupleSetOid(tup, protOid); /* insert a new tuple */ protOid = caql_insert(pcqCtx, tup); /* implicit update of index as well */ caql_endscan(pcqCtx); heap_close(rel, RowExclusiveLock); /* * Create dependencies for the protocol */ myself.classId = ExtprotocolRelationId; myself.objectId = protOid; myself.objectSubId = 0; /* Depends on read function, if any */ if (OidIsValid(readfn)) { referenced.classId = ProcedureRelationId; referenced.objectId = readfn; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* Depends on write function, if any */ if (OidIsValid(writefn)) { referenced.classId = ProcedureRelationId; referenced.objectId = writefn; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* dependency on owner */ recordDependencyOnOwner(ExtprotocolRelationId, protOid, GetUserId()); return protOid; }
/* * Rename conversion */ void RenameConversion(List *name, const char *newname) { Oid conversionOid; Oid namespaceOid; HeapTuple tup; Relation rel; AclResult aclresult; cqContext cqc2; cqContext cqc; cqContext *pcqCtx; rel = heap_open(ConversionRelationId, RowExclusiveLock); conversionOid = FindConversionByName(name); if (!OidIsValid(conversionOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("conversion \"%s\" does not exist", NameListToString(name)))); pcqCtx = caql_addrel(cqclr(&cqc), rel); tup = caql_getfirst( pcqCtx, cql("SELECT * FROM pg_conversion " " WHERE oid = :1 " " FOR UPDATE ", ObjectIdGetDatum(conversionOid))); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "cache lookup failed for conversion %u", conversionOid); namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace; /* make sure the new name doesn't exist */ if (caql_getcount( caql_addrel(cqclr(&cqc2), rel), cql("SELECT COUNT(*) FROM pg_conversion " " WHERE conname = :1 " " AND connamespace = :2 ", CStringGetDatum((char *) newname), ObjectIdGetDatum(namespaceOid)))) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("conversion \"%s\" already exists in schema \"%s\"", newname, get_namespace_name(namespaceOid)))); } /* must be owner */ if (!pg_conversion_ownercheck(conversionOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, NameListToString(name)); /* must have CREATE privilege on namespace */ aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceOid)); /* rename */ namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname); caql_update_current(pcqCtx, tup); /* implicit update of index as well */ heap_close(rel, NoLock); heap_freetuple(tup); }
/* * ConversionCreate * * Add a new tuple to pg_conversion. */ Oid ConversionCreate(const char *conname, Oid connamespace, Oid conowner, int32 conforencoding, int32 contoencoding, Oid conproc, bool def, Oid newOid) { int i; Relation rel; HeapTuple tup; bool nulls[Natts_pg_conversion]; Datum values[Natts_pg_conversion]; NameData cname; Oid oid; ObjectAddress myself, referenced; cqContext cqc; cqContext *pcqCtx; /* sanity checks */ if (!conname) elog(ERROR, "no conversion name supplied"); /* open pg_conversion */ rel = heap_open(ConversionRelationId, RowExclusiveLock); /* make sure there is no existing conversion of same name */ if (caql_getcount( caql_addrel(cqclr(&cqc), rel), cql("SELECT COUNT(*) FROM pg_conversion " " WHERE conname = :1 " " AND connamespace = :2 ", CStringGetDatum((char *) conname), ObjectIdGetDatum(connamespace)))) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("conversion \"%s\" already exists", conname))); } if (def) { /* * make sure there is no existing default <for encoding><to encoding> * pair in this name space */ if (FindDefaultConversion(connamespace, conforencoding, contoencoding)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("default conversion for %s to %s already exists", pg_encoding_to_char(conforencoding), pg_encoding_to_char(contoencoding)))); } pcqCtx = caql_beginscan( caql_addrel(cqclr(&cqc), rel), cql("INSERT INTO pg_conversion", NULL)); /* initialize nulls and values */ for (i = 0; i < Natts_pg_conversion; i++) { nulls[i] = false; values[i] = (Datum) 0; } /* form a tuple */ namestrcpy(&cname, conname); values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname); values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace); values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner); values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding); values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding); values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc); values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def); tup = caql_form_tuple(pcqCtx, values, nulls); if (newOid != 0) HeapTupleSetOid(tup, newOid); /* insert a new tuple */ oid = caql_insert(pcqCtx, tup); /* implicit update of index as well */ Assert(OidIsValid(oid)); myself.classId = ConversionRelationId; myself.objectId = HeapTupleGetOid(tup); myself.objectSubId = 0; /* create dependency on conversion procedure */ referenced.classId = ProcedureRelationId; referenced.objectId = conproc; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); /* create dependency on namespace */ referenced.classId = NamespaceRelationId; referenced.objectId = connamespace; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); /* create dependency on owner */ recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup), conowner); heap_freetuple(tup); caql_endscan(pcqCtx); heap_close(rel, RowExclusiveLock); return oid; }