Skip to content

Commit

Permalink
Simplify the planner hook for columnar tableam (#257)
Browse files Browse the repository at this point in the history
At present, we have two planner hooks in columnar_customscan.c and
columnar_planner_hook.c separately.  The first hook only sets
stmt->parallelModeNeeded to zero when the query is a CREATE TABLE AS
statement, so we can simplify this code by moving it to the second one.
  • Loading branch information
japinli authored May 21, 2024
1 parent 6f709d5 commit a4c3cf5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 89 deletions.
89 changes: 0 additions & 89 deletions columnar/src/backend/columnar/columnar_customscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planner.h"
#include "optimizer/restrictinfo.h"
#if PG_VERSION_NUM >= PG_VERSION_16
#include "parser/parse_relation.h"
Expand Down Expand Up @@ -140,8 +139,6 @@ static void ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index
RangeTblEntry *rte);
static void ColumnarGetRelationInfoHook(PlannerInfo *root, Oid relationObjectId,
bool inhparent, RelOptInfo *rel);
static PlannedStmt *ColumnarPlannerHook(Query *parse, const char *query_string,
int cursorOptions, ParamListInfo boundParams);

static Plan * ColumnarScanPath_PlanCustomPath(PlannerInfo *root,
RelOptInfo *rel,
Expand Down Expand Up @@ -188,12 +185,10 @@ static List * set_deparse_context_planstate(List *dpcontext, Node *node,

/* other helpers */
static List * ColumnarVarNeeded(ColumnarScanState *columnarScanState);
static bool IsCreateTableAs(const char *query);

/* saved hook value in case of unload */
static set_rel_pathlist_hook_type PreviousSetRelPathlistHook = NULL;
static get_relation_info_hook_type PreviousGetRelationInfoHook = NULL;
static planner_hook_type PreviousPlannerHook = NULL;

static bool EnableColumnarCustomScan = true;
static bool EnableColumnarQualPushdown = true;
Expand Down Expand Up @@ -264,9 +259,6 @@ columnar_customscan_init()
PreviousGetRelationInfoHook = get_relation_info_hook;
get_relation_info_hook = ColumnarGetRelationInfoHook;

PreviousPlannerHook = planner_hook;
planner_hook = ColumnarPlannerHook;

/* register customscan specific GUC's */
DefineCustomBoolVariable(
"columnar.enable_custom_scan",
Expand Down Expand Up @@ -330,87 +322,6 @@ columnar_customscan_init()
RegisterCustomScanMethods(&ColumnarScanScanMethods);
}

/*
* IsCreateTableAs
*
* Searches a lower case copy of the query string using strstr to check
* for the keywords CREATE, TABLE, and AS, in that order. There can be
* false positives, but we try to minimize them.
*/
static
bool IsCreateTableAs(const char *query)
{
char *c, *t, *a;
char *haystack = (char *) palloc(strlen(query) + 1);
int16 i;

/* Create a lower case copy of the string. */
for (i = 0; i < strlen(query); i++)
{
haystack[i] = tolower(query[i]);
}

haystack[i] = '\0';

c = strstr(haystack, "create");
if (c == NULL)
{
pfree(haystack);
return false;
}

t = strstr(c + 6, "table");
if (t == NULL)
{
pfree(haystack);
return false;
}

a = strstr(t + 5, "as");
if (a == NULL)
{
pfree(haystack);
return false;
}

pfree(haystack);

return true;
}

static
PlannedStmt *ColumnarPlannerHook(Query *parse, const char *query_string,
int cursorOptions, ParamListInfo boundParams)
{
PlannedStmt *stmt;

if (PreviousPlannerHook)
{
stmt = (*PreviousPlannerHook)(parse, query_string, cursorOptions, boundParams);
}
else
{
stmt = standard_planner(parse, query_string, cursorOptions, boundParams);
}

/*
* In the case of a CREATE TABLE AS query, we are not able to successfully
* drop out of a parallel insert situation. This checks for a CMD_SELECT
* and in that case examines the query string to see if it matches the
* pattern of a CREATE TABLE AS. If so, set the parallelism to 0 (off).
*/
if (parse->commandType == CMD_SELECT)
{
if (IsCreateTableAs(query_string))
{
stmt->parallelModeNeeded = 0;
}
}

return stmt;
}


static void
ColumnarSetRelPathlistHook(PlannerInfo *root, RelOptInfo *rel, Index rti,
RangeTblEntry *rte)
Expand Down
62 changes: 62 additions & 0 deletions columnar/src/backend/columnar/columnar_planner_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static Oid columnar_tableam_oid = InvalidOid;

static PlannedStmt * ColumnarPlannerHook(Query *parse, const char *query_string,
int cursorOptions, ParamListInfo boundParams);
static bool IsCreateTableAs(const char *query);

#if PG_VERSION_NUM >= PG_VERSION_14
static Plan * PlanTreeMutator(Plan *node, void *context);
Expand Down Expand Up @@ -326,6 +327,20 @@ ColumnarPlannerHook(Query *parse,
else
stmt = standard_planner(parse, query_string, cursorOptions, boundParams);

/*
* In the case of a CREATE TABLE AS query, we are not able to successfully
* drop out of a parallel insert situation. This checks for a CMD_SELECT
* and in that case examines the query string to see if it matches the
* pattern of a CREATE TABLE AS. If so, set the parallelism to 0 (off).
*/
if (parse->commandType == CMD_SELECT)
{
if (IsCreateTableAs(query_string))
{
stmt->parallelModeNeeded = 0;
}
}

#if PG_VERSION_NUM >= PG_VERSION_14
if (!(columnar_enable_vectorization /* Vectorization should be enabled */
|| columnar_index_scan) /* or Columnar Index Scan */
Expand Down Expand Up @@ -382,6 +397,53 @@ ColumnarPlannerHook(Query *parse,
return stmt;
}

/*
* IsCreateTableAs
*
* Searches a lower case copy of the query string using strstr to check
* for the keywords CREATE, TABLE, and AS, in that order. There can be
* false positives, but we try to minimize them.
*/
static bool
IsCreateTableAs(const char *query)
{
char *c, *t, *a;
char *haystack = (char *) palloc(strlen(query) + 1);
int16 i;

/* Create a lower case copy of the string. */
for (i = 0; i < strlen(query); i++)
{
haystack[i] = tolower(query[i]);
}

haystack[i] = '\0';

c = strstr(haystack, "create");
if (c == NULL)
{
pfree(haystack);
return false;
}

t = strstr(c + 6, "table");
if (t == NULL)
{
pfree(haystack);
return false;
}

a = strstr(t + 5, "as");
if (a == NULL)
{
pfree(haystack);
return false;
}

pfree(haystack);

return true;
}

void columnar_planner_init(void)
{
Expand Down

0 comments on commit a4c3cf5

Please sign in to comment.