Пример #1
0
/*
 * ProcessUtility hook
 */
static void
pg_record_ProcessUtility(Node *parsetree, const char *queryString,
                    ParamListInfo params, bool isTopLevel,
                    DestReceiver *dest, char *completionTag)
{
    if ((nesting_level == 0) && collect)
    {
        instr_time  start;
        instr_time  duration;
        float       seconds;

        INSTR_TIME_SET_CURRENT(start);

        nesting_level++;
        PG_TRY();
        {
            if (prev_ProcessUtility)
                prev_ProcessUtility(parsetree, queryString, params,
                                    isTopLevel, dest, completionTag);
            else
                standard_ProcessUtility(parsetree, queryString, params,
                                        isTopLevel, dest, completionTag);
            nesting_level--;
        }
        PG_CATCH();
        {
            nesting_level--;
            PG_RE_THROW();
        }
        PG_END_TRY();

        INSTR_TIME_SET_CURRENT(duration);
        INSTR_TIME_SUBTRACT(duration, start);
        
        seconds = INSTR_TIME_GET_DOUBLE(duration);
        
        buffer_add_query(seconds, queryString);

    }
    else
    {
        if (prev_ProcessUtility)
            prev_ProcessUtility(parsetree, queryString, params,
                                isTopLevel, dest, completionTag);
        else
            standard_ProcessUtility(parsetree, queryString, params,
                                    isTopLevel, dest, completionTag);
    }
}
Пример #2
0
queryhist_ProcessUtility(Node *parsetree, const char *queryString,
                         ParamListInfo params, bool isTopLevel,
                         DestReceiver *dest, char *completionTag)
#endif
{
    if (default_histogram_utility && (nesting_level == 0) && query_histogram_enabled())
    {
        /* collecting histogram is enabled, we're in top level (nesting_level=0) */
        instr_time  start;
        instr_time  duration;
        float       seconds;

        INSTR_TIME_SET_CURRENT(start);

        nesting_level++;
        PG_TRY();
        {
            if (prev_ProcessUtility)
#if (PG_VERSION_NUM >= 90300)
                prev_ProcessUtility(parsetree, queryString, context, params,
                                    dest, completionTag);
#else
                prev_ProcessUtility(parsetree, queryString, params,
                                    isTopLevel, dest, completionTag);
#endif
            else
#if (PG_VERSION_NUM >= 90300)
                standard_ProcessUtility(parsetree, queryString, context, params,
                                        dest, completionTag);
#else
                standard_ProcessUtility(parsetree, queryString, params,
                                        isTopLevel, dest, completionTag);
#endif

            nesting_level--;
        }
Пример #3
0
static
void dbrestrict_utility(Node *parsetree,
                        const char *queryString,
                        ProcessUtilityContext context,
                        ParamListInfo params,
                        DestReceiver *dest,
                        char *completionTag)
{
    /* Do our custom process on drop database */
    switch (nodeTag(parsetree))
    {
    case T_DropdbStmt:
    {
        DropdbStmt *stmt = (DropdbStmt *) parsetree;
        char *username = GetUserNameFromId(GetUserId(), false);

        /*
         * Check that only the authorized superuser foo can
         * drop the database undroppable_foodb.
         */
        if (strcmp(stmt->dbname, hook_dbname) == 0 &&
                strcmp(username, hook_username) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg("Only super-superuser \"%s\" can drop database \"%s\"",
                            hook_username, hook_dbname)));
        break;
    }

    default:
        break;
    }

    /*
     * Fallback to normal process, be it the previous hook loaded
     * or the in-core code path if the previous hook does not exist.
     */
    if (prev_utility_hook)
        (*prev_utility_hook) (parsetree, queryString,
                              context, params,
                              dest, completionTag);
    else
        standard_ProcessUtility(parsetree, queryString,
                                context, params,
                                dest, completionTag);
}
Пример #4
0
static void MMProcessUtility(Node *parsetree, const char *queryString,
							 ProcessUtilityContext context, ParamListInfo params,
							 DestReceiver *dest, char *completionTag)
{
	bool skipCommand;
	switch (nodeTag(parsetree))
	{
		case T_TransactionStmt:
		case T_PlannedStmt:
		case T_ClosePortalStmt:
		case T_FetchStmt:
		case T_DoStmt:
		case T_CopyStmt:
		case T_PrepareStmt:
		case T_ExecuteStmt:
		case T_NotifyStmt:
		case T_ListenStmt:
		case T_UnlistenStmt:
		case T_LoadStmt:
		case T_VariableSetStmt:
		case T_VariableShowStmt:
			skipCommand = true;
			break;
	    default:
			skipCommand = false;			
			break;
	}
	if (skipCommand || IsTransactionBlock()) { 
		if (PreviousProcessUtilityHook != NULL)
		{
			PreviousProcessUtilityHook(parsetree, queryString, context,
									   params, dest, completionTag);
		}
		else
		{
			standard_ProcessUtility(parsetree, queryString, context,
									params, dest, completionTag);
		}
		if (!skipCommand) {
			MMIsDistributedTrans = false;
		}
	} else { 		
		MMBroadcastUtilityStmt(queryString, false);
	}
}
Пример #5
0
/*
 * CStoreProcessUtility is the hook for handling utility commands. This function
 * intercepts "COPY cstore_table FROM" statements, and redirectes execution to
 * CopyIntoCStoreTable function. For all other utility statements, the function
 * calls the previous utility hook or the standard utility command.
 */
static void
CStoreProcessUtility(Node *parseTree, const char *queryString,
					 ProcessUtilityContext context, ParamListInfo paramListInfo,
					 DestReceiver *destReceiver, char *completionTag)
{
	bool copyIntoCStoreTable = false;

	/* check if the statement is a "COPY cstore_table FROM ..." statement */
	if (nodeTag(parseTree) == T_CopyStmt)
	{
		CopyStmt *copyStatement = (CopyStmt *) parseTree;
		if (copyStatement->is_from && CStoreTable(copyStatement->relation))
		{
			copyIntoCStoreTable = true;
		}
	}

	if (copyIntoCStoreTable)
	{
		uint64 processed = CopyIntoCStoreTable((CopyStmt *) parseTree, queryString);
		if (completionTag != NULL)
		{
			snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
					 "COPY " UINT64_FORMAT, processed);
		}
	}
	else if (PreviousProcessUtilityHook != NULL)
	{
		PreviousProcessUtilityHook(parseTree, queryString, context, paramListInfo,
								   destReceiver, completionTag);
	}
	else
	{
		standard_ProcessUtility(parseTree, queryString, context, paramListInfo,
								destReceiver, completionTag);
	}
}
Пример #6
0
/*
 * ProcessUtility hook
 */
