OSDN Git Service

関数の配置を変更した。
authorMitsuru Hasegawa <hasegawa@metrosystems.co.jp>
Thu, 26 Jul 2012 09:29:22 +0000 (18:29 +0900)
committerMitsuru Hasegawa <hasegawa@metrosystems.co.jp>
Thu, 26 Jul 2012 09:29:22 +0000 (18:29 +0900)
pg_hint_plan.c

index 8f3d72e..bb9b0a7 100644 (file)
@@ -229,9 +229,11 @@ typedef struct HintParser
 void           _PG_init(void);
 void           _PG_fini(void);
 
-void pg_hint_plan_ProcessUtility(Node *parsetree, const char *queryString,
-                                                                ParamListInfo params, bool isTopLevel,
-                                                                DestReceiver *dest, char *completionTag);
+static void pg_hint_plan_ProcessUtility(Node *parsetree,
+                                                                               const char *queryString,
+                                                                               ParamListInfo params, bool isTopLevel,
+                                                                               DestReceiver *dest,
+                                                                               char *completionTag);
 static PlannedStmt *pg_hint_plan_planner(Query *parse, int cursorOptions,
                                                                                 ParamListInfo boundParams);
 static void pg_hint_plan_get_relation_info(PlannerInfo *root,
@@ -276,8 +278,6 @@ static void make_rels_by_clauseless_joins(PlannerInfo *root,
                                                                                  RelOptInfo *old_rel,
                                                                                  ListCell *other_rels);
 static bool has_join_restriction(PlannerInfo *root, RelOptInfo *rel);
-static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
-                                                        Index rti, RangeTblEntry *rte);
 static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                                                   RangeTblEntry *rte);
 static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
@@ -417,83 +417,9 @@ _PG_fini(void)
        join_search_hook = prev_join_search;
 }
 
-static void
-ProcessUtility_hook_error_callback(void *arg)
-{
-       stmt_name = NULL;
-}
-
-void
-pg_hint_plan_ProcessUtility(Node *parsetree, const char *queryString,
-                                                       ParamListInfo params, bool isTopLevel,
-                                                       DestReceiver *dest, char *completionTag)
-{
-       Node                               *node;
-       ErrorContextCallback    errcontext;
-
-       if (!pg_hint_plan_enable)
-       {
-               if (prev_ProcessUtility)
-                       (*prev_ProcessUtility) (parsetree, queryString, params,
-                                                                       isTopLevel, dest, completionTag);
-               else
-                       standard_ProcessUtility(parsetree, queryString, params,
-                                                                       isTopLevel, dest, completionTag);
-
-               return;
-       }
-
-       node = parsetree;
-       if (IsA(node, ExplainStmt))
-       {
-               /*
-                * EXPLAIN対象のクエリのパースツリーを取得する
-                */
-               ExplainStmt        *stmt;
-               Query              *query;
-
-               stmt = (ExplainStmt *) node;
-
-               Assert(IsA(stmt->query, Query));
-               query = (Query *) stmt->query;
-
-               if (query->commandType == CMD_UTILITY && query->utilityStmt != NULL)
-                       node = query->utilityStmt;
-       }
-
-       /*
-        * EXECUTEコマンドならば、PREPARE時に指定されたクエリ文字列を取得し、ヒント
-        * 句の候補として設定する
-        */
-       if (IsA(node, ExecuteStmt))
-       {
-               ExecuteStmt        *stmt;
-
-               /* Set up callback to statement name reset. */
-               errcontext.callback = ProcessUtility_hook_error_callback;
-               errcontext.arg = NULL;
-               errcontext.previous = error_context_stack;
-               error_context_stack = &errcontext;
-
-               stmt = (ExecuteStmt *) node;
-               stmt_name = stmt->name;
-       }
-
-       if (prev_ProcessUtility)
-               (*prev_ProcessUtility) (parsetree, queryString, params,
-                                                               isTopLevel, dest, completionTag);
-       else
-               standard_ProcessUtility(parsetree, queryString, params,
-                                                               isTopLevel, dest, completionTag);
-
-       if (stmt_name)
-       {
-               stmt_name = NULL;
-
-               /* Remove error callback. */
-               error_context_stack = errcontext.previous;
-       }
-}
+/*
+ * create and delete functions the hint object
+ */
 
 static Hint *
 ScanMethodHintCreate(const char *hint_str, const char *keyword)
