bdr_parse_bool(elem, &data->forward_changesets);
else if (strcmp(elem->defname, "replication_sets") == 0)
{
+ int i;
+
+ /* parse list */
bdr_parse_identifier_list_arr(elem,
&data->replication_sets,
&data->num_replication_sets);
+
+ /* validate elements */
+ for (i = 0; i < data->num_replication_sets; i++)
+ bdr_validate_replication_set_name(data->replication_sets[i],
+ true);
+
+ /* make it bsearch()able */
qsort(data->replication_sets, data->num_replication_sets,
sizeof(char *), pg_qsort_strcmp);
}
/*
* Compare the two ordered list of replication sets and find overlapping
* elements.
+ *
+ * XXX: At some point in the future we probably want to cache this
+ * computation in the bdr relcache entry.
*/
i = j = 0;
while (i < data->num_replication_sets && j < r->num_replication_sets)
#include "utils/catcache.h"
#include "utils/inval.h"
+#include "utils/jsonapi.h"
+#include "utils/json.h"
+#include "utils/jsonb.h"
static HTAB *BDRRelcacheHash = NULL;
(Datum) 0);
}
-#include "utils/jsonapi.h"
-#include "utils/json.h"
-#include "utils/jsonb.h"
+void
+bdr_validate_replication_set_name(const char *name,
+ bool allow_implicit)
+{
+ const char *cp;
+
+ if (strlen(name) == 0)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("replication set name \"%s\" is too short",
+ name)));
+ }
+
+ if (strlen(name) >= NAMEDATALEN)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_NAME_TOO_LONG),
+ errmsg("replication set name \"%s\" is too long",
+ name)));
+ }
+
+ for (cp = name; *cp; cp++)
+ {
+ if (!((*cp >= 'a' && *cp <= 'z')
+ || (*cp >= '0' && *cp <= '9')
+ || (*cp == '_')
+ || (*cp == '-')))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("replication set name \"%s\" contains invalid character",
+ name),
+ errhint("Replication set names may only contain letters, numbers, and the underscore character.")));
+ }
+ }
+
+ if (!allow_implicit && (
+ strcmp(name, "default") == 0 ||
+ strcmp(name, "all") == 0
+ ))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_NAME_TOO_LONG),
+ errmsg("replication set name \"%s\" is reserved",
+ name)));
+ }
+}
void
bdr_parse_relation_options(const char *label, BDRRelation *rel)
else if (parsing_sets)
{
char *setname;
+ MemoryContext oldcontext;
if (r != WJB_ELEM)
elog(ERROR, "unexpected element type %u", r);
if (level != 2)
elog(ERROR, "unexpected level for set %d", level);
+ oldcontext = MemoryContextSwitchTo(CacheMemoryContext);
+
+ setname = pnstrdup(v.val.string.val, v.val.string.len);
+ bdr_validate_replication_set_name(setname, false);
+
if (rel != NULL)
{
- MemoryContext oldcontext;
-
- oldcontext = MemoryContextSwitchTo(CacheMemoryContext);
- setname = pnstrdup(v.val.string.val, v.val.string.len);
rel->replication_sets[rel->num_replication_sets++] = setname;
- MemoryContextSwitchTo(oldcontext);
}
+ else
+ pfree(setname);
+
+ MemoryContextSwitchTo(oldcontext);
}
else
elog(ERROR, "unexpected content: %u at level %d", r, level);