static void
pgss_ProcessUtility(Node *parsetree, const char *queryString,
					ParamListInfo params, bool isTopLevel,
					DestReceiver *dest, char *completionTag)
{
	if (pgss_track_utility && pgss_enabled())
	{
		instr_time	start;
		instr_time	duration;
		uint64		rows = 0;
		BufferUsage bufusage;

		bufusage = pgBufferUsage;
		INSTR_TIME_SET_CURRENT(start);

		nested_level++;
		PG_TRY();
		{
			if (prev_ProcessUtility)
				prev_ProcessUtility(parsetree, queryString, params,
									isTopLevel, dest, completionTag);
			else
				standard_ProcessUtility(parsetree, queryString, params,
										isTopLevel, dest, completionTag);
			nested_level--;
		}
		PG_CATCH();
		{
			nested_level--;
			PG_RE_THROW();
		}
		PG_END_TRY();

		INSTR_TIME_SET_CURRENT(duration);
		INSTR_TIME_SUBTRACT(duration, start);

		/* parse command tag to retrieve the number of affected rows. */
		if (completionTag &&
			sscanf(completionTag, "COPY " UINT64_FORMAT, &rows) != 1)
			rows = 0;

		/* calc differences of buffer counters. */
		bufusage.shared_blks_hit =
			pgBufferUsage.shared_blks_hit - bufusage.shared_blks_hit;
		bufusage.shared_blks_read =
			pgBufferUsage.shared_blks_read - bufusage.shared_blks_read;
		bufusage.shared_blks_written =
			pgBufferUsage.shared_blks_written - bufusage.shared_blks_written;
		bufusage.local_blks_hit =
			pgBufferUsage.local_blks_hit - bufusage.local_blks_hit;
		bufusage.local_blks_read =
			pgBufferUsage.local_blks_read - bufusage.local_blks_read;
		bufusage.local_blks_written =
			pgBufferUsage.local_blks_written - bufusage.local_blks_written;
		bufusage.temp_blks_read =
			pgBufferUsage.temp_blks_read - bufusage.temp_blks_read;
		bufusage.temp_blks_written =
			pgBufferUsage.temp_blks_written - bufusage.temp_blks_written;

		pgss_store(queryString, INSTR_TIME_GET_DOUBLE(duration), rows,
				   &bufusage);
	}
	else
	{
		if (prev_ProcessUtility)
			prev_ProcessUtility(parsetree, queryString, params,
								isTopLevel, dest, completionTag);
		else
			standard_ProcessUtility(parsetree, queryString, params,
									isTopLevel, dest, completionTag);
	}
}
Пример #7
0
static void
trunc2del(Node *parsetree,
		  const char *queryString,
		  ProcessUtilityContext context,
		  ParamListInfo params,
		  DestReceiver *dest,
		  char *completionTag)
{
	/*
	 * Do custom processing for TRUNCATE. Note that this is not aimed at
	 * doing much for TRUNCATE CASCADE and triggers that should fire here.
	 * This becomes even more a mess should a DELETE trigger be defined
	 * on this relation.
	 */
	switch (nodeTag(parsetree))
	{
		case T_TruncateStmt:
		{
			TruncateStmt   *stmt = (TruncateStmt *) parsetree;
			RangeVar	   *rv = (RangeVar *) linitial(stmt->relations);
			int				ret;
			StringInfoData	buf;
			Relation		rel;

			/*
			 * Check existence of relation queried, this is important in case
			 * of an unexistent relation to not let the user know of this
			 * run switch. As we are faking a TRUNCATE, it is as well important
			 * to take a exclusive lock on the relation operated on.
			 */
			rel = heap_openrv(rv, AccessExclusiveLock);

			SPI_connect();
			initStringInfo(&buf);

			appendStringInfo(&buf, "DELETE FROM ");

			if (rv->schemaname)
				appendStringInfo(&buf,"%s.",
								 quote_identifier(rv->schemaname));

			appendStringInfo(&buf, "%s;", quote_identifier(rv->relname));

			ret = SPI_execute(buf.data, false, 0);

			if (ret != SPI_OK_DELETE)
				elog(ERROR, "Error while executing TRUNCATE (really?)");

			SPI_finish();

			/* keep lock until the end of transaction */
			heap_close(rel, NoLock);
			return;
		}
		default:
			break;
	}

	/*
	 * Fallback to normal process, be it the previous hook loaded
	 * or the in-core code path if the previous hook does not exist.
	 */
	if (prev_utility_hook)
		(*prev_utility_hook) (parsetree, queryString,
							  context, params,
							  dest, completionTag);
	 else
		 standard_ProcessUtility(parsetree, queryString,
								 context, params,
								 dest, completionTag);
}