/* Single entry of List returned by getTokenTypes() */ typedefstruct
{ int num; /* token type number */ char *name; /* token type name */
} TSTokenTypeItem;
/* *lookupaparsersupportfunctionandreturnitsOID(asaDatum) * *attnumisthepg_ts_parsercolumnthefunctionwillgointo
*/ static Datum
get_ts_parser_func(DefElem *defel, int attnum)
{
List *funcName = defGetQualifiedName(defel);
Oid typeId[3];
Oid retTypeId; int nargs;
Oid procOid;
retTypeId = INTERNALOID; /* correct for most */ typeId[0] = INTERNALOID; switch (attnum)
{ case Anum_pg_ts_parser_prsstart:
nargs = 2; typeId[1] = INT4OID; break; case Anum_pg_ts_parser_prstoken:
nargs = 3; typeId[1] = INTERNALOID; typeId[2] = INTERNALOID; break; case Anum_pg_ts_parser_prsend:
nargs = 1;
retTypeId = VOIDOID; break; case Anum_pg_ts_parser_prsheadline:
nargs = 3; typeId[1] = INTERNALOID; typeId[2] = TSQUERYOID; break; case Anum_pg_ts_parser_prslextype:
nargs = 1;
/* *Note:becausethelextypemethodreturnstypeinternal,itmust *haveaninternal-typeargumentforsecurityreasons.The *argumentisnotactuallyused,butisjustpassedasazero.
*/ break; default: /* should not be here */
elog(ERROR, "unrecognized attribute for text search parser: %d",
attnum);
nargs = 0; /* keep compiler quiet */
}
procOid = LookupFuncName(funcName, nargs, typeId, false); if (get_func_rettype(procOid) != retTypeId)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("function %s should return type %s",
func_signature_string(funcName, nargs, NIL, typeId),
format_type_be(retTypeId))));
/* *Validation
*/ if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsstart - 1])))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("text search parser start method is required")));
if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prstoken - 1])))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("text search parser gettoken method is required")));
if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsend - 1])))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("text search parser end method is required")));
if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prslextype - 1])))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("text search parser lextypes method is required")));
/* *verifythatatemplate'sinitmethodacceptsaproposedoptionlist
*/ staticvoid
verify_dictoptions(Oid tmplId, List *dictoptions)
{
HeapTuple tup;
Form_pg_ts_template tform;
Oid initmethod;
/* *Suppressthistestwhenrunninginastandalonebackend.Thisisa *hacktoallowinitdbtocreateprefabdictionariesthatmightnot *actuallybeusableintemplate1'sencoding(duetousingexternalfiles *thatcan'tbetranslatedintotemplate1'sencoding).Wewanttocreate *themanyway,sincetheymightbeusablelaterinotherdatabases.
*/ if (!IsUnderPostmaster) return;
tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId)); if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for text search template %u",
tmplId);
tform = (Form_pg_ts_template) GETSTRUCT(tup);
initmethod = tform->tmplinit;
if (!OidIsValid(initmethod))
{ /* If there is no init method, disallow any options */ if (dictoptions)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("text search template \"%s\" does not accept options",
NameStr(tform->tmplname))));
} else
{ /* *Copytheoptionsjustincaseinitmethodthinksitcanscribbleon *them...
*/
dictoptions = copyObject(dictoptions);
/* *CREATETEXTSEARCHDICTIONARY
*/
ObjectAddress
DefineTSDictionary(List *names, List *parameters)
{
ListCell *pl;
Relation dictRel;
HeapTuple tup;
Datum values[Natts_pg_ts_dict]; bool nulls[Natts_pg_ts_dict];
NameData dname;
Oid templId = InvalidOid;
List *dictoptions = NIL;
Oid dictOid;
Oid namespaceoid;
AclResult aclresult; char *dictname;
ObjectAddress address;
/* Convert list of names to a name and namespace */
namespaceoid = QualifiedNameGetCreationNamespace(names, &dictname);
/* Check we have creation rights in target namespace */
aclresult = object_aclcheck(NamespaceRelationId, namespaceoid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_SCHEMA,
get_namespace_name(namespaceoid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for text search dictionary %u",
dictId);
/* must be owner */ if (!object_ownercheck(TSDictionaryRelationId, dictId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSDICTIONARY,
NameListToString(stmt->dictname));
/* deserialize the existing set of options */
opt = SysCacheGetAttr(TSDICTOID, tup,
Anum_pg_ts_dict_dictinitoption,
&isnull); if (isnull)
dictoptions = NIL; else
dictoptions = deserialize_deflist(opt);
/* *lookupatemplatesupportfunctionandreturnitsOID(asaDatum) * *attnumisthepg_ts_templatecolumnthefunctionwillgointo
*/ static Datum
get_ts_template_func(DefElem *defel, int attnum)
{
List *funcName = defGetQualifiedName(defel);
Oid typeId[4];
Oid retTypeId; int nargs;
Oid procOid;
retTypeId = INTERNALOID; typeId[0] = INTERNALOID; typeId[1] = INTERNALOID; typeId[2] = INTERNALOID; typeId[3] = INTERNALOID; switch (attnum)
{ case Anum_pg_ts_template_tmplinit:
nargs = 1; break; case Anum_pg_ts_template_tmpllexize:
nargs = 4; break; default: /* should not be here */
elog(ERROR, "unrecognized attribute for text search template: %d",
attnum);
nargs = 0; /* keep compiler quiet */
}
procOid = LookupFuncName(funcName, nargs, typeId, false); if (get_func_rettype(procOid) != retTypeId)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("function %s should return type %s",
func_signature_string(funcName, nargs, NIL, typeId),
format_type_be(retTypeId))));
/* for ALTER case, first flush old dependencies, except extension deps */ if (removeOld)
{
deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
}
/* Record 'em (this includes duplicate elimination) */
record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
free_object_addresses(addrs);
return myself;
}
/* *CREATETEXTSEARCHCONFIGURATION
*/
ObjectAddress
DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
{
Relation cfgRel;
Relation mapRel = NULL;
HeapTuple tup;
Datum values[Natts_pg_ts_config]; bool nulls[Natts_pg_ts_config];
AclResult aclresult;
Oid namespaceoid; char *cfgname;
NameData cname;
Oid sourceOid = InvalidOid;
Oid prsOid = InvalidOid;
Oid cfgOid;
ListCell *pl;
ObjectAddress address;
/* Convert list of names to a name and namespace */
namespaceoid = QualifiedNameGetCreationNamespace(names, &cfgname);
/* Check we have creation rights in target namespace */
aclresult = object_aclcheck(NamespaceRelationId, namespaceoid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_SCHEMA,
get_namespace_name(namespaceoid));
if (OidIsValid(sourceOid) && OidIsValid(prsOid))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot specify both PARSER and COPY options")));
/* make copied tsconfig available to callers */ if (copied && OidIsValid(sourceOid))
{
ObjectAddressSet(*copied,
TSConfigRelationId,
sourceOid);
}
/* *Lookupsourceconfigifgiven.
*/ if (OidIsValid(sourceOid))
{
Form_pg_ts_config cfg;
tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(sourceOid)); if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for text search configuration %u",
sourceOid);
cfg = (Form_pg_ts_config) GETSTRUCT(tup);
/* use source's parser */
prsOid = cfg->cfgparser;
ReleaseSysCache(tup);
}
/* *Validation
*/ if (!OidIsValid(prsOid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("text search parser is required")));
/* If slots are full, insert a batch of tuples */ if (slot_stored_count == max_slots)
{
CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count,
indstate);
slot_stored_count = 0;
}
}
/* Insert any tuples left in the buffer */ if (slot_stored_count > 0)
CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count,
indstate);
for (int i = 0; i < slot_init_count; i++)
ExecDropSingleTupleTableSlot(slot[i]);
/* Find the configuration */
tup = GetTSConfigTuple(stmt->cfgname); if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("text search configuration \"%s\" does not exist",
NameListToString(stmt->cfgname))));
/* must be owner */ if (!object_ownercheck(TSConfigRelationId, cfgId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSCONFIGURATION,
NameListToString(stmt->cfgname));
if (strcmp(token_name, ts->name) == 0)
{
found = true; break;
}
}
return found;
}
/* *TranslatealistoftokentypenamestoalistofuniqueTSTokenTypeItem. * *Duplicatedentrieslistareremovedfromtokennames.
*/ static List *
getTokenTypes(Oid prsId, List *tokennames)
{
TSParserCacheEntry *prs = lookup_ts_parser_cache(prsId);
LexDescr *list;
List *result = NIL; int ntoken;
ListCell *tn;
ntoken = list_length(tokennames); if (ntoken == 0) return NIL;
if (!OidIsValid(prs->lextypeOid))
elog(ERROR, "method lextype isn't defined for text search parser %u",
prsId);
/* lextype takes one dummy argument */
list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
(Datum) 0));
foreach(tn, tokennames)
{
String *val = lfirst_node(String, tn); bool found = false; int j;
/* Skip if this token is already in the result */ if (tstoken_list_member(strVal(val), result)) continue;
j = 0; while (list && list[j].lexid)
{ if (strcmp(strVal(val), list[j].alias) == 0)
{
TSTokenTypeItem *ts = (TSTokenTypeItem *) palloc0(sizeof(TSTokenTypeItem));
ts->num = list[j].lexid;
ts->name = pstrdup(strVal(val));
result = lappend(result, ts);
found = true; break;
}
j++;
} if (!found)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("token type \"%s\" does not exist",
strVal(val))));
}
return result;
}
/* *ALTERTEXTSEARCHCONFIGURATIONADD/ALTERMAPPING
*/ staticvoid
MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
HeapTuple tup, Relation relMap)
{
Form_pg_ts_config tsform;
Oid cfgId;
ScanKeyData skey[2];
SysScanDesc scan;
HeapTuple maptup; int i; int j;
Oid prsId;
List *tokens = NIL; int ntoken;
Oid *dictIds; int ndict;
ListCell *c;
CatalogIndexState indstate;
systable_endscan(scan);
} else
{
TupleTableSlot **slot; int slotCount = 0; int nslots;
/* Allocate the slots to use and initialize them */
nslots = Min(ntoken * ndict,
MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_ts_config_map));
slot = palloc(sizeof(TupleTableSlot *) * nslots); for (i = 0; i < nslots; i++)
slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(relMap),
&TTSOpsHeapTuple);
while (HeapTupleIsValid((maptup = systable_getnext(scan))))
{
CatalogTupleDelete(relMap, &maptup->t_self);
found = true;
}
systable_endscan(scan);
if (!found)
{ if (!stmt->missing_ok)
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("mapping for token type \"%s\" does not exist",
ts->name)));
} else
{
ereport(NOTICE,
(errmsg("mapping for token type \"%s\" does not exist, skipping",
ts->name)));
}
}
}
/* *IfthevalueisaT_IntegerorT_Float,emititwithoutquotes, *otherwisewithquotes.Thisisessentialtoallowcorrect *reconstructionofthenodetypeaswellasthevalue.
*/ if (IsA(defel->arg, Integer) || IsA(defel->arg, Float))
appendStringInfoString(&buf, val); else
{ /* If backslashes appear, force E syntax to quote them safely */ if (strchr(val, '\\'))
appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
appendStringInfoChar(&buf, '\''); while (*val)
{ char ch = *val++;
if (SQL_STR_DOUBLE(ch, true))
appendStringInfoChar(&buf, ch);
appendStringInfoChar(&buf, ch);
}
appendStringInfoChar(&buf, '\'');
} if (lnext(deflist, l) != NULL)
appendStringInfoString(&buf, ", ");
}
result = cstring_to_text_with_len(buf.data, buf.len);
pfree(buf.data); return result;
}
/* *Deserializedictionaryoptions,reconstructingaListofDefElemfromTEXT * *Thisisalsousedforprsheadlineoptions,soforbackwardcompatibility *weneedtoacceptafewthingsserialize_deflist()willneveremit: *inparticular,unquotedanddouble-quotedstrings.
*/
List *
deserialize_deflist(Datum txt)
{
text *in = DatumGetTextPP(txt); /* in case it's toasted */
List *result = NIL; int len = VARSIZE_ANY_EXHDR(in); char *ptr,
*endptr,
*workspace,
*wsptr = NULL,
*startvalue = NULL; typedefenum
{
CS_WAITKEY,
CS_INKEY,
CS_INQKEY,
CS_WAITEQ,
CS_WAITVALUE,
CS_INSQVALUE,
CS_INDQVALUE,
CS_INWVALUE
} ds_state;
ds_state state = CS_WAITKEY;
workspace = (char *) palloc(len + 1); /* certainly enough room */
ptr = VARDATA_ANY(in);
endptr = ptr + len; for (; ptr < endptr; ptr++)
{ switch (state)
{ case CS_WAITKEY: if (isspace((unsignedchar) *ptr) || *ptr == ',') continue; if (*ptr == '"')
{
wsptr = workspace;
state = CS_INQKEY;
} else
{
wsptr = workspace;
*wsptr++ = *ptr;
state = CS_INKEY;
} break; case CS_INKEY: if (isspace((unsignedchar) *ptr))
{
*wsptr++ = '\0';
state = CS_WAITEQ;
} elseif (*ptr == '=')
{
*wsptr++ = '\0';
state = CS_WAITVALUE;
} else
{
*wsptr++ = *ptr;
} break; case CS_INQKEY: if (*ptr == '"')
{ if (ptr + 1 < endptr && ptr[1] == '"')
{ /* copy only one of the two quotes */
*wsptr++ = *ptr++;
} else
{
*wsptr++ = '\0';
state = CS_WAITEQ;
}
} else
{
*wsptr++ = *ptr;
} break; case CS_WAITEQ: if (*ptr == '=')
state = CS_WAITVALUE; elseif (!isspace((unsignedchar) *ptr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid parameter list format: \"%s\"",
text_to_cstring(in)))); break; case CS_WAITVALUE: if (*ptr == '\'')
{
startvalue = wsptr;
state = CS_INSQVALUE;
} elseif (*ptr == 'E' && ptr + 1 < endptr && ptr[1] == '\'')
{
ptr++;
startvalue = wsptr;
state = CS_INSQVALUE;
} elseif (*ptr == '"')
{
startvalue = wsptr;
state = CS_INDQVALUE;
} elseif (!isspace((unsignedchar) *ptr))
{
startvalue = wsptr;
*wsptr++ = *ptr;
state = CS_INWVALUE;
} break; case CS_INSQVALUE: if (*ptr == '\'')
{ if (ptr + 1 < endptr && ptr[1] == '\'')
{ /* copy only one of the two quotes */
*wsptr++ = *ptr++;
} else
{
*wsptr++ = '\0';
result = lappend(result,
buildDefItem(workspace,
startvalue, true));
state = CS_WAITKEY;
}
} elseif (*ptr == '\\')
{ if (ptr + 1 < endptr && ptr[1] == '\\')
{ /* copy only one of the two backslashes */
*wsptr++ = *ptr++;
} else
*wsptr++ = *ptr;
} else
{
*wsptr++ = *ptr;
} break; case CS_INDQVALUE: if (*ptr == '"')
{ if (ptr + 1 < endptr && ptr[1] == '"')
{ /* copy only one of the two quotes */
*wsptr++ = *ptr++;
} else
{
*wsptr++ = '\0';
result = lappend(result,
buildDefItem(workspace,
startvalue, true));
state = CS_WAITKEY;
}
} else
{
*wsptr++ = *ptr;
} break; case CS_INWVALUE: if (*ptr == ',' || isspace((unsignedchar) *ptr))
{
*wsptr++ = '\0';
result = lappend(result,
buildDefItem(workspace,
startvalue, false));
state = CS_WAITKEY;
} else
{
*wsptr++ = *ptr;
} break; default:
elog(ERROR, "unrecognized deserialize_deflist state: %d",
state);
}
}
if (state == CS_INWVALUE)
{
*wsptr++ = '\0';
result = lappend(result,
buildDefItem(workspace,
startvalue, false));
} elseif (state != CS_WAITKEY)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid parameter list format: \"%s\"",
text_to_cstring(in))));
pfree(workspace);
return result;
}
/* *BuildoneDefElemfordeserialize_deflist
*/ static DefElem *
buildDefItem(constchar *name, constchar *val, bool was_quoted)
{ /* If input was quoted, always emit as string */ if (!was_quoted && val[0] != '\0')
{ int v; char *endptr;
/* Try to parse as an integer */
errno = 0;
v = strtoint(val, &endptr, 10); if (errno == 0 && *endptr == '\0') return makeDefElem(pstrdup(name),
(Node *) makeInteger(v),
-1); /* Nope, how about as a float? */
errno = 0;
(void) strtod(val, &endptr); if (errno == 0 && *endptr == '\0') return makeDefElem(pstrdup(name),
(Node *) makeFloat(pstrdup(val)),
-1);
if (strcmp(val, "true") == 0) return makeDefElem(pstrdup(name),
(Node *) makeBoolean(true),
-1); if (strcmp(val, "false") == 0) return makeDefElem(pstrdup(name),
(Node *) makeBoolean(false),
-1);
} /* Just make it a string */ return makeDefElem(pstrdup(name),
(Node *) makeString(pstrdup(val)),
-1);
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.34Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.