mirror of https://github.com/citusdata/citus.git
378 lines
9.3 KiB
C
378 lines
9.3 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* deparse_text_search.c
|
|
* All routines to deparse text search statements.
|
|
* This file contains all entry points specific for text search statement deparsing.
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "catalog/namespace.h"
|
|
#include "utils/builtins.h"
|
|
|
|
#include "distributed/citus_ruleutils.h"
|
|
#include "distributed/deparser.h"
|
|
#include "distributed/listutils.h"
|
|
|
|
static void AppendDefElemList(StringInfo buf, List *defelms);
|
|
|
|
static void AppendStringInfoTokentypeList(StringInfo buf, List *tokentypes);
|
|
static void AppendStringInfoDictnames(StringInfo buf, List *dicts);
|
|
|
|
|
|
/*
|
|
* DeparseCreateTextSearchStmt returns the sql for a DefineStmt defining a TEXT SEARCH
|
|
* CONFIGURATION
|
|
*
|
|
* Although the syntax is mutually exclusive on the two arguments that can be passed in
|
|
* the deparser will syntactically correct multiple definitions if provided. *
|
|
*/
|
|
char *
|
|
DeparseCreateTextSearchStmt(Node *node)
|
|
{
|
|
DefineStmt *stmt = castNode(DefineStmt, node);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
const char *identifier = NameListToQuotedString(stmt->defnames);
|
|
appendStringInfo(&buf, "CREATE TEXT SEARCH CONFIGURATION %s ", identifier);
|
|
appendStringInfoString(&buf, "(");
|
|
AppendDefElemList(&buf, stmt->definition);
|
|
appendStringInfoString(&buf, ");");
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* AppendDefElemList specialization to append a comma separated list of definitions to a
|
|
* define statement.
|
|
*
|
|
* Currently only supports String and TypeName entries. Will error on others.
|
|
*/
|
|
static void
|
|
AppendDefElemList(StringInfo buf, List *defelems)
|
|
{
|
|
DefElem *defelem = NULL;
|
|
bool first = true;
|
|
foreach_ptr(defelem, defelems)
|
|
{
|
|
if (!first)
|
|
{
|
|
appendStringInfoString(buf, ", ");
|
|
}
|
|
first = false;
|
|
|
|
/* extract identifier from defelem */
|
|
const char *identifier = NULL;
|
|
switch (nodeTag(defelem->arg))
|
|
{
|
|
case T_String:
|
|
{
|
|
identifier = quote_identifier(strVal(defelem->arg));
|
|
break;
|
|
}
|
|
|
|
case T_TypeName:
|
|
{
|
|
TypeName *typeName = castNode(TypeName, defelem->arg);
|
|
identifier = NameListToQuotedString(typeName->names);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
ereport(ERROR, (errmsg("unexpected argument during deparsing of "
|
|
"TEXT SEARCH CONFIGURATION definition")));
|
|
}
|
|
}
|
|
|
|
/* stringify */
|
|
appendStringInfo(buf, "%s = %s", defelem->defname, identifier);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseDropTextSearchConfigurationStmt returns the sql representation for a DROP TEXT
|
|
* SEARCH CONFIGURATION ... statment. Supports dropping multiple configurations at once.
|
|
*/
|
|
char *
|
|
DeparseDropTextSearchConfigurationStmt(Node *node)
|
|
{
|
|
DropStmt *stmt = castNode(DropStmt, node);
|
|
Assert(stmt->removeType == OBJECT_TSCONFIGURATION);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
appendStringInfoString(&buf, "DROP TEXT SEARCH CONFIGURATION ");
|
|
List *nameList = NIL;
|
|
bool first = true;
|
|
foreach_ptr(nameList, stmt->objects)
|
|
{
|
|
if (!first)
|
|
{
|
|
appendStringInfoString(&buf, ", ");
|
|
}
|
|
first = false;
|
|
|
|
appendStringInfoString(&buf, NameListToQuotedString(nameList));
|
|
}
|
|
|
|
if (stmt->behavior == DROP_CASCADE)
|
|
{
|
|
appendStringInfoString(&buf, " CASCADE");
|
|
}
|
|
|
|
appendStringInfoString(&buf, ";");
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseRenameTextSearchConfigurationStmt returns the sql representation of a ALTER TEXT
|
|
* SEARCH CONFIGURATION ... RENAME TO ... statement.
|
|
*/
|
|
char *
|
|
DeparseRenameTextSearchConfigurationStmt(Node *node)
|
|
{
|
|
RenameStmt *stmt = castNode(RenameStmt, node);
|
|
Assert(stmt->renameType == OBJECT_TSCONFIGURATION);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
char *identifier = NameListToQuotedString(castNode(List, stmt->object));
|
|
appendStringInfo(&buf, "ALTER TEXT SEARCH CONFIGURATION %s RENAME TO %s;",
|
|
identifier, quote_identifier(stmt->newname));
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseAlterTextSearchConfigurationStmt returns the ql representation of any generic
|
|
* ALTER TEXT SEARCH CONFIGURATION .... statement. The statements supported include:
|
|
* - ALTER TEXT SEARCH CONFIGURATIONS ... ADD MAPPING FOR [, ...] WITH [, ...]
|
|
* - ALTER TEXT SEARCH CONFIGURATIONS ... ALTER MAPPING FOR [, ...] WITH [, ...]
|
|
* - ALTER TEXT SEARCH CONFIGURATIONS ... ALTER MAPPING REPLACE ... WITH ...
|
|
* - ALTER TEXT SEARCH CONFIGURATIONS ... ALTER MAPPING FOR [, ...] REPLACE ... WITH ...
|
|
* - ALTER TEXT SEARCH CONFIGURATIONS ... DROP MAPPING [ IF EXISTS ] FOR ...
|
|
*/
|
|
char *
|
|
DeparseAlterTextSearchConfigurationStmt(Node *node)
|
|
{
|
|
AlterTSConfigurationStmt *stmt = castNode(AlterTSConfigurationStmt, node);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
char *identifier = NameListToQuotedString(castNode(List, stmt->cfgname));
|
|
appendStringInfo(&buf, "ALTER TEXT SEARCH CONFIGURATION %s", identifier);
|
|
|
|
switch (stmt->kind)
|
|
{
|
|
case ALTER_TSCONFIG_ADD_MAPPING:
|
|
{
|
|
appendStringInfoString(&buf, " ADD MAPPING FOR ");
|
|
AppendStringInfoTokentypeList(&buf, stmt->tokentype);
|
|
|
|
appendStringInfoString(&buf, " WITH ");
|
|
AppendStringInfoDictnames(&buf, stmt->dicts);
|
|
|
|
break;
|
|
}
|
|
|
|
case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
|
|
{
|
|
appendStringInfoString(&buf, " ALTER MAPPING FOR ");
|
|
AppendStringInfoTokentypeList(&buf, stmt->tokentype);
|
|
|
|
appendStringInfoString(&buf, " WITH ");
|
|
AppendStringInfoDictnames(&buf, stmt->dicts);
|
|
|
|
break;
|
|
}
|
|
|
|
case ALTER_TSCONFIG_REPLACE_DICT:
|
|
case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
|
|
{
|
|
appendStringInfoString(&buf, " ALTER MAPPING");
|
|
if (list_length(stmt->tokentype) > 0)
|
|
{
|
|
appendStringInfoString(&buf, " FOR ");
|
|
AppendStringInfoTokentypeList(&buf, stmt->tokentype);
|
|
}
|
|
|
|
if (list_length(stmt->dicts) != 2)
|
|
{
|
|
elog(ERROR, "unexpected number of dictionaries while deparsing ALTER "
|
|
"TEXT SEARCH CONFIGURATION ... ALTER MAPPING [FOR ...] REPLACE "
|
|
"statement.");
|
|
}
|
|
|
|
appendStringInfo(&buf, " REPLACE %s",
|
|
NameListToQuotedString(linitial(stmt->dicts)));
|
|
|
|
appendStringInfo(&buf, " WITH %s",
|
|
NameListToQuotedString(lsecond(stmt->dicts)));
|
|
|
|
break;
|
|
}
|
|
|
|
case ALTER_TSCONFIG_DROP_MAPPING:
|
|
{
|
|
appendStringInfoString(&buf, " DROP MAPPING");
|
|
|
|
if (stmt->missing_ok)
|
|
{
|
|
appendStringInfoString(&buf, " IF EXISTS");
|
|
}
|
|
|
|
appendStringInfoString(&buf, " FOR ");
|
|
AppendStringInfoTokentypeList(&buf, stmt->tokentype);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
elog(ERROR, "unable to deparse unsupported ALTER TEXT SEARCH STATEMENT");
|
|
}
|
|
}
|
|
|
|
appendStringInfoString(&buf, ";");
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseAlterTextSearchConfigurationSchemaStmt returns the sql statement representing
|
|
* ALTER TEXT SEARCH CONFIGURATION ... SET SCHEMA ... statements.
|
|
*/
|
|
char *
|
|
DeparseAlterTextSearchConfigurationSchemaStmt(Node *node)
|
|
{
|
|
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
|
Assert(stmt->objectType == OBJECT_TSCONFIGURATION);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
appendStringInfo(&buf, "ALTER TEXT SEARCH CONFIGURATION %s SET SCHEMA %s;",
|
|
NameListToQuotedString(castNode(List, stmt->object)),
|
|
quote_identifier(stmt->newschema));
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseTextSearchConfigurationCommentStmt returns the sql statement representing
|
|
* COMMENT ON TEXT SEARCH CONFIGURATION ... IS ...
|
|
*/
|
|
char *
|
|
DeparseTextSearchConfigurationCommentStmt(Node *node)
|
|
{
|
|
CommentStmt *stmt = castNode(CommentStmt, node);
|
|
Assert(stmt->objtype == OBJECT_TSCONFIGURATION);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
appendStringInfo(&buf, "COMMENT ON TEXT SEARCH CONFIGURATION %s IS ",
|
|
NameListToQuotedString(castNode(List, stmt->object)));
|
|
|
|
if (stmt->comment == NULL)
|
|
{
|
|
appendStringInfoString(&buf, "NULL");
|
|
}
|
|
else
|
|
{
|
|
appendStringInfoString(&buf, quote_literal_cstr(stmt->comment));
|
|
}
|
|
|
|
appendStringInfoString(&buf, ";");
|
|
|
|
return buf.data;
|
|
}
|
|
|
|
|
|
/*
|
|
* AppendStringInfoTokentypeList specializes in adding a comma separated list of
|
|
* token_tyoe's to TEXT SEARCH CONFIGURATION commands
|
|
*/
|
|
static void
|
|
AppendStringInfoTokentypeList(StringInfo buf, List *tokentypes)
|
|
{
|
|
Value *tokentype = NULL;
|
|
bool first = true;
|
|
foreach_ptr(tokentype, tokentypes)
|
|
{
|
|
if (nodeTag(tokentype) != T_String)
|
|
{
|
|
elog(ERROR,
|
|
"unexpected tokentype for deparsing in text search configuration");
|
|
}
|
|
|
|
if (!first)
|
|
{
|
|
appendStringInfoString(buf, ", ");
|
|
}
|
|
first = false;
|
|
|
|
appendStringInfoString(buf, strVal(tokentype));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* AppendStringInfoDictnames specializes in appending a comma separated list of
|
|
* dictionaries to TEXT SEARCH CONFIGURATION commands.
|
|
*/
|
|
static void
|
|
AppendStringInfoDictnames(StringInfo buf, List *dicts)
|
|
{
|
|
List *dictNames = NIL;
|
|
bool first = true;
|
|
foreach_ptr(dictNames, dicts)
|
|
{
|
|
if (!first)
|
|
{
|
|
appendStringInfoString(buf, ", ");
|
|
}
|
|
first = false;
|
|
|
|
char *dictIdentifier = NameListToQuotedString(dictNames);
|
|
appendStringInfoString(buf, dictIdentifier);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* DeparseAlterTextSearchConfigurationOwnerStmt returns the sql statement representing
|
|
* ALTER TEXT SEARCH CONFIGURATION ... ONWER TO ... commands.
|
|
*/
|
|
char *
|
|
DeparseAlterTextSearchConfigurationOwnerStmt(Node *node)
|
|
{
|
|
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
|
Assert(stmt->objectType == OBJECT_TSCONFIGURATION);
|
|
|
|
StringInfoData buf = { 0 };
|
|
initStringInfo(&buf);
|
|
|
|
appendStringInfo(&buf, "ALTER TEXT SEARCH CONFIGURATION %s OWNER TO %s;",
|
|
NameListToQuotedString(castNode(List, stmt->object)),
|
|
RoleSpecString(stmt->newowner, true));
|
|
|
|
return buf.data;
|
|
}
|