static ovsdb_operation_executor ovsdb_execute_wait;
static ovsdb_operation_executor ovsdb_execute_commit;
static ovsdb_operation_executor ovsdb_execute_abort;
-static ovsdb_operation_executor ovsdb_execute_declare;
static ovsdb_operation_executor ovsdb_execute_comment;
static ovsdb_operation_executor *
{ "wait", ovsdb_execute_wait },
{ "commit", ovsdb_execute_commit },
{ "abort", ovsdb_execute_abort },
- { "declare", ovsdb_execute_declare },
{ "comment", ovsdb_execute_comment },
};
size_t n_operations;
size_t i;
- if (params->type != JSON_ARRAY) {
+ if (params->type != JSON_ARRAY
+ || !params->u.array.n
+ || params->u.array.elems[0]->type != JSON_STRING
+ || strcmp(params->u.array.elems[0]->u.string, db->schema->name)) {
struct ovsdb_error *error;
- error = ovsdb_syntax_error(params, NULL, "array expected");
+ if (params->type != JSON_ARRAY) {
+ error = ovsdb_syntax_error(params, NULL, "array expected");
+ } else {
+ error = ovsdb_syntax_error(params, NULL, "database name expected "
+ "as first parameter");
+ }
+
results = ovsdb_error_to_json(error);
ovsdb_error_destroy(error);
return results;
results = NULL;
results = json_array_create_empty();
- n_operations = params->u.array.n;
+ n_operations = params->u.array.n - 1;
error = NULL;
- for (i = 0; i < n_operations; i++) {
+ for (i = 1; i <= n_operations; i++) {
struct json *operation = params->u.array.elems[i];
struct ovsdb_error *parse_error;
struct ovsdb_parser parser;
/* Parse and execute operation. */
ovsdb_parser_init(&parser, operation,
- "ovsdb operation %zu of %zu", i + 1, n_operations);
+ "ovsdb operation %zu of %zu", i, n_operations);
op = ovsdb_parser_member(&parser, "op", OP_ID);
result = json_object_create();
if (op) {
struct ovsdb_error *
ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser,
- struct json *result UNUSED)
+ struct json *result OVS_UNUSED)
{
const struct json *durable;
}
static struct ovsdb_error *
-ovsdb_execute_abort(struct ovsdb_execution *x UNUSED,
- struct ovsdb_parser *parser UNUSED,
- struct json *result UNUSED)
+ovsdb_execute_abort(struct ovsdb_execution *x OVS_UNUSED,
+ struct ovsdb_parser *parser OVS_UNUSED,
+ struct json *result OVS_UNUSED)
{
return ovsdb_error("aborted", "aborted by request");
}
static WARN_UNUSED_RESULT struct ovsdb_error *
parse_row(struct ovsdb_parser *parser, const char *member,
const struct ovsdb_table *table,
- const struct ovsdb_symbol_table *symtab,
+ struct ovsdb_symbol_table *symtab,
struct ovsdb_row **rowp, struct ovsdb_column_set *columns)
{
struct ovsdb_error *error;
if (uuid_name) {
struct ovsdb_symbol *symbol;
- symbol = ovsdb_symbol_table_get(x->symtab, json_string(uuid_name));
- if (symbol) {
- if (symbol->used) {
- return ovsdb_syntax_error(uuid_name, "duplicate uuid-name",
- "This \"uuid-name\" appeared on an "
- "earlier \"insert\" operation.");
- }
- row_uuid = symbol->uuid;
- symbol->used = true;
- } else {
- uuid_generate(&row_uuid);
- ovsdb_symbol_table_put(x->symtab, json_string(uuid_name),
- &row_uuid, true);
+ symbol = ovsdb_symbol_table_insert(x->symtab, json_string(uuid_name));
+ if (symbol->used) {
+ return ovsdb_syntax_error(uuid_name, "duplicate uuid-name",
+ "This \"uuid-name\" appeared on an "
+ "earlier \"insert\" operation.");
}
+ row_uuid = symbol->uuid;
+ symbol->used = true;
} else {
uuid_generate(&row_uuid);
}
if (!error) {
error = parse_row(parser, "row", table, x->symtab, &row, NULL);
}
+ if (!error) {
+ /* Check constraints for columns not included in "row", in case the
+ * default values do not satisfy the constraints. We could check only
+ * the columns that have their default values by supplying an
+ * ovsdb_column_set to parse_row() above, but I suspect that this is
+ * cheaper. */
+ const struct shash_node *node;
+
+ SHASH_FOR_EACH (node, &table->schema->columns) {
+ const struct ovsdb_column *column = node->data;
+ const struct ovsdb_datum *datum = &row->fields[column->index];
+
+ /* If there are 0 keys or pairs, there's nothing to check.
+ * If there is 1, it might be a default value.
+ * If there are more, it can't be a default value, so the value has
+ * already been checked. */
+ if (datum->n == 1) {
+ error = ovsdb_datum_check_constraints(datum, &column->type);
+ if (error) {
+ ovsdb_row_destroy(row);
+ break;
+ }
+ }
+ }
+ }
if (!error) {
*ovsdb_row_get_uuid_rw(row) = row_uuid;
ovsdb_txn_row_insert(x->txn, row);
json_object_put(result, "uuid",
ovsdb_datum_to_json(&row->fields[OVSDB_COL_UUID],
&ovsdb_type_uuid));
- row = NULL;
}
return error;
}
static struct ovsdb_error *
ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser,
- struct json *result UNUSED)
+ struct json *result OVS_UNUSED)
{
struct ovsdb_table *table;
const struct json *timeout, *where, *columns_json, *until, *rows;
/* Parse "rows" into 'expected'. */
ovsdb_row_hash_init(&expected, &columns);
for (i = 0; i < rows->u.array.n; i++) {
- struct ovsdb_error *error;
struct ovsdb_row *row;
row = ovsdb_row_create(table);
return error;
}
-static struct ovsdb_error *
-ovsdb_execute_declare(struct ovsdb_execution *x, struct ovsdb_parser *parser,
- struct json *result)
-{
- const struct json *uuid_name;
- struct uuid uuid;
-
- uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID);
- if (!uuid_name) {
- return NULL;
- }
-
- if (ovsdb_symbol_table_get(x->symtab, json_string(uuid_name))) {
- return ovsdb_syntax_error(uuid_name, "duplicate uuid-name",
- "This \"uuid-name\" appeared on an "
- "earlier \"declare\" or \"insert\" "
- "operation.");
- }
-
- uuid_generate(&uuid);
- ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), &uuid, false);
- json_object_put(result, "uuid",
- json_array_create_2(
- json_string_create("uuid"),
- json_string_create_nocopy(
- xasprintf(UUID_FMT, UUID_ARGS(&uuid)))));
- return NULL;
-}
-
static struct ovsdb_error *
ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser,
- struct json *result UNUSED)
+ struct json *result OVS_UNUSED)
{
const struct json *comment;