@@ -528,49 +454,6 @@ ScanMethodHintDelete(ScanMethodHint *hint)
        pfree(hint);
 }
 
-static void
-dump_quote_value(StringInfo buf, const char *value)
-{
-       bool            need_quote = false;
-       const char *str;
-
-       for (str = value; *str != '\0'; str++)
-       {
-               if (isspace(*str) || *str == ')' || *str == '"')
-               {
-                       need_quote = true;
-                       appendStringInfoCharMacro(buf, '"');
-                       break;
-               }
-       }
-
-       for (str = value; *str != '\0'; str++)
-       {
-               if (*str == '"')
-                       appendStringInfoCharMacro(buf, '"');
-
-               appendStringInfoCharMacro(buf, *str);
-       }
-
-       if (need_quote)
-               appendStringInfoCharMacro(buf, '"');
-}
-
-static void
-ScanMethodHintDump(ScanMethodHint *hint, StringInfo buf)
-{
-       ListCell   *l;
-
-       appendStringInfo(buf, "%s(", hint->base.keyword);
-       dump_quote_value(buf, hint->relname);
-       foreach(l, hint->indexnames)
-       {
-               appendStringInfoCharMacro(buf, ' ');
-               dump_quote_value(buf, (char *) lfirst(l));
-       }
-       appendStringInfoString(buf, ")\n");
-}
-
 static Hint *
 JoinMethodHintCreate(const char *hint_str, const char *keyword)
 {
@@ -611,22 +494,6 @@ JoinMethodHintDelete(JoinMethodHint *hint)
        pfree(hint);
 }
 
-static void
-JoinMethodHintDump(JoinMethodHint *hint, StringInfo buf)
-{
-       int     i;
-
-       appendStringInfo(buf, "%s(", hint->base.keyword);
-       dump_quote_value(buf, hint->relnames[0]);
-       for (i = 1; i < hint->nrels; i++)
-       {
-               appendStringInfoCharMacro(buf, ' ');
-               dump_quote_value(buf, hint->relnames[i]);
-       }
-       appendStringInfoString(buf, ")\n");
-
-}
-
 static Hint *
 LeadingHintCreate(const char *hint_str, const char *keyword)
 {
@@ -656,27 +523,6 @@ LeadingHintDelete(LeadingHint *hint)
        pfree(hint);
 }
 
-static void
-LeadingHintDump(LeadingHint *hint, StringInfo buf)
-{
-       bool            is_first;
-       ListCell   *l;
-
-       appendStringInfo(buf, "%s(", HINT_LEADING);
-       is_first = true;
-       foreach(l, hint->relations)
-       {
-               if (is_first)
-                       is_first = false;
-               else
-                       appendStringInfoCharMacro(buf, ' ');
-
-               dump_quote_value(buf, (char *) lfirst(l));
-       }
-
-       appendStringInfoString(buf, ")\n");
-}
-
 static Hint *
 SetHintCreate(const char *hint_str, const char *keyword)
 {
@@ -710,16 +556,6 @@ SetHintDelete(SetHint *hint)
        pfree(hint);
 }
 
-static void
-SetHintDump(SetHint *hint, StringInfo buf)
-{
-       appendStringInfo(buf, "%s(", HINT_SET);
-       dump_quote_value(buf, hint->name);
-       appendStringInfoCharMacro(buf, ' ');
-       dump_quote_value(buf, hint->value);
-       appendStringInfo(buf, ")\n");
-}
-
 static PlanHint *
 PlanHintCreate(void)
 {
@@ -761,6 +597,100 @@ PlanHintDelete(PlanHint *hint)
                pfree(hint->all_hints);
 }
 
