Пример #1
0
/**
 * This method looks at the Append part of the plan under a join and extracts out interesting bits of information.
 * These include: partitionOid of the master table, partitionInfo that is a struct containing partitioning information,
 * what are the partitioning keys and what does an all null row of the partitioned table look like.
 */
static void MatchAppendPattern(Plan *append, PartitionJoinMutatorContext *ctx)
{
	ctx->partitionOid = InvalidOid;

	/**
	 * It is possible we have already applied the transformation to this subtree.
	 * Check for result node as child.
	 */
	Append *appendNode = (Append *) append;
	Assert(list_length(appendNode->appendplans) > 0);
	Plan *child = (Plan *) list_nth(appendNode->appendplans, 0);
	if (IsA(child, Result))
	{
		ctx->safeToConvert = false;
		return;
	}

	/**
	 * Find all the vars in the targetlist and check if they're from a partitioned table.
	 */
	List *allVars = extract_nodes(NULL /* PlannerGlobal */, (Node *) append->targetlist, T_Var);
	ListCell *lc = NULL;
	foreach (lc, allVars)
	{
		Var *v = (Var *) lfirst(lc);
		RangeTblEntry *rte = rt_fetch(v->varno, ctx->rtable);
		Assert(rte);

		if (!rel_is_partitioned(rte->relid))
		{
			ctx->safeToConvert = false;
			return;
		}

		if (ctx->partitionOid == InvalidOid)
		{
			ctx->partitionOid = rte->relid;
			ctx->partitionVarno = v->varno;
		}

		if (ctx->partitionOid != rte->relid)
		{
			ctx->safeToConvert = false;
			return;
		}
	}
Пример #2
0
void LockSegfilesOnMaster(Relation rel, int32 segno) {
  List *children = NIL;
  ListCell *lc;

  children = find_all_inheritors(rel->rd_id);

  foreach(lc, children)
  {
    Relation child_rel = rel;
    Oid oid = lfirst_oid(lc);

    if (rel_is_partitioned(oid))
      continue;

    /* open/close the child relation. */
    if (oid != rel->rd_id)
      child_rel = heap_open(oid, AccessShareLock);

    LockSegfilesOnMasterForSingleRel(child_rel, segno);

    if (oid != rel->rd_id)
      heap_close(child_rel, AccessShareLock);
  }
Пример #3
0
/*
 * This method takes a decision to run analyze based on the query and the number of modified tuples based
 * on the policy set via gp_autostats_mode. The following modes are currently supported:
 * none			:	no automatic analyzes are issued. simply return.
 * on_change	:	if the number of modified tuples > gp_onchange_threshold, then an automatic analyze is issued.
 * on_no_stats	:	if the operation is a ctas/insert-select and there are no stats on the modified table,
 *					an automatic analyze is issued.
 */
void
auto_stats(AutoStatsCmdType cmdType, Oid relationOid, uint64 ntuples, bool inFunction)
{
	TimestampTz start;
	bool		policyCheck = false;

	start = GetCurrentTimestamp();

	if (Gp_role != GP_ROLE_DISPATCH || relationOid == InvalidOid || rel_is_partitioned(relationOid))
	{
		return;
	}

	Assert(relationOid != InvalidOid);
	Assert(cmdType >= 0 && cmdType <= AUTOSTATS_CMDTYPE_SENTINEL);		/* it is a valid command
																		 * as per auto-stats */

	GpAutoStatsModeValue actual_gp_autostats_mode;

	if (inFunction)
	{
		actual_gp_autostats_mode = gp_autostats_mode_in_functions;
	}
	else
	{
		actual_gp_autostats_mode = gp_autostats_mode;
	}

	switch (actual_gp_autostats_mode)
	{
		case GP_AUTOSTATS_ON_CHANGE:
			policyCheck = autostats_on_change_check(cmdType, ntuples);
			break;
		case GP_AUTOSTATS_ON_NO_STATS:
			policyCheck = autostats_on_no_stats_check(cmdType, relationOid);
			break;
		default:
			Assert(actual_gp_autostats_mode == GP_AUTOSTATS_NONE);
			policyCheck = false;
			break;
	}

	if (!policyCheck)
	{
		elog(DEBUG3, "In mode %s, command %s on (dboid,tableoid)=(%d,%d) modifying " UINT64_FORMAT " tuples did not issue Auto-ANALYZE.",
			 gpvars_show_gp_autostats_mode(),
			 autostats_cmdtype_to_string(cmdType),
			 MyDatabaseId,
			 relationOid,
			 ntuples);

		return;
	}

	if (log_autostats)
	{
		const char *autostats_mode;

		if (inFunction)
		{
			autostats_mode = gpvars_show_gp_autostats_mode_in_functions();
		}
		else
		{
			autostats_mode = gpvars_show_gp_autostats_mode();
		}
		elog(LOG, "In mode %s, command %s on (dboid,tableoid)=(%d,%d) modifying " UINT64_FORMAT " tuples caused Auto-ANALYZE.",
			 autostats_mode,
			 autostats_cmdtype_to_string(cmdType),
			 MyDatabaseId,
			 relationOid,
			 ntuples);
	}

	autostats_issue_analyze(relationOid);

	if (log_duration)
	{
		long		secs;
		int			usecs;
		int			msecs;

		TimestampDifference(start, GetCurrentTimestamp(), &secs, &usecs);
		msecs = usecs / 1000;
		elog(LOG, "duration: %ld.%03d ms Auto-ANALYZE", secs * 1000 + msecs, usecs % 1000);
	}
}
Пример #4
0
/*
 * ValidateErrorTableMetaData
 *
 * This function gets called if a user wants an already existing table to be
 * used as an error table for some COPY or external table operation with SREH.
 * In here we verify that the metadata of the user selected table matches the
 * predefined requirement for an error table.
 */
void
ValidateErrorTableMetaData(Relation rel)
{
	TupleDesc   tupDesc = RelationGetDescr(rel);
	Form_pg_attribute *attr = tupDesc->attrs;
	TupleConstr *constr = tupDesc->constr;
	char		*relname = RelationGetRelationName(rel);
	int			attr_count = tupDesc->natts;

	/*
	 * Verify it is an ordinary table.
	 */
	if (rel->rd_rel->relkind != RELKIND_RELATION)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("error table \"%s\" is not a table", relname)));

	/*
	 * Verify it is a heap table.
	 */
	if (!RelationIsHeap(rel))
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
				 errmsg("error table \"%s\" is not a heap table", relname),
				 errhint("Use a relation with heap storage type for error table")));

	/*
	 * Verify number of attributes match
	 */
	if (attr_count != NUM_ERRORTABLE_ATTR)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
				 errmsg("Relation \"%s\" already exists and is not of a valid "
						"error table format (expected %d attributes, found %d)",
						relname, NUM_ERRORTABLE_ATTR, attr_count)));

	/*
	 * Verify this table is randomly-distributed.
	 */
	if (!GpPolicyIsRandomly(rel->rd_cdbpolicy))
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
				 errmsg("error table \"%s\" is not randomly distributed",
						relname),
				 errhint("Use a randomly-distributed realtion for error table")));

	/*
	 * Verify this table is not a partitioned or child partition table.
	 */
	if (rel_is_partitioned(RelationGetRelid(rel)) ||
		rel_is_child_partition(RelationGetRelid(rel)))
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
				 errmsg("error table \"%s\" is a partitioned table",
						relname),
				 errdetail("Either root or child partition are not allowed as an error table")));

	/*
	 * Verify this table has no constraints.
	 *
	 * This errors out with DEFAULTs, CHECKs or NOT NULLs.
	 *
	 * Unique constraint is not allowed in randomly-distributed table
	 * so we don't check it here.
	 *
	 * We never insert NULL values in some attributes, but allowing
	 * NOT NULL for error table columns doesn't give much convenience
	 * to the user anyway.  Likewise, DEFAULT values are not of interest
	 * mostly, but it does not give much value to user, either.
	 */
	if (constr)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
				 errmsg("Relation \"%s\" already exists and is not of a valid "
						"error table format. If appears to have constraints "
						"defined.", relname)));

	/*
	 * run through each attribute at a time and verify it's what we expect
	 */
	VerifyErrorTableAttr(attr, errtable_cmdtime, "cmdtime", TIMESTAMPTZOID, relname);
	VerifyErrorTableAttr(attr, errtable_relname, "relname", TEXTOID, relname);
	VerifyErrorTableAttr(attr, errtable_filename, "filename", TEXTOID, relname);
	VerifyErrorTableAttr(attr, errtable_linenum, "linenum", INT4OID, relname);
	VerifyErrorTableAttr(attr, errtable_bytenum, "bytenum", INT4OID, relname);
	VerifyErrorTableAttr(attr, errtable_errmsg, "errmsg", TEXTOID, relname);
	VerifyErrorTableAttr(attr, errtable_rawdata, "rawdata", TEXTOID, relname);
	VerifyErrorTableAttr(attr, errtable_rawbytes, "rawbytes", BYTEAOID, relname);
}