select ts_lexize('intdict', '641439323669');
select ts_lexize('intdict', '314532610153');
-ALTER TEXT SEARCH DICTIONARY intdict (MAXLEN = -214783648);
+ALTER TEXT SEARCH DICTIONARY intdict (MAXLEN = -214783648); -- fail
+-- This ought to fail, perhaps, but historically it has not:
+ALTER TEXT SEARCH DICTIONARY intdict (MAXLEN = 6.7);
select ts_lexize('intdict', '-40865854');
select ts_lexize('intdict', '+40865854');
ALTER TEXT SEARCH DICTIONARY intdict (ABSVAL = true);
select ts_lexize('intdict', '-40865854');
select ts_lexize('intdict', '+40865854');
+ALTER TEXT SEARCH DICTIONARY intdict (REJECTLONG = 1);
+select ts_lexize('intdict', '-40865854');
+select ts_lexize('intdict', '-4086585');
+select ts_lexize('intdict', '-408658');
+
+SELECT dictinitoption FROM pg_ts_dict WHERE dictname = 'intdict';
#include "commands/alter.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
+#include "common/string.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_func.h"
HeapTuple tup, Relation relMap);
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
HeapTuple tup, Relation relMap);
+static DefElem *buildDefItem(const char *name, const char *val,
+ bool was_quoted);
/* --------------------- TS Parser commands ------------------------ */
* For the convenience of pg_dump, the output is formatted exactly as it
* would need to appear in CREATE TEXT SEARCH DICTIONARY to reproduce the
* same options.
- *
- * Note that we assume that only the textual representation of an option's
- * value is interesting --- hence, non-string DefElems get forced to strings.
*/
text *
serialize_deflist(List *deflist)
appendStringInfo(&buf, "%s = ",
quote_identifier(defel->defname));
- /* If backslashes appear, force E syntax to determine their handling */
- if (strchr(val, '\\'))
- appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
- appendStringInfoChar(&buf, '\'');
- while (*val)
+
+ /*
+ * If the value is a T_Integer or T_Float, emit it without quotes,
+ * otherwise with quotes. This is essential to allow correct
+ * reconstruction of the node type as well as the value.
+ */
+ if (IsA(defel->arg, Integer) || IsA(defel->arg, Float))
+ appendStringInfoString(&buf, val);
+ else
{
- char ch = *val++;
+ /* 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))
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(&buf, ch);
appendStringInfoChar(&buf, ch);
- appendStringInfoChar(&buf, ch);
+ }
+ appendStringInfoChar(&buf, '\'');
}
- appendStringInfoChar(&buf, '\'');
if (lnext(deflist, l) != NULL)
appendStringInfoString(&buf, ", ");
}
*
* This is also used for prsheadline options, so for backward compatibility
* we need to accept a few things serialize_deflist() will never emit:
- * in particular, unquoted and double-quoted values.
+ * in particular, unquoted and double-quoted strings.
*/
List *
deserialize_deflist(Datum txt)
{
*wsptr++ = '\0';
result = lappend(result,
- makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue)), -1));
+ buildDefItem(workspace,
+ startvalue,
+ true));
state = CS_WAITKEY;
}
}
{
*wsptr++ = '\0';
result = lappend(result,
- makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue)), -1));
+ buildDefItem(workspace,
+ startvalue,
+ true));
state = CS_WAITKEY;
}
}
{
*wsptr++ = '\0';
result = lappend(result,
- makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue)), -1));
+ buildDefItem(workspace,
+ startvalue,
+ false));
state = CS_WAITKEY;
}
else
{
*wsptr++ = '\0';
result = lappend(result,
- makeDefElem(pstrdup(workspace),
- (Node *) makeString(pstrdup(startvalue)), -1));
+ buildDefItem(workspace,
+ startvalue,
+ false));
}
else if (state != CS_WAITKEY)
ereport(ERROR,
return result;
}
+
+/*
+ * Build one DefElem for deserialize_deflist
+ */
+static DefElem *
+buildDefItem(const char *name, const char *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);
+ }
+ /* Just make it a string */
+ return makeDefElem(pstrdup(name),
+ (Node *) makeString(pstrdup(val)),
+ -1);
+}
{index}
(1 row)
+-- test altering boolean parameters
+SELECT dictinitoption FROM pg_ts_dict WHERE dictname = 'synonym';
+ dictinitoption
+-----------------------------
+ synonyms = 'synonym_sample'
+(1 row)
+
+ALTER TEXT SEARCH DICTIONARY synonym (CaseSensitive = 1);
+SELECT ts_lexize('synonym', 'PoStGrEs');
+ ts_lexize
+-----------
+
+(1 row)
+
+SELECT dictinitoption FROM pg_ts_dict WHERE dictname = 'synonym';
+ dictinitoption
+------------------------------------------------
+ synonyms = 'synonym_sample', casesensitive = 1
+(1 row)
+
+ALTER TEXT SEARCH DICTIONARY synonym (CaseSensitive = 2); -- fail
+ERROR: casesensitive requires a Boolean value
+ALTER TEXT SEARCH DICTIONARY synonym (CaseSensitive = off);
+SELECT ts_lexize('synonym', 'PoStGrEs');
+ ts_lexize
+-----------
+ {pgsql}
+(1 row)
+
+SELECT dictinitoption FROM pg_ts_dict WHERE dictname = 'synonym';
+ dictinitoption
+----------------------------------------------------
+ synonyms = 'synonym_sample', casesensitive = 'off'
+(1 row)
+
-- Create and simple test thesaurus dictionary
-- More tests in configuration checks because ts_lexize()
-- cannot pass more than one word to thesaurus.