+/*
+ * dump functions
+ */
+
+static void
+dump_quote_value(StringInfo buf, const char *value)
+{
+       bool            need_quote = false;
+       const char *str;
+
+       for (str = value; *str != '\0'; str++)
+       {
+               if (isspace(*str) || *str == ')' || *str == '"')
+               {
+                       need_quote = true;
+                       appendStringInfoCharMacro(buf, '"');
+                       break;
+               }
+       }
+
+       for (str = value; *str != '\0'; str++)
+       {
+               if (*str == '"')
+                       appendStringInfoCharMacro(buf, '"');
+
+               appendStringInfoCharMacro(buf, *str);
+       }
+
+       if (need_quote)
+               appendStringInfoCharMacro(buf, '"');
+}
+
+static void
+ScanMethodHintDump(ScanMethodHint *hint, StringInfo buf)
+{
+       ListCell   *l;
+
+       appendStringInfo(buf, "%s(", hint->base.keyword);
+       dump_quote_value(buf, hint->relname);
+       foreach(l, hint->indexnames)
+       {
+               appendStringInfoCharMacro(buf, ' ');
+               dump_quote_value(buf, (char *) lfirst(l));
+       }
+       appendStringInfoString(buf, ")\n");
+}
+
+static void
+JoinMethodHintDump(JoinMethodHint *hint, StringInfo buf)
+{
+       int     i;
+
+       appendStringInfo(buf, "%s(", hint->base.keyword);
+       dump_quote_value(buf, hint->relnames[0]);
+       for (i = 1; i < hint->nrels; i++)
+       {
+               appendStringInfoCharMacro(buf, ' ');
+               dump_quote_value(buf, hint->relnames[i]);
+       }
+       appendStringInfoString(buf, ")\n");
+
+}
+
+static void
+LeadingHintDump(LeadingHint *hint, StringInfo buf)
+{
+       bool            is_first;
+       ListCell   *l;
+
+       appendStringInfo(buf, "%s(", HINT_LEADING);
+       is_first = true;
+       foreach(l, hint->relations)
+       {
+               if (is_first)
+                       is_first = false;
+               else
+                       appendStringInfoCharMacro(buf, ' ');
+
+               dump_quote_value(buf, (char *) lfirst(l));
+       }
+
+       appendStringInfoString(buf, ")\n");
+}
+
+static void
+SetHintDump(SetHint *hint, StringInfo buf)
+{
+       appendStringInfo(buf, "%s(", HINT_SET);
+       dump_quote_value(buf, hint->name);
+       appendStringInfoCharMacro(buf, ' ');
+       dump_quote_value(buf, hint->value);
+       appendStringInfo(buf, ")\n");
+}
+
 static void
 all_hint_dump(PlanHint *hint, StringInfo buf, const char *title,
                          HintStatus state)
@@ -801,6 +731,10 @@ PlanHintDump(PlanHint *hint)
        pfree(buf.data);
 }
 
+/*
+ * compare functions
+ */
+
 static int
 RelnameCmp(const void *a, const void *b)
 {
@@ -811,158 +745,62 @@ RelnameCmp(const void *a, const void *b)
 }
 
 static int
