/* * DefineAggregate * * "oldstyle" signals the old (pre-8.2) style where the aggregate input type * is specified by a BASETYPE element in the parameters. Otherwise, * "args" defines the input type(s). */ Oid DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) { char *aggName; Oid aggNamespace; AclResult aclresult; List *transfuncName = NIL; List *finalfuncName = NIL; List *sortoperatorName = NIL; TypeName *baseType = NULL; TypeName *transType = NULL; char *initval = NULL; Oid *aggArgTypes; int numArgs; Oid transTypeId; char transTypeType; ListCell *pl; /* Convert list of names to a name and namespace */ aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName); /* Check we have creation rights in target namespace */ aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(aggNamespace)); foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); /* * sfunc1, stype1, and initcond1 are accepted as obsolete spellings * for sfunc, stype, initcond. */ if (pg_strcasecmp(defel->defname, "sfunc") == 0) transfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "sfunc1") == 0) transfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "finalfunc") == 0) finalfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "sortop") == 0) sortoperatorName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "basetype") == 0) baseType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "stype") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "stype1") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "initcond") == 0) initval = defGetString(defel); else if (pg_strcasecmp(defel->defname, "initcond1") == 0) initval = defGetString(defel); else ereport(WARNING, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("aggregate attribute \"%s\" not recognized", defel->defname))); }
/* * cstore_fdw_validator validates options given to one of the following commands: * foreign data wrapper, server, user mapping, or foreign table. This function * errors out if the given option name or its value is considered invalid. */ Datum cstore_fdw_validator(PG_FUNCTION_ARGS) { Datum optionArray = PG_GETARG_DATUM(0); Oid optionContextId = PG_GETARG_OID(1); List *optionList = untransformRelOptions(optionArray); ListCell *optionCell = NULL; char *filename = NULL; char *compressionTypeString = NULL; char *stripeRowCountString = NULL; char *blockRowCountString = NULL; foreach(optionCell, optionList) { DefElem *optionDef = (DefElem *) lfirst(optionCell); char *optionName = optionDef->defname; bool optionValid = false; int32 optionIndex = 0; for (optionIndex = 0; optionIndex < ValidOptionCount; optionIndex++) { const CStoreValidOption *validOption = &(ValidOptionArray[optionIndex]); if ((optionContextId == validOption->optionContextId) && (strncmp(optionName, validOption->optionName, NAMEDATALEN) == 0)) { optionValid = true; break; } } /* if invalid option, display an informative error message */ if (!optionValid) { StringInfo optionNamesString = OptionNamesString(optionContextId); ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", optionName), errhint("Valid options in this context are: %s", optionNamesString->data))); } if (strncmp(optionName, OPTION_NAME_FILENAME, NAMEDATALEN) == 0) { filename = defGetString(optionDef); } else if (strncmp(optionName, OPTION_NAME_COMPRESSION_TYPE, NAMEDATALEN) == 0) { compressionTypeString = defGetString(optionDef); } else if (strncmp(optionName, OPTION_NAME_STRIPE_ROW_COUNT, NAMEDATALEN) == 0) { stripeRowCountString = defGetString(optionDef); } else if (strncmp(optionName, OPTION_NAME_BLOCK_ROW_COUNT, NAMEDATALEN) == 0) { blockRowCountString = defGetString(optionDef); } }
Datum dispell_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictISpell *d; bool affloaded = false, dictloaded = false, stoploaded = false; ListCell *l; d = (DictISpell *) palloc0(sizeof(DictISpell)); NIStartBuild(&(d->obj)); foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "DictFile") == 0) { if (dictloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple DictFile parameters"))); NIImportDictionary(&(d->obj), get_tsearch_config_filename(defGetString(defel), "dict")); dictloaded = true; } else if (pg_strcasecmp(defel->defname, "AffFile") == 0) { if (affloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple AffFile parameters"))); NIImportAffixes(&(d->obj), get_tsearch_config_filename(defGetString(defel), "affix")); affloaded = true; } else if (pg_strcasecmp(defel->defname, "StopWords") == 0) { if (stoploaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); readstoplist(defGetString(defel), &(d->stoplist), lowerstr); stoploaded = true; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized Ispell parameter: \"%s\"", defel->defname))); } }
/* * This initializes a (shared) dictionary for a backend. The function receives * a list of options specified in the CREATE TEXT SEARCH DICTIONARY with ispell * template (http://www.postgresql.org/docs/9.3/static/sql-createtsdictionary.html). * * There are three allowed options: DictFile, AffFile, StopWords. The values * should match to filenames in `pg_config --sharedir` directory, ending with * .dict, .affix and .stop. * * The StopWords parameter is optional, the two other are required. * * If any of the filenames are incorrect, the call to init_shared_dict will fail. */ Datum dispell_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); char *dictFile = NULL, *affFile = NULL, *stopFile = NULL; bool affloaded = false, dictloaded = false, stoploaded = false; ListCell *l; /* this is the result passed to dispell_lexize */ DictInfo * info = (DictInfo *)palloc0(sizeof(DictInfo)); foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "DictFile") == 0) { if (dictloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple DictFile parameters"))); dictFile = defGetString(defel); dictloaded = true; } else if (pg_strcasecmp(defel->defname, "AffFile") == 0) { if (affloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple AffFile parameters"))); affFile = defGetString(defel); affloaded = true; } else if (pg_strcasecmp(defel->defname, "StopWords") == 0) { if (stoploaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); stopFile = defGetString(defel); stoploaded = true; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized Ispell parameter: \"%s\"", defel->defname))); } }
Datum dregex_init(PG_FUNCTION_ARGS) { parser_str *parser = parser_create(); List *dictoptions = (List *) PG_GETARG_POINTER(0); ListCell *l; foreach(l, dictoptions){ DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "RULES") == 0) { parser_read_rules(parser, defGetString(defel)); } else { elog(ERROR,"Unknown option: %s => %s", defel->defname, defGetString(defel)); } }
Datum dsynonym_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictSyn *d; ListCell *l; char *filename = NULL; bool case_sensitive = false; tsearch_readline_state trst; char *starti, *starto, *end = NULL; int cur = 0; char *line = NULL; uint16 flags = 0; foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp("Synonyms", defel->defname) == 0) filename = defGetString(defel); else if (pg_strcasecmp("CaseSensitive", defel->defname) == 0) case_sensitive = defGetBoolean(defel); else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized synonym parameter: \"%s\"", defel->defname))); }
Datum multicorn_validator(PG_FUNCTION_ARGS) { List *options_list = untransformRelOptions(PG_GETARG_DATUM(0)); Oid catalog = PG_GETARG_OID(1); char *className = NULL; ListCell *cell; PyObject *p_class; foreach(cell, options_list) { DefElem *def = (DefElem *) lfirst(cell); if (strcmp(def->defname, "wrapper") == 0) { /* Only at server creation can we set the wrapper, */ /* for security issues. */ if (catalog == ForeignTableRelationId) { ereport(ERROR, (errmsg("%s", "Cannot set the wrapper class on the table"), errhint("%s", "Set it on the server"))); } else { className = (char *) defGetString(def); } } }
/* * AppendOptionListToString converts the option list to its textual format, and * appends this text to the given string buffer. */ void AppendOptionListToString(StringInfo stringBuffer, List *optionList) { if (optionList != NIL) { ListCell *optionCell = NULL; bool firstOptionPrinted = false; appendStringInfo(stringBuffer, " OPTIONS ("); foreach(optionCell, optionList) { DefElem *option = (DefElem *) lfirst(optionCell); char *optionName = option->defname; char *optionValue = defGetString(option); if (firstOptionPrinted) { appendStringInfo(stringBuffer, ", "); } firstOptionPrinted = true; appendStringInfo(stringBuffer, "%s ", quote_identifier(optionName)); appendStringInfo(stringBuffer, "%s", quote_literal_cstr(optionValue)); }
Datum dxsyn_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictSyn *d; ListCell *l; d = (DictSyn *) palloc0(sizeof(DictSyn)); d->len = 0; d->syn = NULL; d->keeporig = true; foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "KEEPORIG") == 0) { d->keeporig = defGetBoolean(defel); } else if (pg_strcasecmp(defel->defname, "RULES") == 0) { read_dictionary(d, defGetString(defel)); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized xsyn parameter: \"%s\"", defel->defname))); } }
Datum unaccent_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); SuffixChar *rootSuffixTree = NULL; bool fileloaded = false; ListCell *l; foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp("Rules", defel->defname) == 0) { if (fileloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Rules parameters"))); rootSuffixTree = initSuffixTree(defGetString(defel)); fileloaded = true; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized Unaccent parameter: \"%s\"", defel->defname))); } }
Datum dintdict_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictInt *d; ListCell *l; d = (DictInt *) palloc0(sizeof(DictInt)); d->maxlen = 6; d->rejectlong = false; foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "MAXLEN") == 0) { d->maxlen = atoi(defGetString(defel)); } else if (pg_strcasecmp(defel->defname, "REJECTLONG") == 0) { d->rejectlong = defGetBoolean(defel); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized intdict parameter: \"%s\"", defel->defname))); } }
static void getTableOptions(Oid foreigntableid,struct ktTableOptions *table_options) { ForeignTable *table; ForeignServer *server; UserMapping *mapping; List *options; ListCell *lc; #ifdef DEBUG elog(NOTICE, "getTableOptions"); #endif /* * Extract options from FDW objects. We only need to worry about server * options for Redis * */ table = GetForeignTable(foreigntableid); server = GetForeignServer(table->serverid); mapping = GetUserMapping(GetUserId(), table->serverid); table_options->userId = mapping->userid; table_options->serverId = server->serverid; options = NIL; options = list_concat(options, table->options); options = list_concat(options, server->options); options = list_concat(options, mapping->options); // table_options->table_type = PG_REDIS_SCALAR_TABLE; /* Loop through the options, and get the server/port */ foreach(lc, options) { DefElem *def = (DefElem *) lfirst(lc); if (strcmp(def->defname, "host") == 0) table_options->host = defGetString(def); if (strcmp(def->defname, "port") == 0) table_options->port = atoi(defGetString(def)); if (strcmp(def->defname, "timeout") == 0) table_options->timeout = atoi(defGetString(def)); }
Datum thesaurus_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictThesaurus *d; char *subdictname = NULL; bool fileloaded = false; ListCell *l; d = (DictThesaurus *) palloc0(sizeof(DictThesaurus)); foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp("DictFile", defel->defname) == 0) { if (fileloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple DictFile parameters"))); thesaurusRead(defGetString(defel), d); fileloaded = true; } else if (pg_strcasecmp("Dictionary", defel->defname) == 0) { if (subdictname) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Dictionary parameters"))); subdictname = pstrdup(defGetString(defel)); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized Thesaurus parameter: \"%s\"", defel->defname))); } }
static void getTableOptions(Oid foreigntableid, struct wdbTableOptions *table_options) { ForeignTable* table; ForeignServer* server; UserMapping* mapping; List* options = NIL; ListCell* lc = NULL; #ifdef DEBUG elog(NOTICE, "getTableOptions"); #endif /* * Extract options from FDW objects. * */ table = GetForeignTable(foreigntableid); server = GetForeignServer(table->serverid); mapping = GetUserMapping(GetUserId(), table->serverid); table_options->userId = mapping->userid; table_options->serverId = server->serverid; options = NIL; options = list_concat(options, table->options); options = list_concat(options, server->options); options = list_concat(options, mapping->options); /* Loop through the options, and get the server/port */ foreach(lc, options) { DefElem *def = (DefElem *) lfirst(lc); if (strcmp(def->defname, "address") == 0) table_options->address = defGetString(def); if (strcmp(def->defname, "size") == 0) table_options->size = atoi(defGetString(def)); }
Datum dsnowball_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictSnowball *d; bool stoploaded = false; ListCell *l; d = (DictSnowball *) palloc0(sizeof(DictSnowball)); foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp("StopWords", defel->defname) == 0) { if (stoploaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); readstoplist(defGetString(defel), &d->stoplist, lowerstr); stoploaded = true; } else if (pg_strcasecmp("Language", defel->defname) == 0) { if (d->stem) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Language parameters"))); locate_stem_module(d, defGetString(defel)); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized Snowball parameter: \"%s\"", defel->defname))); } }
/* * Extract a boolean value from a DefElem. */ bool defGetBoolean(DefElem *def) { /* * If no parameter given, assume "true" is meant. */ if (def->arg == NULL) return true; /* * Allow 0, 1, "true", "false", "on", "off" */ switch (nodeTag(def->arg)) { case T_Integer: switch (intVal(def->arg)) { case 0: return false; case 1: return true; default: /* otherwise, error out below */ break; } break; default: { char *sval = defGetString(def); /* * The set of strings accepted here should match up with the * grammar's opt_boolean production. */ if (pg_strcasecmp(sval, "true") == 0) return true; if (pg_strcasecmp(sval, "false") == 0) return false; if (pg_strcasecmp(sval, "on") == 0) return true; if (pg_strcasecmp(sval, "off") == 0) return false; } break; } ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s requires a Boolean value", def->defname))); return false; /* keep compiler quiet */ }
Datum dxsyn_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictSyn *d; ListCell *l; char *filename = NULL; d = (DictSyn *) palloc0(sizeof(DictSyn)); d->len = 0; d->syn = NULL; d->matchorig = true; d->keeporig = true; d->matchsynonyms = false; d->keepsynonyms = true; foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp(defel->defname, "MATCHORIG") == 0) { d->matchorig = defGetBoolean(defel); } else if (pg_strcasecmp(defel->defname, "KEEPORIG") == 0) { d->keeporig = defGetBoolean(defel); } else if (pg_strcasecmp(defel->defname, "MATCHSYNONYMS") == 0) { d->matchsynonyms = defGetBoolean(defel); } else if (pg_strcasecmp(defel->defname, "KEEPSYNONYMS") == 0) { d->keepsynonyms = defGetBoolean(defel); } else if (pg_strcasecmp(defel->defname, "RULES") == 0) { /* we can't read the rules before parsing all options! */ filename = defGetString(defel); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized xsyn parameter: \"%s\"", defel->defname))); } }
/* * mongo_fdw_validator validates options given to one of the following commands: * foreign data wrapper, server, user mapping, or foreign table. This function * errors out if the given option name or its value is considered invalid. */ Datum mongo_fdw_validator(PG_FUNCTION_ARGS) { Datum optionArray = PG_GETARG_DATUM(0); Oid optionContextId = PG_GETARG_OID(1); List *optionList = untransformRelOptions(optionArray); ListCell *optionCell = NULL; foreach(optionCell, optionList) { DefElem *optionDef = (DefElem *) lfirst(optionCell); char *optionName = optionDef->defname; bool optionValid = false; int32 optionIndex = 0; for (optionIndex = 0; optionIndex < ValidOptionCount; optionIndex++) { const MongoValidOption *validOption = &(ValidOptionArray[optionIndex]); if ((optionContextId == validOption->optionContextId) && (strncmp(optionName, validOption->optionName, NAMEDATALEN) == 0)) { optionValid = true; break; } } /* if invalid option, display an informative error message */ if (!optionValid) { StringInfo optionNamesString = OptionNamesString(optionContextId); ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", optionName), errhint("Valid options in this context are: %s", optionNamesString->data))); } /* if port option is given, error out if its value isn't an integer */ if (strncmp(optionName, OPTION_NAME_PORT, NAMEDATALEN) == 0) { char *optionValue = defGetString(optionDef); int32 portNumber = pg_atoi(optionValue, sizeof(int32), 0); (void) portNumber; } }
Datum dsimple_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); DictSimple *d = (DictSimple *) palloc0(sizeof(DictSimple)); bool stoploaded = false, acceptloaded = false; ListCell *l; d->accept = true; /* default */ foreach(l, dictoptions) { DefElem *defel = (DefElem *) lfirst(l); if (pg_strcasecmp("StopWords", defel->defname) == 0) { if (stoploaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); readstoplist(defGetString(defel), &d->stoplist, lowerstr); stoploaded = true; } else if (pg_strcasecmp("Accept", defel->defname) == 0) { if (acceptloaded) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Accept parameters"))); d->accept = defGetBoolean(defel); acceptloaded = true; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized simple dictionary parameter: \"%s\"", defel->defname))); } }
/* * Extract a type length indicator (either absolute bytes, or * -1 for "variable") from a DefElem. */ int defGetTypeLength(DefElem *def) { if (def->arg == NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s requires a parameter", def->defname))); switch (nodeTag(def->arg)) { case T_Integer: return intVal(def->arg); case T_Float: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s requires an integer value", def->defname))); break; case T_String: if (pg_strcasecmp(strVal(def->arg), "variable") == 0) return -1; /* variable length */ break; case T_TypeName: /* cope if grammar chooses to believe "variable" is a typename */ if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg), "variable") == 0) return -1; /* variable length */ break; case T_List: /* must be an operator name */ break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg)); } ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid argument for %s: \"%s\"", def->defname, defGetString(def)))); return 0; /* keep compiler quiet */ }
static javaFdwExecutionState* javaGetOptions(Oid foreigntableid) { ForeignTable *f_table; ForeignServer *f_server; UserMapping *f_mapping; List *options; ListCell *cell; jobject obj, res, serverClass; jmethodID serverConstructor; jclass cl; javaFdwExecutionState *state; char *classname = NULL; options = NIL; f_table = GetForeignTable(foreigntableid); options = list_concat(options, f_table->options); f_server = GetForeignServer(f_table->serverid); options = list_concat(options, f_server->options); PG_TRY(); { f_mapping = GetUserMapping(GetUserId(), f_table->serverid); options = list_concat(options, f_mapping->options); } PG_CATCH(); { FlushErrorState(); /* DO NOTHING HERE */ } PG_END_TRY(); foreach(cell, options) { DefElem *def = (DefElem *) lfirst(cell); if (strcmp(def->defname, "class") == 0) { classname = (char *) defGetString(def); } }
static const char * sonar_get_option(const char *optname, Oid tbl) { ForeignTable *foreignTable = NULL; List *optionList = NIL; ListCell *optionCell = NULL; const char *val = NULL; foreignTable = GetForeignTable(tbl); optionList = list_concat(optionList, foreignTable->options); foreach(optionCell, optionList) { DefElem *optionDef = (DefElem *) lfirst(optionCell); char *optionDefName = optionDef->defname; if (strncmp(optionDefName, optname, NAMEDATALEN) == 0) { val = defGetString(optionDef); break; } }
/* * Convert a DefElem list to the text array format that is used in * pg_foreign_data_wrapper, pg_foreign_server, and pg_user_mapping. * Returns the array in the form of a Datum, or PointerGetDatum(NULL) * if the list is empty. * * Note: The array is usually stored to database without further * processing, hence any validation should be done before this * conversion. */ static Datum optionListToArray(List *options) { ArrayBuildState *astate = NULL; ListCell *cell; foreach(cell, options) { DefElem *def = lfirst(cell); const char *value; Size len; text *t; value = defGetString(def); len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value); t = palloc(len + 1); SET_VARSIZE(t, len); sprintf(VARDATA(t), "%s=%s", def->defname, value); astate = accumArrayResult(astate, PointerGetDatum(t), false, TEXTOID, CurrentMemoryContext); }
/* * Validate the generic options given to a FOREIGN DATA WRAPPER, SERVER, * USER MAPPING or FOREIGN TABLE that uses file_fdw. * * Raise an ERROR if the option or its value is considered invalid. */ Datum file_fdw_validator(PG_FUNCTION_ARGS) { List *options_list = untransformRelOptions(PG_GETARG_DATUM(0)); Oid catalog = PG_GETARG_OID(1); char *filename = NULL; DefElem *force_not_null = NULL; List *other_options = NIL; ListCell *cell; /* * Only superusers are allowed to set options of a file_fdw foreign table. * This is because the filename is one of those options, and we don't want * non-superusers to be able to determine which file gets read. * * Putting this sort of permissions check in a validator is a bit of a * crock, but there doesn't seem to be any other place that can enforce * the check more cleanly. * * Note that the valid_options[] array disallows setting filename at any * options level other than foreign table --- otherwise there'd still be a * security hole. */ if (catalog == ForeignTableRelationId && !superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("only superuser can change options of a file_fdw foreign table"))); /* * Check that only options supported by file_fdw, and allowed for the * current object type, are given. */ foreach(cell, options_list) { DefElem *def = (DefElem *) lfirst(cell); if (!is_valid_option(def->defname, catalog)) { struct FileFdwOption *opt; StringInfoData buf; /* * Unknown option specified, complain about it. Provide a hint * with list of valid options for the object. */ initStringInfo(&buf); for (opt = valid_options; opt->optname; opt++) { if (catalog == opt->optcontext) appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "", opt->optname); } ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", def->defname), errhint("Valid options in this context are: %s", buf.data))); } /* * Separate out filename and force_not_null, since ProcessCopyOptions * won't accept them. (force_not_null only comes in a boolean * per-column flavor here.) */ if (strcmp(def->defname, "filename") == 0) { if (filename) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); filename = defGetString(def); } else if (strcmp(def->defname, "force_not_null") == 0) { if (force_not_null) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); force_not_null = def; /* Don't care what the value is, as long as it's a legal boolean */ (void) defGetBoolean(def); } else other_options = lappend(other_options, def); }
/* * DefineAggregate * * "oldstyle" signals the old (pre-8.2) style where the aggregate input type * is specified by a BASETYPE element in the parameters. Otherwise, * "args" is a pair, whose first element is a list of FunctionParameter structs * defining the agg's arguments (both direct and aggregated), and whose second * element is an Integer node with the number of direct args, or -1 if this * isn't an ordered-set aggregate. * "parameters" is a list of DefElem representing the agg's definition clauses. */ ObjectAddress DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, const char *queryString) { char *aggName; Oid aggNamespace; AclResult aclresult; char aggKind = AGGKIND_NORMAL; List *transfuncName = NIL; List *finalfuncName = NIL; List *combinefuncName = NIL; List *serialfuncName = NIL; List *deserialfuncName = NIL; List *mtransfuncName = NIL; List *minvtransfuncName = NIL; List *mfinalfuncName = NIL; bool finalfuncExtraArgs = false; bool mfinalfuncExtraArgs = false; List *sortoperatorName = NIL; TypeName *baseType = NULL; TypeName *transType = NULL; TypeName *serialType = NULL; TypeName *mtransType = NULL; int32 transSpace = 0; int32 mtransSpace = 0; char *initval = NULL; char *minitval = NULL; char *parallel = NULL; int numArgs; int numDirectArgs = 0; oidvector *parameterTypes; ArrayType *allParameterTypes; ArrayType *parameterModes; ArrayType *parameterNames; List *parameterDefaults; Oid variadicArgType; Oid transTypeId; Oid serialTypeId = InvalidOid; Oid mtransTypeId = InvalidOid; char transTypeType; char mtransTypeType = 0; char proparallel = PROPARALLEL_UNSAFE; ListCell *pl; /* Convert list of names to a name and namespace */ aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName); /* Check we have creation rights in target namespace */ aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(aggNamespace)); /* Deconstruct the output of the aggr_args grammar production */ if (!oldstyle) { Assert(list_length(args) == 2); numDirectArgs = intVal(lsecond(args)); if (numDirectArgs >= 0) aggKind = AGGKIND_ORDERED_SET; else numDirectArgs = 0; args = (List *) linitial(args); } /* Examine aggregate's definition clauses */ foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); /* * sfunc1, stype1, and initcond1 are accepted as obsolete spellings * for sfunc, stype, initcond. */ if (pg_strcasecmp(defel->defname, "sfunc") == 0) transfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "sfunc1") == 0) transfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "finalfunc") == 0) finalfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "combinefunc") == 0) combinefuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "serialfunc") == 0) serialfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "deserialfunc") == 0) deserialfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "msfunc") == 0) mtransfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "minvfunc") == 0) minvtransfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "mfinalfunc") == 0) mfinalfuncName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "finalfunc_extra") == 0) finalfuncExtraArgs = defGetBoolean(defel); else if (pg_strcasecmp(defel->defname, "mfinalfunc_extra") == 0) mfinalfuncExtraArgs = defGetBoolean(defel); else if (pg_strcasecmp(defel->defname, "sortop") == 0) sortoperatorName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "basetype") == 0) baseType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "hypothetical") == 0) { if (defGetBoolean(defel)) { if (aggKind == AGGKIND_NORMAL) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("only ordered-set aggregates can be hypothetical"))); aggKind = AGGKIND_HYPOTHETICAL; } } else if (pg_strcasecmp(defel->defname, "stype") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "serialtype") == 0) serialType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "stype1") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "sspace") == 0) transSpace = defGetInt32(defel); else if (pg_strcasecmp(defel->defname, "mstype") == 0) mtransType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "msspace") == 0) mtransSpace = defGetInt32(defel); else if (pg_strcasecmp(defel->defname, "initcond") == 0) initval = defGetString(defel); else if (pg_strcasecmp(defel->defname, "initcond1") == 0) initval = defGetString(defel); else if (pg_strcasecmp(defel->defname, "minitcond") == 0) minitval = defGetString(defel); else if (pg_strcasecmp(defel->defname, "parallel") == 0) parallel = defGetString(defel); else ereport(WARNING, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("aggregate attribute \"%s\" not recognized", defel->defname))); }
/* * Common option parsing function for CREATE and ALTER SUBSCRIPTION commands. * * Since not all options can be specified in both commands, this function * will report an error on options if the target output pointer is NULL to * accomodate that. */ static void parse_subscription_options(List *options, bool *connect, bool *enabled_given, bool *enabled, bool *create_slot, char **slot_name, bool *copy_data) { ListCell *lc; bool connect_given = false; bool create_slot_given = false; bool copy_data_given = false; if (connect) *connect = true; if (enabled) { *enabled_given = false; *enabled = true; } if (create_slot) *create_slot = true; if (slot_name) *slot_name = NULL; if (copy_data) *copy_data = true; /* Parse options */ foreach (lc, options) { DefElem *defel = (DefElem *) lfirst(lc); if (strcmp(defel->defname, "noconnect") == 0 && connect) { if (connect_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); connect_given = true; *connect = !defGetBoolean(defel); } else if (strcmp(defel->defname, "enabled") == 0 && enabled) { if (*enabled_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); *enabled_given = true; *enabled = defGetBoolean(defel); } else if (strcmp(defel->defname, "disabled") == 0 && enabled) { if (*enabled_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); *enabled_given = true; *enabled = !defGetBoolean(defel); } else if (strcmp(defel->defname, "create slot") == 0 && create_slot) { if (create_slot_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); create_slot_given = true; *create_slot = defGetBoolean(defel); } else if (strcmp(defel->defname, "nocreate slot") == 0 && create_slot) { if (create_slot_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); create_slot_given = true; *create_slot = !defGetBoolean(defel); } else if (strcmp(defel->defname, "slot name") == 0 && slot_name) { if (*slot_name) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); *slot_name = defGetString(defel); } else if (strcmp(defel->defname, "copy data") == 0 && copy_data) { if (copy_data_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); copy_data_given = true; *copy_data = defGetBoolean(defel); } else if (strcmp(defel->defname, "nocopy data") == 0 && copy_data) { if (copy_data_given) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options"))); copy_data_given = true; *copy_data = !defGetBoolean(defel); } else elog(ERROR, "unrecognized option: %s", defel->defname); }
/* MPP-6923: */ static List * AlterResqueueCapabilityEntry( List *stmtOptIdList, Oid queueid, ListCell *initcell, bool bCreate) { ListCell *lc; List *elems = NIL; List *dropelems = NIL; List *dupcheck = NIL; HeapTuple tuple; cqContext *pcqCtx; cqContext cqc; Relation rel = NULL; bool bWithout = false; TupleDesc tupdesc = NULL; #ifdef USE_ASSERT_CHECKING { DefElem *defel = (DefElem *) lfirst(initcell); Assert(0 == strcmp(defel->defname, "withliststart")); } #endif initcell = lnext(initcell); /* walk the original list and build a list of valid entries */ for_each_cell(lc, initcell) { DefElem *defel = (DefElem *) lfirst(lc); Oid resTypeOid = InvalidOid; int resTypeInt = 0; List *pentry = NIL; Value *pKeyVal = NULL; Value *pStrVal = NULL; if (!bWithout && (strcmp(defel->defname, "withoutliststart") == 0)) { bWithout = true; rel = heap_open(ResourceTypeRelationId, RowExclusiveLock); tupdesc = RelationGetDescr(rel); goto L_loop_cont; } /* ignore the basic threshold entries -- should already be processed */ if (strcmp(defel->defname, "active_statements") == 0) goto L_loop_cont; if (strcmp(defel->defname, "max_cost") == 0) goto L_loop_cont; if (strcmp(defel->defname, "cost_overcommit") == 0) goto L_loop_cont; if (strcmp(defel->defname, "min_cost") == 0) goto L_loop_cont; if (!GetResourceTypeByName(defel->defname, &resTypeInt, &resTypeOid)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("option \"%s\" is not a valid resource type", defel->defname))); pKeyVal = makeString(defel->defname); /* WITHOUT clause value determined in pg_resourcetype */ if (!bWithout) pStrVal = makeString(defGetString(defel)); else { pStrVal = NULL; /* if NULL, delete entry from * pg_resqueuecapability */ pcqCtx = caql_beginscan( caql_addrel(cqclr(&cqc), rel), cql("SELECT * FROM pg_resourcetype" " WHERE restypid = :1 FOR UPDATE", Int16GetDatum(resTypeInt))); while (HeapTupleIsValid(tuple = caql_getnext(pcqCtx))) { text *shutoff_text = NULL; char *shutoff_str = NULL; Datum shutoff_datum; bool isnull = false; Form_pg_resourcetype rtyp = (Form_pg_resourcetype)GETSTRUCT(tuple); if (!rtyp->reshasdisable) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("option \"%s\" cannot be disabled", defel->defname))); } /* required type must have a default value if it can * be disabled */ if (!rtyp->reshasdefault) { if (!rtyp->resrequired) /* optional resource without a default is * turned off by removing entry from * pg_resqueuecapability */ break; else { /* XXX XXX */ Assert(0); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("required option \"%s\" cannot be disabled", defel->defname))); } } /* get the shutoff string */ shutoff_datum = heap_getattr(tuple, Anum_pg_resourcetype_resdisabledsetting, tupdesc, &isnull); Assert(!isnull); shutoff_text = DatumGetTextP(shutoff_datum); shutoff_str = DatumGetCString( DirectFunctionCall1( textout, PointerGetDatum(shutoff_text))); pStrVal = makeString(shutoff_str); break; } /* end while heaptuple is valid */ caql_endscan(pcqCtx); } /* check for duplicate key specifications */ if (list_member(dupcheck, pKeyVal)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant option for \"%s\"", defel->defname))); dupcheck = lappend(dupcheck, pKeyVal); pentry = list_make2( makeInteger(resTypeInt), pStrVal); /* list of lists - (resource type, resource setting) */ if (bWithout) { /* if the "without" entry has an "off" value, then treat * it as a regular "with" item and update it in * pg_resqueuecapability, else remove its entry */ if (!pStrVal) dropelems = lappend(dropelems, pentry); else elems = lappend(elems, pentry); } else elems = lappend(elems, pentry); L_loop_cont: resTypeInt = 0; /* make compiler happy */ }
/* * Validate the generic options given to a FOREIGN DATA WRAPPER, SERVER, * USER MAPPING or FOREIGN TABLE that uses file_fdw. * * Raise an ERROR if the option or its value is considered invalid. */ Datum redis_fdw_validator(PG_FUNCTION_ARGS) { List *options_list = untransformRelOptions(PG_GETARG_DATUM(0)); Oid catalog = PG_GETARG_OID(1); char *svr_address = NULL; int svr_port = 0; char *svr_password = NULL; int svr_database = 0; redis_table_type tabletype = PG_REDIS_SCALAR_TABLE; char *tablekeyprefix = NULL; char *tablekeyset = NULL; ListCell *cell; #ifdef DEBUG elog(NOTICE, "redis_fdw_validator"); #endif /* * Check that only options supported by redis_fdw, and allowed for the * current object type, are given. */ foreach(cell, options_list) { DefElem *def = (DefElem *) lfirst(cell); if (!redisIsValidOption(def->defname, catalog)) { struct RedisFdwOption *opt; StringInfoData buf; /* * Unknown option specified, complain about it. Provide a hint * with list of valid options for the object. */ initStringInfo(&buf); for (opt = valid_options; opt->optname; opt++) { if (catalog == opt->optcontext) appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "", opt->optname); } ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_OPTION_NAME), errmsg("invalid option \"%s\"", def->defname), errhint("Valid options in this context are: %s", buf.len ? buf.data : "<none>") )); } if (strcmp(def->defname, "address") == 0) { if (svr_address) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: " "address (%s)", defGetString(def)) )); svr_address = defGetString(def); } else if (strcmp(def->defname, "port") == 0) { if (svr_port) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: port (%s)", defGetString(def)) )); svr_port = atoi(defGetString(def)); } if (strcmp(def->defname, "password") == 0) { if (svr_password) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: password") )); svr_password = defGetString(def); } else if (strcmp(def->defname, "database") == 0) { if (svr_database) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: database " "(%s)", defGetString(def)) )); svr_database = atoi(defGetString(def)); } else if (strcmp(def->defname, "tablekeyprefix") == 0) { if (tablekeyset) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting options: tablekeyset(%s) and " "tablekeyprefix (%s)", tablekeyset, defGetString(def)) )); if (tablekeyprefix) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: " "tablekeyprefix (%s)", defGetString(def)) )); tablekeyprefix = defGetString(def); } else if (strcmp(def->defname, "tablekeyset") == 0) { if (tablekeyprefix) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting options: tablekeyprefix (%s) and " "tablekeyset (%s)", tablekeyprefix, defGetString(def)) )); if (tablekeyset) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: " "tablekeyset (%s)", defGetString(def)) )); tablekeyset = defGetString(def); } else if (strcmp(def->defname, "tabletype") == 0) { char *typeval = defGetString(def); if (tabletype) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options: tabletype " "(%s)", typeval))); if (strcmp(typeval,"hash") == 0) tabletype = PG_REDIS_HASH_TABLE; else if (strcmp(typeval,"list") == 0) tabletype = PG_REDIS_LIST_TABLE; else if (strcmp(typeval,"set") == 0) tabletype = PG_REDIS_SET_TABLE; else if (strcmp(typeval,"zset") == 0) tabletype = PG_REDIS_ZSET_TABLE; else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid tabletype (%s) - must be hash, " "list, set or zset", typeval))); } }
/* * If CREATE/SET, add new options to array; if RESET, just check that the * user didn't say RESET (option=val). (Must do this because the grammar * doesn't enforce it.) */ foreach(cell, defList) { DefElem *def = (DefElem *) lfirst(cell); if (isReset) { if (def->arg != NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("RESET must not include values for parameters"))); } else { text *t; const char *value; Size len; /* * Error out if the namespace is not valid. A NULL namespace is * always valid. */ if (def->defnamespace != NULL) { bool valid = false; int i; if (validnsps) { for (i = 0; validnsps[i]; i++) { if (pg_strcasecmp(def->defnamespace, validnsps[i]) == 0) { valid = true; break; } } } if (!valid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized parameter namespace \"%s\"", def->defnamespace))); } if (ignoreOids && pg_strcasecmp(def->defname, "oids") == 0) continue; /* ignore if not in the same namespace */ if (namspace == NULL) { if (def->defnamespace != NULL) continue; } else if (def->defnamespace == NULL) continue; else if (pg_strcasecmp(def->defnamespace, namspace) != 0) continue; /* * Flatten the DefElem into a text string like "name=arg". If we * have just "name", assume "name=true" is meant. Note: the * namespace is not output. */ if (def->arg != NULL) value = defGetString(def); else value = "true"; len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value); /* +1 leaves room for sprintf's trailing null */ t = (text *) palloc(len + 1); SET_VARSIZE(t, len); sprintf(VARDATA(t), "%s=%s", def->defname, value); astate = accumArrayResult(astate, PointerGetDatum(t), false, TEXTOID, CurrentMemoryContext); } }
/* * Check list of options and return things filled. * This includes check on option values. */ static void check_node_options(const char *node_name, List *options, char **node_host, int *node_port, char *node_type, bool *is_primary, bool *is_preferred) { ListCell *option; if (!options) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("No options specified"))); /* Filter options */ foreach(option, options) { DefElem *defel = (DefElem *) lfirst(option); if (strcmp(defel->defname, "port") == 0) { *node_port = defGetTypeLength(defel); if (*node_port < 1 || *node_port > 65535) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("port value is out of range"))); } else if (strcmp(defel->defname, "host") == 0) { *node_host = defGetString(defel); } else if (strcmp(defel->defname, "type") == 0) { char *type_loc; type_loc = defGetString(defel); if (strcmp(type_loc, "coordinator") != 0 && strcmp(type_loc, "datanode") != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("type value is incorrect, specify 'coordinator or 'datanode'"))); if (strcmp(type_loc, "coordinator") == 0) *node_type = PGXC_NODE_COORDINATOR; else *node_type = PGXC_NODE_DATANODE; } else if (strcmp(defel->defname, "primary") == 0) { *is_primary = defGetBoolean(defel); } else if (strcmp(defel->defname, "preferred") == 0) { *is_preferred = defGetBoolean(defel); } else { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("incorrect option: %s", defel->defname))); } }