/* 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)));
}
}
}
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.