-ScanMethodHintCmp(const ScanMethodHint *a, const ScanMethodHint *b)
-{
-       return RelnameCmp(&a->relname, &b->relname);
-}
-
-static int
-JoinMethodHintCmp(const JoinMethodHint *a, const JoinMethodHint *b)
-{
-       int     i;
-
-       if (a->nrels != b->nrels)
-               return a->nrels - b->nrels;
-
-       for (i = 0; i < a->nrels; i++)
-       {
-               int     result;
-               if ((result = RelnameCmp(&a->relnames[i], &b->relnames[i])) != 0)
-                       return result;
-       }
-
-       return 0;
-}
-
-static int
-LeadingHintCmp(const LeadingHint *a, const LeadingHint *b)
-{
-       return 0;
-}
-
-static int
-SetHintCmp(const SetHint *a, const SetHint *b)
-{
-       return strcmp(a->name, b->name);
-}
-
-static int
-AllHintCmp(const void *a, const void *b, bool order)
-{
-       const Hint *hinta = *((const Hint **) a);
-       const Hint *hintb = *((const Hint **) b);
-       int                     result = 0;
-
-       if (hinta->type != hintb->type)
-               return hinta->type - hintb->type;
-
-       if ((result = hinta->cmp_func(hinta, hintb)) != 0 || !order)
-               return result;
-
-       /* ヒント句で指定した順を返す */
-       return hinta->hint_str - hintb->hint_str;
-}
-
-static int
-AllHintCmpIsOrder(const void *a, const void *b)
-{
-       return AllHintCmp(a, b, true);
-}
-
-#if PG_VERSION_NUM < 90200
-static int
-set_config_option_wrapper(const char *name, const char *value,
-                                                 GucContext context, GucSource source,
-                                                 GucAction action, bool changeVal, int elevel)
-{
-       int                             result = 0;
-       MemoryContext   ccxt = CurrentMemoryContext;
-
-       PG_TRY();
-       {
-               result = set_config_option(name, value, context, source,
-                                                                  action, changeVal);
-       }
-       PG_CATCH();
-       {
-               ErrorData          *errdata;
-               MemoryContext   ecxt;
-
-               if (elevel >= ERROR)
-                       PG_RE_THROW();
-
-               ecxt = MemoryContextSwitchTo(ccxt);
-               errdata = CopyErrorData();
-               ereport(elevel, (errcode(errdata->sqlerrcode),
-                               errmsg("%s", errdata->message),
-                               errdata->detail ? errdetail("%s", errdata->detail) : 0,
-                               errdata->hint ? errhint("%s", errdata->hint) : 0));
-               FreeErrorData(errdata);
-
-               MemoryContextSwitchTo(ecxt);
-       }
-       PG_END_TRY();
-
-       return result;
-}
-
-#define set_config_option(name, value, context, source, \
-                                                 action, changeVal, elevel) \
-       set_config_option_wrapper(name, value, context, source, \
-                                                         action, changeVal, elevel)
-#endif
+ScanMethodHintCmp(const ScanMethodHint *a, const ScanMethodHint *b)
+{
+       return RelnameCmp(&a->relname, &b->relname);
+}
 
 static int
-set_config_options(SetHint **options, int noptions, GucContext context)
+JoinMethodHintCmp(const JoinMethodHint *a, const JoinMethodHint *b)
 {
        int     i;
-       int     save_nestlevel;
 
-       save_nestlevel = NewGUCNestLevel();
+       if (a->nrels != b->nrels)
+               return a->nrels - b->nrels;
 
-       for (i = 0; i < noptions; i++)
+       for (i = 0; i < a->nrels; i++)
        {
-               SetHint    *hint = options[i];
-               int                     result;
-
-               if (!hint_state_enabled(hint))
-                       continue;
-
-               result = set_config_option(hint->name, hint->value, context,
-                                                                  PGC_S_SESSION, GUC_ACTION_SAVE, true,
-                                                                  pg_hint_plan_parse_messages);
-               if (result != 0)
-                       hint->base.state = HINT_STATE_USED;
-               else
-                       hint->base.state = HINT_STATE_ERROR;
+               int     result;
+               if ((result = RelnameCmp(&a->relnames[i], &b->relnames[i])) != 0)
+                       return result;
        }
 
-       return save_nestlevel;
+       return 0;
 }
 
-#define SET_CONFIG_OPTION(name, type_bits) \
-       set_config_option((name), \
-               (enforce_mask & (type_bits)) ? "true" : "false", \
-               context, PGC_S_SESSION, GUC_ACTION_SAVE, true, ERROR)
+static int
+LeadingHintCmp(const LeadingHint *a, const LeadingHint *b)
+{
+       return 0;
+}
 
