示例#1
0
/*
 * Is there a rule by the given name?
 */
bool
IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
{
	return SearchSysCacheExists2(RULERELNAME,
								 ObjectIdGetDatum(owningRel),
								 PointerGetDatum(ruleName));
}
示例#2
0
/*
 * RenameTypeInternal
 *		This renames a type, as well as any associated array type.
 *
 * Caller must have already checked privileges.
 *
 * Currently this is used for renaming table rowtypes and for
 * ALTER TYPE RENAME TO command.
 */
void
RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
{
	Relation	pg_type_desc;
	HeapTuple	tuple;
	Form_pg_type typ;
	Oid			arrayOid;

	pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);

	tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
	if (!HeapTupleIsValid(tuple))
		elog(ERROR, "cache lookup failed for type %u", typeOid);
	typ = (Form_pg_type) GETSTRUCT(tuple);

	/* We are not supposed to be changing schemas here */
	Assert(typeNamespace == typ->typnamespace);

	arrayOid = typ->typarray;

	/* Just to give a more friendly error than unique-index violation */
	if (SearchSysCacheExists2(TYPENAMENSP,
							  CStringGetDatum(newTypeName),
							  ObjectIdGetDatum(typeNamespace)))
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("type \"%s\" already exists", newTypeName)));

	/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
	namestrcpy(&(typ->typname), newTypeName);

	simple_heap_update(pg_type_desc, &tuple->t_self, tuple);

	/* update the system catalog indexes */
	CatalogUpdateIndexes(pg_type_desc, tuple);

	InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);

	heap_freetuple(tuple);
	heap_close(pg_type_desc, RowExclusiveLock);

	/* If the type has an array type, recurse to handle that */
	if (OidIsValid(arrayOid))
	{
		char	   *arrname = makeArrayTypeName(newTypeName, typeNamespace);

		RenameTypeInternal(arrayOid, arrname, typeNamespace);
		pfree(arrname);
	}
}
示例#3
0
/*
 * Rename conversion
 */
Oid
RenameConversion(List *name, const char *newname)
{
    Oid			conversionOid;
    Oid			namespaceOid;
    HeapTuple	tup;
    Relation	rel;
    AclResult	aclresult;

    rel = heap_open(ConversionRelationId, RowExclusiveLock);

    conversionOid = get_conversion_oid(name, false);

    tup = SearchSysCacheCopy1(CONVOID, 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 (SearchSysCacheExists2(CONNAMENSP,
                              CStringGetDatum(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);
    simple_heap_update(rel, &tup->t_self, tup);
    CatalogUpdateIndexes(rel, tup);

    heap_close(rel, NoLock);
    heap_freetuple(tup);

    return conversionOid;
}
示例#4
0
/*
 * makeArrayTypeName
 *	  - given a base type name, make an array type name for it
 *
 * the caller is responsible for pfreeing the result
 */
char *
makeArrayTypeName(const char *typeName, Oid typeNamespace)
{
	char	   *arr = (char *) palloc(NAMEDATALEN);
	int			namelen = strlen(typeName);
	Relation	pg_type_desc;
	int			i;

	/*
	 * The idea is to prepend underscores as needed until we make a name that
	 * doesn't collide with anything...
	 */
	pg_type_desc = heap_open(TypeRelationId, AccessShareLock);

	for (i = 1; i < NAMEDATALEN - 1; i++)
	{
		arr[i - 1] = '_';
		if (i + namelen < NAMEDATALEN)
			strcpy(arr + i, typeName);
		else
		{
			memcpy(arr + i, typeName, NAMEDATALEN - i);
			truncate_identifier(arr, NAMEDATALEN, false);
		}
		if (!SearchSysCacheExists2(TYPENAMENSP,
								   CStringGetDatum(arr),
								   ObjectIdGetDatum(typeNamespace)))
			break;
	}

	heap_close(pg_type_desc, AccessShareLock);

	if (i >= NAMEDATALEN - 1)
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("could not form array type name for type \"%s\"",
						typeName)));

	return arr;
}
示例#5
0
/*
 * 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)
{
    int			i;
    Relation	rel;
    TupleDesc	tupDesc;
    HeapTuple	tup;
    bool		nulls[Natts_pg_conversion];
    Datum		values[Natts_pg_conversion];
    NameData	cname;
    Oid			oid;
    ObjectAddress myself,
                  referenced;

    /* sanity checks */
    if (!conname)
        elog(ERROR, "no conversion name supplied");

    /* make sure there is no existing conversion of same name */
    if (SearchSysCacheExists2(CONNAMENSP,
                              PointerGetDatum(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))));
    }

    /* open pg_conversion */
    rel = heap_open(ConversionRelationId, RowExclusiveLock);
    tupDesc = rel->rd_att;

    /* initialize nulls and values */
    for (i = 0; i < Natts_pg_conversion; i++)
    {
        nulls[i] = false;
        values[i] = (Datum) NULL;
    }

    /* 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 = heap_form_tuple(tupDesc, values, nulls);

    /* insert a new tuple */
    oid = simple_heap_insert(rel, tup);
    Assert(OidIsValid(oid));

    /* update the index if any */
    CatalogUpdateIndexes(rel, tup);

    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);

    /* dependency on extension */
    recordDependencyOnCurrentExtension(&myself, false);

    /* Post creation hook for new conversion */
    InvokeObjectPostCreateHook(ConversionRelationId, HeapTupleGetOid(tup), 0);

    heap_freetuple(tup);
    heap_close(rel, RowExclusiveLock);

    return oid;
}
示例#6
0
/*
 * Insert new publication / relation mapping.
 */
