Exemple #1
0
/*
 * pg_get_extensiondef_string finds the foreign data wrapper that corresponds to
 * the given foreign tableId, and checks if an extension owns this foreign data
 * wrapper. If it does, the function returns the extension's definition. If not,
 * the function returns null.
 */
char *
pg_get_extensiondef_string(Oid tableRelationId)
{
	ForeignTable *foreignTable = GetForeignTable(tableRelationId);
	ForeignServer *server = GetForeignServer(foreignTable->serverid);
	ForeignDataWrapper *foreignDataWrapper = GetForeignDataWrapper(server->fdwid);
	StringInfoData buffer = { NULL, 0, 0, 0 };

	Oid classId = ForeignDataWrapperRelationId;
	Oid objectId = server->fdwid;

	Oid extensionId = getExtensionOfObject(classId, objectId);
	if (OidIsValid(extensionId))
	{
		char *extensionName = get_extension_name(extensionId);
		Oid extensionSchemaId = get_extension_schema(extensionId);
		char *extensionSchema = get_namespace_name(extensionSchemaId);

		initStringInfo(&buffer);
		appendStringInfo(&buffer, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s",
						 quote_identifier(extensionName),
						 quote_identifier(extensionSchema));
	}
	else
	{
		ereport(NOTICE, (errmsg("foreign-data wrapper \"%s\" does not have an "
								"extension defined", foreignDataWrapper->fdwname)));
	}

	return (buffer.data);
}
/*
 * Create partitions and return an OID of the partition that contain value
 */
Oid
create_partitions(Oid relid, Datum value, Oid value_type, bool *crashed)
{
	int 		ret;
	RangeEntry *ranges;
	Datum		vals[2];
	Oid			oids[] = {OIDOID, value_type};
	bool		nulls[] = {false, false};
	char	   *sql;
	bool		found;
	int pos;
	PartRelationInfo *prel;
	RangeRelation	*rangerel;
	FmgrInfo   cmp_func;
	char *schema;

	*crashed = false;
	schema = get_extension_schema();

	prel = get_pathman_relation_info(relid, NULL);
	rangerel = get_pathman_range_relation(relid, NULL);
	ranges = dsm_array_get_pointer(&rangerel->ranges);

	/* Comparison function */
	cmp_func = *get_cmp_func(value_type, prel->atttype);

	vals[0] = ObjectIdGetDatum(relid);
	vals[1] = value;

	/* Perform PL procedure */
	sql = psprintf("SELECT %s.append_partitions_on_demand_internal($1, $2)",
				   schema);
	PG_TRY();
	{
		ret = SPI_execute_with_args(sql, 2, oids, vals, nulls, false, 0);
		if (ret > 0)
		{
			/* Update relation info */
			free_dsm_array(&rangerel->ranges);
			free_dsm_array(&prel->children);
			load_check_constraints(relid, GetCatalogSnapshot(relid));
		}
	}
	PG_CATCH();
	{
		elog(WARNING, "Attempt to create new partitions failed");
		if (crashed != NULL)
			*crashed = true;
		return 0;
	}
	PG_END_TRY();

	/* Repeat binary search */
	ranges = dsm_array_get_pointer(&rangerel->ranges);
	pos = range_binary_search(rangerel, &cmp_func, value, &found);
	if (found)
		return ranges[pos].child_oid;

	return 0;
}
/* LocalTableSize returns the size on disk of the given table. */
static uint64
LocalTableSize(Oid relationId)
{
	uint64 tableSize = 0;
	char relationType = 0;
	Datum relationIdDatum = ObjectIdGetDatum(relationId);

	relationType = get_rel_relkind(relationId);
	if (relationType == RELKIND_RELATION)
	{
		Datum tableSizeDatum = DirectFunctionCall1(pg_table_size, relationIdDatum);

		tableSize = DatumGetInt64(tableSizeDatum);
	}
	else if (relationType == RELKIND_FOREIGN_TABLE)
	{
		bool cstoreTable = CStoreTable(relationId);
		if (cstoreTable)
		{
			/* extract schema name of cstore */
			Oid cstoreId = get_extension_oid(CSTORE_FDW_NAME, false);
			Oid cstoreSchemaOid = get_extension_schema(cstoreId);
			const char *cstoreSchemaName = get_namespace_name(cstoreSchemaOid);

			const int tableSizeArgumentCount = 1;

			Oid tableSizeFunctionOid = FunctionOid(cstoreSchemaName,
												   CSTORE_TABLE_SIZE_FUNCTION_NAME,
												   tableSizeArgumentCount);
			Datum tableSizeDatum = OidFunctionCall1(tableSizeFunctionOid,
													relationIdDatum);

			tableSize = DatumGetInt64(tableSizeDatum);
		}
		else
		{
			char *relationName = get_rel_name(relationId);
			struct stat fileStat;

			int statOK = 0;

			StringInfo localFilePath = makeStringInfo();
			appendStringInfo(localFilePath, FOREIGN_CACHED_FILE_PATH, relationName);

			/* extract the file size using stat, analogous to pg_stat_file */
			statOK = stat(localFilePath->data, &fileStat);
			if (statOK < 0)
			{
				ereport(ERROR, (errcode_for_file_access(),
								errmsg("could not stat file \"%s\": %m",
									   localFilePath->data)));
			}

			tableSize = (uint64) fileStat.st_size;
		}
	}
	else
	{
		char *relationName = get_rel_name(relationId);

		ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						errmsg("cannot get size for table \"%s\"", relationName),
						errdetail("Only regular and foreign tables are supported.")));
	}

	return tableSize;
}