-static void
-set_scan_config_options(unsigned char enforce_mask, GucContext context)
+static int
+SetHintCmp(const SetHint *a, const SetHint *b)
 {
-       SET_CONFIG_OPTION("enable_seqscan", ENABLE_SEQSCAN);
-       SET_CONFIG_OPTION("enable_indexscan", ENABLE_INDEXSCAN);
-       SET_CONFIG_OPTION("enable_bitmapscan", ENABLE_BITMAPSCAN);
-       SET_CONFIG_OPTION("enable_tidscan", ENABLE_TIDSCAN);
-#if PG_VERSION_NUM >= 90200
-       SET_CONFIG_OPTION("enable_indexonlyscan", ENABLE_INDEXONLYSCAN);
-#endif
+       return strcmp(a->name, b->name);
 }
 
-static void
-set_join_config_options(unsigned char enforce_mask, GucContext context)
+static int
+AllHintCmp(const void *a, const void *b, bool order)
 {
-       SET_CONFIG_OPTION("enable_nestloop", ENABLE_NESTLOOP);
-       SET_CONFIG_OPTION("enable_mergejoin", ENABLE_MERGEJOIN);
-       SET_CONFIG_OPTION("enable_hashjoin", ENABLE_HASHJOIN);
+       const Hint *hinta = *((const Hint **) a);
+       const Hint *hintb = *((const Hint **) b);
+       int                     result = 0;
+
+       if (hinta->type != hintb->type)
+               return hinta->type - hintb->type;
+
+       if ((result = hinta->cmp_func(hinta, hintb)) != 0 || !order)
+               return result;
+
+       /* ヒント句で指定した順を返す */
+       return hinta->hint_str - hintb->hint_str;
+}
+
+static int
+AllHintCmpIsOrder(const void *a, const void *b)
+{
+       return AllHintCmp(a, b, true);
 }
 
 /*
@@ -1433,6 +1271,188 @@ SetHintParse(SetHint *hint, PlanHint *plan, Query *parse, const char *str)
        return str;
 }
 
+/*
+ * set GUC parameter functions
+ */
+
+#if PG_VERSION_NUM < 90200
+static int
+set_config_option_wrapper(const char *name, const char *value,
+                                                 GucContext context, GucSource source,
+                                                 GucAction action, bool changeVal, int elevel)
+{
+       int                             result = 0;
+       MemoryContext   ccxt = CurrentMemoryContext;
+
+       PG_TRY();
+       {
+               result = set_config_option(name, value, context, source,
+                                                                  action, changeVal);
+       }
+       PG_CATCH();
+       {
+               ErrorData          *errdata;
+               MemoryContext   ecxt;
+
+               if (elevel >= ERROR)
+                       PG_RE_THROW();
+
+               ecxt = MemoryContextSwitchTo(ccxt);
+               errdata = CopyErrorData();
+               ereport(elevel, (errcode(errdata->sqlerrcode),
+                               errmsg("%s", errdata->message),
+                               errdata->detail ? errdetail("%s", errdata->detail) : 0,
+                               errdata->hint ? errhint("%s", errdata->hint) : 0));
+               FreeErrorData(errdata);
+
+               MemoryContextSwitchTo(ecxt);
+       }
+       PG_END_TRY();
+
+       return result;
+}
+
+#define set_config_option(name, value, context, source, \
+                                                 action, changeVal, elevel) \
+       set_config_option_wrapper(name, value, context, source, \
+                                                         action, changeVal, elevel)
+#endif
+
+static int
+set_config_options(SetHint **options, int noptions, GucContext context)
+{
+       int     i;
+       int     save_nestlevel;
+
+       save_nestlevel = NewGUCNestLevel();
+
+       for (i = 0; i < noptions; i++)
+       {
+               SetHint    *hint = options[i];
+               int                     result;
+
+               if (!hint_state_enabled(hint))
+                       continue;
+
+               result = set_config_option(hint->name, hint->value, context,
+                                                                  PGC_S_SESSION, GUC_ACTION_SAVE, true,
+                                                                  pg_hint_plan_parse_messages);
+               if (result != 0)
+                       hint->base.state = HINT_STATE_USED;
+               else
+                       hint->base.state = HINT_STATE_ERROR;
+       }
+
+       return save_nestlevel;
+}
+
+#define SET_CONFIG_OPTION(name, type_bits) \
+       set_config_option((name), \
+               (enforce_mask & (type_bits)) ? "true" : "false", \
+               context, PGC_S_SESSION, GUC_ACTION_SAVE, true, ERROR)
+
+static void
+set_scan_config_options(unsigned char enforce_mask, GucContext context)
+{
+       SET_CONFIG_OPTION("enable_seqscan", ENABLE_SEQSCAN);
+       SET_CONFIG_OPTION("enable_indexscan", ENABLE_INDEXSCAN);
+       SET_CONFIG_OPTION("enable_bitmapscan", ENABLE_BITMAPSCAN);
+       SET_CONFIG_OPTION("enable_tidscan", ENABLE_TIDSCAN);
+#if PG_VERSION_NUM >= 90200
+       SET_CONFIG_OPTION("enable_indexonlyscan", ENABLE_INDEXONLYSCAN);
+#endif
+}
+
+static void
+set_join_config_options(unsigned char enforce_mask, GucContext context)
+{
+       SET_CONFIG_OPTION("enable_nestloop", ENABLE_NESTLOOP);
+       SET_CONFIG_OPTION("enable_mergejoin", ENABLE_MERGEJOIN);
+       SET_CONFIG_OPTION("enable_hashjoin", ENABLE_HASHJOIN);
+}
+
+/*
+ * pg_hint_plan hook functions
+ */
+
+static void
+ProcessUtility_hook_error_callback(void *arg)
+{
+       stmt_name = NULL;
+}
+
+static void
+pg_hint_plan_ProcessUtility(Node *parsetree, const char *queryString,
+                                                       ParamListInfo params, bool isTopLevel,
+                                                       DestReceiver *dest, char *completionTag)
+{
+       Node                               *node;
+       ErrorContextCallback    errcontext;
+
+       if (!pg_hint_plan_enable)
+       {
+               if (prev_ProcessUtility)
+                       (*prev_ProcessUtility) (parsetree, queryString, params,
+                                                                       isTopLevel, dest, completionTag);
+               else
+                       standard_ProcessUtility(parsetree, queryString, params,
+                                                                       isTopLevel, dest, completionTag);
+
+               return;
+       }
+
+       node = parsetree;
+       if (IsA(node, ExplainStmt))
+       {
+               /*
+                * EXPLAIN対象のクエリのパースツリーを取得する
+                */
+               ExplainStmt        *stmt;
+               Query              *query;
+
+               stmt = (ExplainStmt *) node;
+
+               Assert(IsA(stmt->query, Query));
+               query = (Query *) stmt->query;
+
+               if (query->commandType == CMD_UTILITY && query->utilityStmt != NULL)
+                       node = query->utilityStmt;
+       }
+
+       /*
+        * EXECUTEコマンドならば、PREPARE時に指定されたクエリ文字列を取得し、ヒント
+        * 句の候補として設定する
+        */
+       if (IsA(node, ExecuteStmt))
+       {
+               ExecuteStmt        *stmt;
+
+               /* Set up callback to statement name reset. */
+               errcontext.callback = ProcessUtility_hook_error_callback;
+               errcontext.arg = NULL;
+               errcontext.previous = error_context_stack;
+               error_context_stack = &errcontext;
+
+               stmt = (ExecuteStmt *) node;
+               stmt_name = stmt->name;
+       }
+
+       if (prev_ProcessUtility)
+               (*prev_ProcessUtility) (parsetree, queryString, params,
+                                                               isTopLevel, dest, completionTag);
+       else
+               standard_ProcessUtility(parsetree, queryString, params,
+                                                               isTopLevel, dest, completionTag);
+
+       if (stmt_name)
+       {
+               stmt_name = NULL;
+
+               /* Remove error callback. */
+               error_context_stack = errcontext.previous;
+       }
+}
+
 static PlannedStmt *
 pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 {