ObjectAddress
publication_add_relation(Oid pubid, Relation targetrel,
						 bool if_not_exists)
{
	Relation	rel;
	HeapTuple	tup;
	Datum		values[Natts_pg_publication_rel];
	bool		nulls[Natts_pg_publication_rel];
	Oid			relid = RelationGetRelid(targetrel);
	Oid			prrelid;
	Publication *pub = GetPublication(pubid);
	ObjectAddress myself,
				referenced;

	rel = heap_open(PublicationRelRelationId, RowExclusiveLock);

	/*
	 * Check for duplicates. Note that this does not really prevent
	 * duplicates, it's here just to provide nicer error message in common
	 * case. The real protection is the unique key on the catalog.
	 */
	if (SearchSysCacheExists2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid),
							  ObjectIdGetDatum(pubid)))
	{
		heap_close(rel, RowExclusiveLock);

		if (if_not_exists)
			return InvalidObjectAddress;

		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_OBJECT),
				 errmsg("relation \"%s\" is already member of publication \"%s\"",
						RelationGetRelationName(targetrel), pub->name)));
	}

	check_publication_add_relation(targetrel);

	/* Form a tuple. */
	memset(values, 0, sizeof(values));
	memset(nulls, false, sizeof(nulls));

	prrelid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId,
								 Anum_pg_publication_rel_oid);
	values[Anum_pg_publication_rel_oid - 1] = ObjectIdGetDatum(prrelid);
	values[Anum_pg_publication_rel_prpubid - 1] =
		ObjectIdGetDatum(pubid);
	values[Anum_pg_publication_rel_prrelid - 1] =
		ObjectIdGetDatum(relid);

	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);

	/* Insert tuple into catalog. */
	CatalogTupleInsert(rel, tup);
	heap_freetuple(tup);

	ObjectAddressSet(myself, PublicationRelRelationId, prrelid);

	/* Add dependency on the publication */
	ObjectAddressSet(referenced, PublicationRelationId, pubid);
	recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);

	/* Add dependency on the relation */
	ObjectAddressSet(referenced, RelationRelationId, relid);
	recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);

	/* Close the table. */
	heap_close(rel, RowExclusiveLock);

	/* Invalidate relcache so that publication info is rebuilt. */
	CacheInvalidateRelcache(targetrel);

	return myself;
}