pfree(buf.data);
}
+
+/* search hint. */
+static const char *
+search_hints(const char *client_query,
+ const char *client_application)
+{
+ const char *search_query =
+ "SELECT hints "
+ " FROM hint_plan.hints "
+ " WHERE norm_query_string = $1 "
+ " AND ( application_name = $2 "
+ " OR application_name = '' ) "
+ " ORDER BY application_name DESC";
+ static SPIPlanPtr plan = NULL;
+ int ret;
+ char *hints = NULL;
+ Oid argtypes[2] = { TEXTOID, TEXTOID };
+ Datum values[2];
+ bool nulls[2] = { false, false };
+ text *qry;
+ text *app;
+
+ ret = SPI_connect();
+ if (ret != SPI_OK_CONNECT)
+ elog(ERROR, "pg_hint_plan: SPI_connect => %d", ret);
+
+ if (plan == NULL)
+ {
+ SPIPlanPtr p;
+ p = SPI_prepare(search_query, 2, argtypes);
+ if (p == NULL)
+ elog(ERROR, "pg_hint_plan: SPI_prepare => %d", SPI_result);
+ plan = SPI_saveplan(p);
+ SPI_freeplan(p);
+ }
+
+ qry = cstring_to_text(client_query);
+ app = cstring_to_text(client_application);
+ values[0] = PointerGetDatum(qry);
+ values[1] = PointerGetDatum(app);
+
+ pg_hint_plan_enable_hint = false;
+ ret = SPI_execute_plan(plan, values, nulls, true, 1);
+ pg_hint_plan_enable_hint = true;
+ if (ret != SPI_OK_SELECT)
+ elog(ERROR, "pg_hint_plan: SPI_execute_plan => %d", ret);
+
+ if (SPI_processed > 0)
+ {
+ hints = pstrdup(SPI_getvalue(SPI_tuptable->vals[0],
+ SPI_tuptable->tupdesc, 1));
+ }
+ SPI_finish();
+
+ return hints;
+}
+
/*
- * Do basic parsing of the query head comment.
+ * Get client-supplied query string.
*/
- static HintState *
- parse_head_comment(Query *parse)
+ static const char *
+ get_query_string(void)
{
const char *p;
- const char *hint_head;
- char *head;
- char *tail;
- int len;
- int i;
- HintState *hstate;
- /* get client-supplied query string. */
if (stmt_name)
{
PreparedStatement *entry;
* try to change plan with current_hint if any, so set it to NULL.
*/
if (!pg_hint_plan_enable_hint)
- {
- current_hint = NULL;
-
- if (prev_planner)
- return (*prev_planner) (parse, cursorOptions, boundParams);
- else
- return standard_planner(parse, cursorOptions, boundParams);
- }
+ goto standard_planner_proc;
- /* Create hint struct from parse tree. */
- hstate = parse_head_comment(parse);
+ /*
+ *search hint.
+ * TODO: replace "app1" with current application_name setting of the
+ * session.
+ * XXX: use something instead of debug_query_string?
+ */
+ hints = search_hints(debug_query_string, application_name);
+ elog(LOG,
+ "pg_hint_plan: search_hints [%s][%s]=>[%s]",
+ debug_query_string, application_name,
+ hints ? hints : "(none)");
+
+ /* Create hint struct from client-supplied query string. */
+ query = get_query_string();
+ hints = get_hints_from_comment(query);
+ hstate = create_hintstate(parse, hints);
/*
* Use standard planner if the statement has not valid hint. Other hook