+
+ hint->relname = linitial(name_list);
+
+ /* The second parameter is number of workers */
+ hint->nworkers_str = list_nth(name_list, 1);
+ nworkers = strtod(hint->nworkers_str, &end_ptr);
+ if (*end_ptr || nworkers < 0 || nworkers > max_worker_processes)
+ {
+ if (*end_ptr)
+ hint_ereport(hint->nworkers_str,
+ ("number of workers must be a number: %s",
+ hint->base.keyword));
+ else if (nworkers < 0)
+ hint_ereport(hint->nworkers_str,
+ ("number of workers must be greater than zero: %s",
+ hint->base.keyword));
+ else if (nworkers > max_worker_processes)
+ hint_ereport(hint->nworkers_str,
+ ("number of workers = %d is larger than max_worker_processes(%d): %s",
+ nworkers, max_worker_processes, hint->base.keyword));
+
+ hint->base.state = HINT_STATE_ERROR;
+ }
+
+ hint->nworkers = nworkers;
+
+ /* optional third parameter is specified */
+ if (length == 3)
+ {
+ const char *modeparam = (const char *)list_nth(name_list, 2);
+ if (pg_strcasecmp(modeparam, "hard") == 0)
+ force_parallel = true;
+ else if (pg_strcasecmp(modeparam, "soft") != 0)
+ {
+ hint_ereport(modeparam,
+ ("enforcement must be soft or hard: %s",
+ hint->base.keyword));
+ hint->base.state = HINT_STATE_ERROR;
+ }
+ }
+
+ hint->force_parallel = force_parallel;
+
+ if (hint->base.state != HINT_STATE_ERROR &&
+ nworkers > max_hint_nworkers)
+ max_hint_nworkers = nworkers;
+
+ return str;
+}
+
+/*
+ * set GUC parameter functions
+ */
+
+static int
+get_current_scan_mask()
+{
+ int mask = 0;
+
+ if (enable_seqscan)
+ mask |= ENABLE_SEQSCAN;
+ if (enable_indexscan)
+ mask |= ENABLE_INDEXSCAN;
+ if (enable_bitmapscan)
+ mask |= ENABLE_BITMAPSCAN;
+ if (enable_tidscan)
+ mask |= ENABLE_TIDSCAN;
+ if (enable_indexonlyscan)
+ mask |= ENABLE_INDEXONLYSCAN;
+
+ return mask;
+}
+
+static int
+get_current_join_mask()
+{
+ int mask = 0;
+
+ if (enable_nestloop)
+ mask |= ENABLE_NESTLOOP;
+ if (enable_mergejoin)
+ mask |= ENABLE_MERGEJOIN;
+ if (enable_hashjoin)
+ mask |= ENABLE_HASHJOIN;
+ if (enable_memoize)
+ mask |= ENABLE_MEMOIZE;
+
+ return mask;
+}
+
+/*
+ * Sets GUC prameters without throwing exception. Reutrns false if something
+ * wrong.
+ */
+static int
+set_config_option_noerror(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, 0, false);
+ }
+ PG_CATCH();
+ {
+ ErrorData *errdata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(ccxt);
+ errdata = CopyErrorData();
+ FlushErrorState();
+
+ ereport(elevel,
+ (errcode(errdata->sqlerrcode),
+ errmsg("%s", errdata->message),
+ errdata->detail ? errdetail("%s", errdata->detail) : 0,
+ errdata->hint ? errhint("%s", errdata->hint) : 0));
+ msgqno = qno;
+ FreeErrorData(errdata);
+ }
+ PG_END_TRY();