2 * Copyright (c) 2015 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include "db-ctl-base.h"
25 #include "command-line.h"
28 #include "dynamic-string.h"
29 #include "fatal-signal.h"
32 #include "openvswitch/vlog.h"
33 #include "ovsdb-data.h"
34 #include "ovsdb-idl.h"
35 #include "ovsdb-idl-provider.h"
41 VLOG_DEFINE_THIS_MODULE(db_ctl_base
);
43 /* The IDL we're using and the current transaction, if any.
44 * This is for use by ctl_exit() only, to allow it to clean up.
45 * Other code should use its context arguments. */
46 struct ovsdb_idl
*the_idl
;
47 struct ovsdb_idl_txn
*the_idl_txn
;
49 static struct shash all_commands
= SHASH_INITIALIZER(&all_commands
);
53 die_if_error(char *error
)
56 ctl_fatal("%s", error
);
61 to_lower_and_underscores(unsigned c
)
63 return c
== '-' ? '_' : tolower(c
);
67 score_partial_match(const char *name
, const char *s
)
71 if (!strcmp(name
, s
)) {
74 for (score
= 0; ; score
++, name
++, s
++) {
75 if (to_lower_and_underscores(*name
) != to_lower_and_underscores(*s
)) {
77 } else if (*name
== '\0') {
81 return *s
== '\0' ? score
: 0;
84 static struct ovsdb_symbol
*
85 create_symbol(struct ovsdb_symbol_table
*symtab
, const char *id
, bool *newp
)
87 struct ovsdb_symbol
*symbol
;
90 ctl_fatal("row id \"%s\" does not begin with \"@\"", id
);
94 *newp
= ovsdb_symbol_table_get(symtab
, id
) == NULL
;
97 symbol
= ovsdb_symbol_table_insert(symtab
, id
);
98 if (symbol
->created
) {
99 ctl_fatal("row id \"%s\" may only be specified on one --id option",
102 symbol
->created
= true;
106 static const struct ovsdb_idl_row
*
107 get_row_by_id(struct ctl_context
*ctx
, const struct ctl_table_class
*table
,
108 const struct ctl_row_id
*id
, const char *record_id
)
110 const struct ovsdb_idl_row
*referrer
, *final
;
116 if (!id
->name_column
) {
117 if (strcmp(record_id
, ".")) {
120 referrer
= ovsdb_idl_first_row(ctx
->idl
, id
->table
);
121 if (!referrer
|| ovsdb_idl_next_row(referrer
)) {
125 const struct ovsdb_idl_row
*row
;
128 for (row
= ovsdb_idl_first_row(ctx
->idl
, id
->table
);
130 row
= ovsdb_idl_next_row(row
))
132 const struct ovsdb_datum
*name
;
134 name
= ovsdb_idl_get(row
, id
->name_column
,
135 OVSDB_TYPE_STRING
, OVSDB_TYPE_VOID
);
136 if (name
->n
== 1 && !strcmp(name
->keys
[0].string
, record_id
)) {
138 ctl_fatal("multiple rows in %s match \"%s\"",
139 table
->class->name
, record_id
);
150 if (id
->uuid_column
) {
151 const struct ovsdb_datum
*uuid
;
153 ovsdb_idl_txn_verify(referrer
, id
->uuid_column
);
154 uuid
= ovsdb_idl_get(referrer
, id
->uuid_column
,
155 OVSDB_TYPE_UUID
, OVSDB_TYPE_VOID
);
157 final
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
->class,
158 &uuid
->keys
[0].uuid
);
167 static const struct ovsdb_idl_row
*
168 get_row(struct ctl_context
*ctx
,
169 const struct ctl_table_class
*table
, const char *record_id
,
172 const struct ovsdb_idl_row
*row
;
176 if (uuid_from_string(&uuid
, record_id
)) {
177 row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
->class, &uuid
);
182 for (i
= 0; i
< ARRAY_SIZE(table
->row_ids
); i
++) {
183 row
= get_row_by_id(ctx
, table
, &table
->row_ids
[i
], record_id
);
189 if (must_exist
&& !row
) {
190 ctl_fatal("no row \"%s\" in table %s",
191 record_id
, table
->class->name
);
197 get_column(const struct ctl_table_class
*table
, const char *column_name
,
198 const struct ovsdb_idl_column
**columnp
)
200 const struct ovsdb_idl_column
*best_match
= NULL
;
201 unsigned int best_score
= 0;
204 for (i
= 0; i
< table
->class->n_columns
; i
++) {
205 const struct ovsdb_idl_column
*column
= &table
->class->columns
[i
];
206 unsigned int score
= score_partial_match(column
->name
, column_name
);
207 if (score
> best_score
) {
210 } else if (score
== best_score
) {
215 *columnp
= best_match
;
218 } else if (best_score
) {
219 return xasprintf("%s contains more than one column whose name "
220 "matches \"%s\"", table
->class->name
, column_name
);
222 return xasprintf("%s does not contain a column whose name matches "
223 "\"%s\"", table
->class->name
, column_name
);
228 pre_get_column(struct ctl_context
*ctx
,
229 const struct ctl_table_class
*table
, const char *column_name
,
230 const struct ovsdb_idl_column
**columnp
)
232 die_if_error(get_column(table
, column_name
, columnp
));
233 ovsdb_idl_add_column(ctx
->idl
, *columnp
);
236 static const struct ctl_table_class
*
237 pre_get_table(struct ctl_context
*ctx
, const char *table_name
)
239 const struct ctl_table_class
*table_class
;
242 table_class
= get_table(table_name
);
243 ovsdb_idl_add_table(ctx
->idl
, table_class
->class);
245 for (i
= 0; i
< ARRAY_SIZE(table_class
->row_ids
); i
++) {
246 const struct ctl_row_id
*id
= &table_class
->row_ids
[i
];
248 ovsdb_idl_add_table(ctx
->idl
, id
->table
);
250 if (id
->name_column
) {
251 ovsdb_idl_add_column(ctx
->idl
, id
->name_column
);
253 if (id
->uuid_column
) {
254 ovsdb_idl_add_column(ctx
->idl
, id
->uuid_column
);
262 missing_operator_error(const char *arg
, const char **allowed_operators
,
268 ds_put_format(&s
, "%s: argument does not end in ", arg
);
269 ds_put_format(&s
, "\"%s\"", allowed_operators
[0]);
270 if (n_allowed
== 2) {
271 ds_put_format(&s
, " or \"%s\"", allowed_operators
[1]);
272 } else if (n_allowed
> 2) {
275 for (i
= 1; i
< n_allowed
- 1; i
++) {
276 ds_put_format(&s
, ", \"%s\"", allowed_operators
[i
]);
278 ds_put_format(&s
, ", or \"%s\"", allowed_operators
[i
]);
280 ds_put_format(&s
, " followed by a value.");
282 return ds_steal_cstr(&s
);
285 /* Breaks 'arg' apart into a number of fields in the following order:
287 * - The name of a column in 'table', stored into '*columnp'. The column
288 * name may be abbreviated.
290 * - Optionally ':' followed by a key string. The key is stored as a
291 * malloc()'d string into '*keyp', or NULL if no key is present in
294 * - If 'valuep' is nonnull, an operator followed by a value string. The
295 * allowed operators are the 'n_allowed' string in 'allowed_operators',
296 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
297 * index of the operator within 'allowed_operators' is stored into
298 * '*operatorp'. The value is stored as a malloc()'d string into
299 * '*valuep', or NULL if no value is present in 'arg'.
301 * On success, returns NULL. On failure, returned a malloc()'d string error
302 * message and stores NULL into all of the nonnull output arguments. */
303 static char * OVS_WARN_UNUSED_RESULT
304 parse_column_key_value(const char *arg
,
305 const struct ctl_table_class
*table
,
306 const struct ovsdb_idl_column
**columnp
, char **keyp
,
308 const char **allowed_operators
, size_t n_allowed
,
315 ovs_assert(!(operatorp
&& !valuep
));
321 /* Parse column name. */
322 error
= ovsdb_token_parse(&p
, &column_name
);
326 if (column_name
[0] == '\0') {
328 error
= xasprintf("%s: missing column name", arg
);
331 error
= get_column(table
, column_name
, columnp
);
337 /* Parse key string. */
340 error
= ovsdb_token_parse(&p
, keyp
);
346 /* Parse value string. */
352 if (!allowed_operators
) {
353 static const char *equals
= "=";
354 allowed_operators
= &equals
;
360 for (i
= 0; i
< n_allowed
; i
++) {
361 const char *op
= allowed_operators
[i
];
362 size_t op_len
= strlen(op
);
364 if (op_len
> best_len
&& !strncmp(op
, p
, op_len
) && p
[op_len
]) {
370 error
= missing_operator_error(arg
, allowed_operators
, n_allowed
);
377 *valuep
= xstrdup(p
+ best_len
);
380 error
= xasprintf("%s: trailing garbage \"%s\" in argument",
401 static const struct ovsdb_idl_column
*
402 pre_parse_column_key_value(struct ctl_context
*ctx
,
404 const struct ctl_table_class
*table
)
406 const struct ovsdb_idl_column
*column
;
411 die_if_error(ovsdb_token_parse(&p
, &column_name
));
412 if (column_name
[0] == '\0') {
413 ctl_fatal("%s: missing column name", arg
);
416 pre_get_column(ctx
, table
, column_name
, &column
);
423 check_mutable(const struct ovsdb_idl_row
*row
,
424 const struct ovsdb_idl_column
*column
)
426 if (!ovsdb_idl_is_mutable(row
, column
)) {
427 ctl_fatal("cannot modify read-only column %s in table %s",
428 column
->name
, row
->table
->class->name
);
433 RELOP(RELOP_EQ, "=") \
434 RELOP(RELOP_NE, "!=") \
435 RELOP(RELOP_LT, "<") \
436 RELOP(RELOP_GT, ">") \
437 RELOP(RELOP_LE, "<=") \
438 RELOP(RELOP_GE, ">=") \
439 RELOP(RELOP_SET_EQ, "{=}") \
440 RELOP(RELOP_SET_NE, "{!=}") \
441 RELOP(RELOP_SET_LT, "{<}") \
442 RELOP(RELOP_SET_GT, "{>}") \
443 RELOP(RELOP_SET_LE, "{<=}") \
444 RELOP(RELOP_SET_GE, "{>=}")
447 #define RELOP(ENUM, STRING) ENUM,
453 is_set_operator(enum relop op
)
455 return (op
== RELOP_SET_EQ
|| op
== RELOP_SET_NE
||
456 op
== RELOP_SET_LT
|| op
== RELOP_SET_GT
||
457 op
== RELOP_SET_LE
|| op
== RELOP_SET_GE
);
461 evaluate_relop(const struct ovsdb_datum
*a
, const struct ovsdb_datum
*b
,
462 const struct ovsdb_type
*type
, enum relop op
)
467 return ovsdb_datum_compare_3way(a
, b
, type
) == 0;
470 return ovsdb_datum_compare_3way(a
, b
, type
) != 0;
472 return ovsdb_datum_compare_3way(a
, b
, type
) < 0;
474 return ovsdb_datum_compare_3way(a
, b
, type
) > 0;
476 return ovsdb_datum_compare_3way(a
, b
, type
) <= 0;
478 return ovsdb_datum_compare_3way(a
, b
, type
) >= 0;
481 return b
->n
> a
->n
&& ovsdb_datum_includes_all(a
, b
, type
);
483 return a
->n
> b
->n
&& ovsdb_datum_includes_all(b
, a
, type
);
485 return ovsdb_datum_includes_all(a
, b
, type
);
487 return ovsdb_datum_includes_all(b
, a
, type
);
495 is_condition_satisfied(const struct ctl_table_class
*table
,
496 const struct ovsdb_idl_row
*row
, const char *arg
,
497 struct ovsdb_symbol_table
*symtab
)
499 static const char *operators
[] = {
500 #define RELOP(ENUM, STRING) STRING,
505 const struct ovsdb_idl_column
*column
;
506 const struct ovsdb_datum
*have_datum
;
507 char *key_string
, *value_string
;
508 struct ovsdb_type type
;
513 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
514 &operator, operators
, ARRAY_SIZE(operators
),
518 ctl_fatal("%s: missing value", arg
);
522 type
.n_max
= UINT_MAX
;
524 have_datum
= ovsdb_idl_read(row
, column
);
526 union ovsdb_atom want_key
;
527 struct ovsdb_datum b
;
530 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
531 ctl_fatal("cannot specify key to check for non-map column %s",
535 die_if_error(ovsdb_atom_from_string(&want_key
, &column
->type
.key
,
536 key_string
, symtab
));
538 type
.key
= type
.value
;
539 type
.value
.type
= OVSDB_TYPE_VOID
;
540 die_if_error(ovsdb_datum_from_string(&b
, &type
, value_string
, symtab
));
542 idx
= ovsdb_datum_find_key(have_datum
,
543 &want_key
, column
->type
.key
.type
);
544 if (idx
== UINT_MAX
&& !is_set_operator(operator)) {
547 struct ovsdb_datum a
;
549 if (idx
!= UINT_MAX
) {
551 a
.keys
= &have_datum
->values
[idx
];
559 retval
= evaluate_relop(&a
, &b
, &type
, operator);
562 ovsdb_atom_destroy(&want_key
, column
->type
.key
.type
);
563 ovsdb_datum_destroy(&b
, &type
);
565 struct ovsdb_datum want_datum
;
567 die_if_error(ovsdb_datum_from_string(&want_datum
, &column
->type
,
568 value_string
, symtab
));
569 retval
= evaluate_relop(have_datum
, &want_datum
, &type
, operator);
570 ovsdb_datum_destroy(&want_datum
, &column
->type
);
580 invalidate_cache(struct ctl_context
*ctx
)
582 if (ctx
->invalidate_cache
) {
583 (ctx
->invalidate_cache
)(ctx
);
588 pre_cmd_get(struct ctl_context
*ctx
)
590 const char *id
= shash_find_data(&ctx
->options
, "--id");
591 const char *table_name
= ctx
->argv
[1];
592 const struct ctl_table_class
*table
;
595 /* Using "get" without --id or a column name could possibly make sense.
596 * Maybe, for example, a *ctl command run wants to assert that a row
597 * exists. But it is unlikely that an interactive user would want to do
598 * that, so issue a warning if we're running on a terminal. */
599 if (!id
&& ctx
->argc
<= 3 && isatty(STDOUT_FILENO
)) {
600 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
601 "possibly erroneous");
604 table
= pre_get_table(ctx
, table_name
);
605 for (i
= 3; i
< ctx
->argc
; i
++) {
606 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
607 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
611 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
616 cmd_get(struct ctl_context
*ctx
)
618 const char *id
= shash_find_data(&ctx
->options
, "--id");
619 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
620 const char *table_name
= ctx
->argv
[1];
621 const char *record_id
= ctx
->argv
[2];
622 const struct ctl_table_class
*table
;
623 const struct ovsdb_idl_row
*row
;
624 struct ds
*out
= &ctx
->output
;
627 if (id
&& !must_exist
) {
628 ctl_fatal("--if-exists and --id may not be specified together");
631 table
= get_table(table_name
);
632 row
= get_row(ctx
, table
, record_id
, must_exist
);
638 struct ovsdb_symbol
*symbol
;
641 symbol
= create_symbol(ctx
->symtab
, id
, &new);
643 ctl_fatal("row id \"%s\" specified on \"get\" command was used "
644 "before it was defined", id
);
646 symbol
->uuid
= row
->uuid
;
648 /* This symbol refers to a row that already exists, so disable warnings
649 * about it being unreferenced. */
650 symbol
->strong_ref
= true;
652 for (i
= 3; i
< ctx
->argc
; i
++) {
653 const struct ovsdb_idl_column
*column
;
654 const struct ovsdb_datum
*datum
;
657 /* Special case for obtaining the UUID of a row. We can't just do this
658 * through parse_column_key_value() below since it returns a "struct
659 * ovsdb_idl_column" and the UUID column doesn't have one. */
660 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
661 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
662 ds_put_format(out
, UUID_FMT
"\n", UUID_ARGS(&row
->uuid
));
666 die_if_error(parse_column_key_value(ctx
->argv
[i
], table
,
667 &column
, &key_string
,
668 NULL
, NULL
, 0, NULL
));
670 ovsdb_idl_txn_verify(row
, column
);
671 datum
= ovsdb_idl_read(row
, column
);
673 union ovsdb_atom key
;
676 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
677 ctl_fatal("cannot specify key to get for non-map column %s",
681 die_if_error(ovsdb_atom_from_string(&key
,
683 key_string
, ctx
->symtab
));
685 idx
= ovsdb_datum_find_key(datum
, &key
,
686 column
->type
.key
.type
);
687 if (idx
== UINT_MAX
) {
689 ctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
690 key_string
, table
->class->name
, record_id
,
694 ovsdb_atom_to_string(&datum
->values
[idx
],
695 column
->type
.value
.type
, out
);
697 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
699 ovsdb_datum_to_string(datum
, &column
->type
, out
);
701 ds_put_char(out
, '\n');
708 parse_column_names(const char *column_names
,
709 const struct ctl_table_class
*table
,
710 const struct ovsdb_idl_column
***columnsp
,
713 const struct ovsdb_idl_column
**columns
;
719 n_columns
= table
->class->n_columns
+ 1;
720 columns
= xmalloc(n_columns
* sizeof *columns
);
722 for (i
= 0; i
< table
->class->n_columns
; i
++) {
723 columns
[i
+ 1] = &table
->class->columns
[i
];
726 char *s
= xstrdup(column_names
);
727 size_t allocated_columns
;
728 char *save_ptr
= NULL
;
732 allocated_columns
= n_columns
= 0;
733 for (column_name
= strtok_r(s
, ", ", &save_ptr
); column_name
;
734 column_name
= strtok_r(NULL
, ", ", &save_ptr
)) {
735 const struct ovsdb_idl_column
*column
;
737 if (!strcasecmp(column_name
, "_uuid")) {
740 die_if_error(get_column(table
, column_name
, &column
));
742 if (n_columns
>= allocated_columns
) {
743 columns
= x2nrealloc(columns
, &allocated_columns
,
746 columns
[n_columns
++] = column
;
751 ctl_fatal("must specify at least one column name");
755 *n_columnsp
= n_columns
;
759 pre_list_columns(struct ctl_context
*ctx
,
760 const struct ctl_table_class
*table
,
761 const char *column_names
)
763 const struct ovsdb_idl_column
**columns
;
767 parse_column_names(column_names
, table
, &columns
, &n_columns
);
768 for (i
= 0; i
< n_columns
; i
++) {
770 ovsdb_idl_add_column(ctx
->idl
, columns
[i
]);
777 pre_cmd_list(struct ctl_context
*ctx
)
779 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
780 const char *table_name
= ctx
->argv
[1];
781 const struct ctl_table_class
*table
;
783 table
= pre_get_table(ctx
, table_name
);
784 pre_list_columns(ctx
, table
, column_names
);
787 static struct table
*
788 list_make_table(const struct ovsdb_idl_column
**columns
, size_t n_columns
)
793 out
= xmalloc(sizeof *out
);
796 for (i
= 0; i
< n_columns
; i
++) {
797 const struct ovsdb_idl_column
*column
= columns
[i
];
798 const char *column_name
= column
? column
->name
: "_uuid";
800 table_add_column(out
, "%s", column_name
);
807 list_record(const struct ovsdb_idl_row
*row
,
808 const struct ovsdb_idl_column
**columns
, size_t n_columns
,
818 for (i
= 0; i
< n_columns
; i
++) {
819 const struct ovsdb_idl_column
*column
= columns
[i
];
820 struct cell
*cell
= table_add_cell(out
);
823 struct ovsdb_datum datum
;
824 union ovsdb_atom atom
;
826 atom
.uuid
= row
->uuid
;
832 cell
->json
= ovsdb_datum_to_json(&datum
, &ovsdb_type_uuid
);
833 cell
->type
= &ovsdb_type_uuid
;
835 const struct ovsdb_datum
*datum
= ovsdb_idl_read(row
, column
);
837 cell
->json
= ovsdb_datum_to_json(datum
, &column
->type
);
838 cell
->type
= &column
->type
;
844 cmd_list(struct ctl_context
*ctx
)
846 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
847 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
848 const struct ovsdb_idl_column
**columns
;
849 const char *table_name
= ctx
->argv
[1];
850 const struct ctl_table_class
*table
;
855 table
= get_table(table_name
);
856 parse_column_names(column_names
, table
, &columns
, &n_columns
);
857 out
= ctx
->table
= list_make_table(columns
, n_columns
);
859 for (i
= 2; i
< ctx
->argc
; i
++) {
860 list_record(get_row(ctx
, table
, ctx
->argv
[i
], must_exist
),
861 columns
, n_columns
, out
);
864 const struct ovsdb_idl_row
*row
;
866 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
->class); row
!= NULL
;
867 row
= ovsdb_idl_next_row(row
)) {
868 list_record(row
, columns
, n_columns
, out
);
875 pre_cmd_find(struct ctl_context
*ctx
)
877 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
878 const char *table_name
= ctx
->argv
[1];
879 const struct ctl_table_class
*table
;
882 table
= pre_get_table(ctx
, table_name
);
883 pre_list_columns(ctx
, table
, column_names
);
884 for (i
= 2; i
< ctx
->argc
; i
++) {
885 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
890 cmd_find(struct ctl_context
*ctx
)
892 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
893 const struct ovsdb_idl_column
**columns
;
894 const char *table_name
= ctx
->argv
[1];
895 const struct ctl_table_class
*table
;
896 const struct ovsdb_idl_row
*row
;
900 table
= get_table(table_name
);
901 parse_column_names(column_names
, table
, &columns
, &n_columns
);
902 out
= ctx
->table
= list_make_table(columns
, n_columns
);
903 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
->class); row
;
904 row
= ovsdb_idl_next_row(row
)) {
907 for (i
= 2; i
< ctx
->argc
; i
++) {
908 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
],
913 list_record(row
, columns
, n_columns
, out
);
921 pre_cmd_set(struct ctl_context
*ctx
)
923 const char *table_name
= ctx
->argv
[1];
924 const struct ctl_table_class
*table
;
927 table
= pre_get_table(ctx
, table_name
);
928 for (i
= 3; i
< ctx
->argc
; i
++) {
929 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
934 cmd_set(struct ctl_context
*ctx
)
936 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
937 const char *table_name
= ctx
->argv
[1];
938 const char *record_id
= ctx
->argv
[2];
939 const struct ctl_table_class
*table
;
940 const struct ovsdb_idl_row
*row
;
943 table
= get_table(table_name
);
944 row
= get_row(ctx
, table
, record_id
, must_exist
);
949 for (i
= 3; i
< ctx
->argc
; i
++) {
950 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
953 invalidate_cache(ctx
);
957 pre_cmd_add(struct ctl_context
*ctx
)
959 const char *table_name
= ctx
->argv
[1];
960 const char *column_name
= ctx
->argv
[3];
961 const struct ctl_table_class
*table
;
962 const struct ovsdb_idl_column
*column
;
964 table
= pre_get_table(ctx
, table_name
);
965 pre_get_column(ctx
, table
, column_name
, &column
);
969 cmd_add(struct ctl_context
*ctx
)
971 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
972 const char *table_name
= ctx
->argv
[1];
973 const char *record_id
= ctx
->argv
[2];
974 const char *column_name
= ctx
->argv
[3];
975 const struct ctl_table_class
*table
;
976 const struct ovsdb_idl_column
*column
;
977 const struct ovsdb_idl_row
*row
;
978 const struct ovsdb_type
*type
;
979 struct ovsdb_datum old
;
982 table
= get_table(table_name
);
983 die_if_error(get_column(table
, column_name
, &column
));
984 row
= get_row(ctx
, table
, record_id
, must_exist
);
988 check_mutable(row
, column
);
990 type
= &column
->type
;
991 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
992 for (i
= 4; i
< ctx
->argc
; i
++) {
993 struct ovsdb_type add_type
;
994 struct ovsdb_datum add
;
998 add_type
.n_max
= UINT_MAX
;
999 die_if_error(ovsdb_datum_from_string(&add
, &add_type
, ctx
->argv
[i
],
1001 ovsdb_datum_union(&old
, &add
, type
, false);
1002 ovsdb_datum_destroy(&add
, type
);
1004 if (old
.n
> type
->n_max
) {
1005 ctl_fatal("\"add\" operation would put %u %s in column %s of "
1006 "table %s but the maximum number is %u",
1008 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
1009 column
->name
, table
->class->name
, type
->n_max
);
1011 ovsdb_idl_txn_verify(row
, column
);
1012 ovsdb_idl_txn_write(row
, column
, &old
);
1014 invalidate_cache(ctx
);
1018 pre_cmd_remove(struct ctl_context
*ctx
)
1020 const char *table_name
= ctx
->argv
[1];
1021 const char *column_name
= ctx
->argv
[3];
1022 const struct ctl_table_class
*table
;
1023 const struct ovsdb_idl_column
*column
;
1025 table
= pre_get_table(ctx
, table_name
);
1026 pre_get_column(ctx
, table
, column_name
, &column
);
1030 cmd_remove(struct ctl_context
*ctx
)
1032 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1033 const char *table_name
= ctx
->argv
[1];
1034 const char *record_id
= ctx
->argv
[2];
1035 const char *column_name
= ctx
->argv
[3];
1036 const struct ctl_table_class
*table
;
1037 const struct ovsdb_idl_column
*column
;
1038 const struct ovsdb_idl_row
*row
;
1039 const struct ovsdb_type
*type
;
1040 struct ovsdb_datum old
;
1043 table
= get_table(table_name
);
1044 die_if_error(get_column(table
, column_name
, &column
));
1045 row
= get_row(ctx
, table
, record_id
, must_exist
);
1049 check_mutable(row
, column
);
1051 type
= &column
->type
;
1052 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
1053 for (i
= 4; i
< ctx
->argc
; i
++) {
1054 struct ovsdb_type rm_type
;
1055 struct ovsdb_datum rm
;
1060 rm_type
.n_max
= UINT_MAX
;
1061 error
= ovsdb_datum_from_string(&rm
, &rm_type
,
1062 ctx
->argv
[i
], ctx
->symtab
);
1065 if (ovsdb_type_is_map(&rm_type
)) {
1066 rm_type
.value
.type
= OVSDB_TYPE_VOID
;
1068 die_if_error(ovsdb_datum_from_string(
1069 &rm
, &rm_type
, ctx
->argv
[i
], ctx
->symtab
));
1071 ctl_fatal("%s", error
);
1074 ovsdb_datum_subtract(&old
, type
, &rm
, &rm_type
);
1075 ovsdb_datum_destroy(&rm
, &rm_type
);
1077 if (old
.n
< type
->n_min
) {
1078 ctl_fatal("\"remove\" operation would put %u %s in column %s of "
1079 "table %s but the minimum number is %u",
1081 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
1082 column
->name
, table
->class->name
, type
->n_min
);
1084 ovsdb_idl_txn_verify(row
, column
);
1085 ovsdb_idl_txn_write(row
, column
, &old
);
1087 invalidate_cache(ctx
);
1091 pre_cmd_clear(struct ctl_context
*ctx
)
1093 const char *table_name
= ctx
->argv
[1];
1094 const struct ctl_table_class
*table
;
1097 table
= pre_get_table(ctx
, table_name
);
1098 for (i
= 3; i
< ctx
->argc
; i
++) {
1099 const struct ovsdb_idl_column
*column
;
1101 pre_get_column(ctx
, table
, ctx
->argv
[i
], &column
);
1106 cmd_clear(struct ctl_context
*ctx
)
1108 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1109 const char *table_name
= ctx
->argv
[1];
1110 const char *record_id
= ctx
->argv
[2];
1111 const struct ctl_table_class
*table
;
1112 const struct ovsdb_idl_row
*row
;
1115 table
= get_table(table_name
);
1116 row
= get_row(ctx
, table
, record_id
, must_exist
);
1121 for (i
= 3; i
< ctx
->argc
; i
++) {
1122 const struct ovsdb_idl_column
*column
;
1123 const struct ovsdb_type
*type
;
1124 struct ovsdb_datum datum
;
1126 die_if_error(get_column(table
, ctx
->argv
[i
], &column
));
1127 check_mutable(row
, column
);
1129 type
= &column
->type
;
1130 if (type
->n_min
> 0) {
1131 ctl_fatal("\"clear\" operation cannot be applied to column %s "
1132 "of table %s, which is not allowed to be empty",
1133 column
->name
, table
->class->name
);
1136 ovsdb_datum_init_empty(&datum
);
1137 ovsdb_idl_txn_write(row
, column
, &datum
);
1140 invalidate_cache(ctx
);
1144 pre_create(struct ctl_context
*ctx
)
1146 const char *id
= shash_find_data(&ctx
->options
, "--id");
1147 const char *table_name
= ctx
->argv
[1];
1148 const struct ctl_table_class
*table
;
1150 table
= get_table(table_name
);
1151 if (!id
&& !table
->class->is_root
) {
1152 VLOG_WARN("applying \"create\" command to table %s without --id "
1153 "option will have no effect", table
->class->name
);
1158 cmd_create(struct ctl_context
*ctx
)
1160 const char *id
= shash_find_data(&ctx
->options
, "--id");
1161 const char *table_name
= ctx
->argv
[1];
1162 const struct ctl_table_class
*table
= get_table(table_name
);
1163 const struct ovsdb_idl_row
*row
;
1164 const struct uuid
*uuid
;
1168 struct ovsdb_symbol
*symbol
= create_symbol(ctx
->symtab
, id
, NULL
);
1169 if (table
->class->is_root
) {
1170 /* This table is in the root set, meaning that rows created in it
1171 * won't disappear even if they are unreferenced, so disable
1172 * warnings about that by pretending that there is a reference. */
1173 symbol
->strong_ref
= true;
1175 uuid
= &symbol
->uuid
;
1180 row
= ovsdb_idl_txn_insert(ctx
->txn
, table
->class, uuid
);
1181 for (i
= 2; i
< ctx
->argc
; i
++) {
1182 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
1184 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
1187 /* This function may be used as the 'postprocess' function for commands that
1188 * insert new rows into the database. It expects that the command's 'run'
1189 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
1190 * sole output. It replaces that output by the row's permanent UUID assigned
1191 * by the database server and appends a new-line.
1193 * Currently we use this only for "create", because the higher-level commands
1194 * are supposed to be independent of the actual structure of the vswitch
1197 post_create(struct ctl_context
*ctx
)
1199 const struct uuid
*real
;
1202 if (!uuid_from_string(&dummy
, ds_cstr(&ctx
->output
))) {
1205 real
= ovsdb_idl_txn_get_insert_uuid(ctx
->txn
, &dummy
);
1207 ds_clear(&ctx
->output
);
1208 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(real
));
1210 ds_put_char(&ctx
->output
, '\n');
1214 pre_cmd_destroy(struct ctl_context
*ctx
)
1216 const char *table_name
= ctx
->argv
[1];
1218 pre_get_table(ctx
, table_name
);
1222 cmd_destroy(struct ctl_context
*ctx
)
1224 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1225 bool delete_all
= shash_find(&ctx
->options
, "--all");
1226 const char *table_name
= ctx
->argv
[1];
1227 const struct ctl_table_class
*table
;
1230 table
= get_table(table_name
);
1232 if (delete_all
&& ctx
->argc
> 2) {
1233 ctl_fatal("--all and records argument should not be specified together");
1236 if (delete_all
&& !must_exist
) {
1237 ctl_fatal("--all and --if-exists should not be specified together");
1241 const struct ovsdb_idl_row
*row
;
1242 const struct ovsdb_idl_row
*next_row
;
1244 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
->class);
1246 next_row
= ovsdb_idl_next_row(row
);
1247 ovsdb_idl_txn_delete(row
);
1251 for (i
= 2; i
< ctx
->argc
; i
++) {
1252 const struct ovsdb_idl_row
*row
;
1254 row
= get_row(ctx
, table
, ctx
->argv
[i
], must_exist
);
1256 ovsdb_idl_txn_delete(row
);
1260 invalidate_cache(ctx
);
1264 pre_cmd_wait_until(struct ctl_context
*ctx
)
1266 const char *table_name
= ctx
->argv
[1];
1267 const struct ctl_table_class
*table
;
1270 table
= pre_get_table(ctx
, table_name
);
1272 for (i
= 3; i
< ctx
->argc
; i
++) {
1273 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1278 cmd_wait_until(struct ctl_context
*ctx
)
1280 const char *table_name
= ctx
->argv
[1];
1281 const char *record_id
= ctx
->argv
[2];
1282 const struct ctl_table_class
*table
;
1283 const struct ovsdb_idl_row
*row
;
1286 table
= get_table(table_name
);
1288 row
= get_row(ctx
, table
, record_id
, false);
1290 ctx
->try_again
= true;
1294 for (i
= 3; i
< ctx
->argc
; i
++) {
1295 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
], ctx
->symtab
)) {
1296 ctx
->try_again
= true;
1302 /* Parses one command. */
1304 parse_command(int argc
, char *argv
[], struct shash
*local_options
,
1305 struct ctl_command
*command
)
1307 const struct ctl_command_syntax
*p
;
1308 struct shash_node
*node
;
1312 shash_init(&command
->options
);
1313 shash_swap(local_options
, &command
->options
);
1314 for (i
= 0; i
< argc
; i
++) {
1315 const char *option
= argv
[i
];
1319 if (option
[0] != '-') {
1323 equals
= strchr(option
, '=');
1325 key
= xmemdup0(option
, equals
- option
);
1326 value
= xstrdup(equals
+ 1);
1328 key
= xstrdup(option
);
1332 if (shash_find(&command
->options
, key
)) {
1333 ctl_fatal("'%s' option specified multiple times", argv
[i
]);
1335 shash_add_nocopy(&command
->options
, key
, value
);
1338 ctl_fatal("missing command name (use --help for help)");
1341 p
= shash_find_data(&all_commands
, argv
[i
]);
1343 ctl_fatal("unknown command '%s'; use --help for help", argv
[i
]);
1346 SHASH_FOR_EACH (node
, &command
->options
) {
1347 const char *s
= strstr(p
->options
, node
->name
);
1348 int end
= s
? s
[strlen(node
->name
)] : EOF
;
1350 if (end
!= '=' && end
!= ',' && end
!= ' ' && end
!= '\0') {
1351 ctl_fatal("'%s' command has no '%s' option",
1352 argv
[i
], node
->name
);
1354 if ((end
== '=') != (node
->data
!= NULL
)) {
1356 ctl_fatal("missing argument to '%s' option on '%s' "
1357 "command", node
->name
, argv
[i
]);
1359 ctl_fatal("'%s' option on '%s' does not accept an "
1360 "argument", node
->name
, argv
[i
]);
1365 n_arg
= argc
- i
- 1;
1366 if (n_arg
< p
->min_args
) {
1367 ctl_fatal("'%s' command requires at least %d arguments",
1368 p
->name
, p
->min_args
);
1369 } else if (n_arg
> p
->max_args
) {
1372 for (j
= i
+ 1; j
< argc
; j
++) {
1373 if (argv
[j
][0] == '-') {
1374 ctl_fatal("'%s' command takes at most %d arguments "
1375 "(note that options must precede command "
1376 "names and follow a \"--\" argument)",
1377 p
->name
, p
->max_args
);
1381 ctl_fatal("'%s' command takes at most %d arguments",
1382 p
->name
, p
->max_args
);
1385 command
->syntax
= p
;
1386 command
->argc
= n_arg
+ 1;
1387 command
->argv
= &argv
[i
];
1391 /* Parses command-line input for commands. */
1392 struct ctl_command
*
1393 ctl_parse_commands(int argc
, char *argv
[], struct shash
*local_options
,
1394 size_t *n_commandsp
)
1396 struct ctl_command
*commands
;
1397 size_t n_commands
, allocated_commands
;
1401 n_commands
= allocated_commands
= 0;
1403 for (start
= i
= 0; i
<= argc
; i
++) {
1404 if (i
== argc
|| !strcmp(argv
[i
], "--")) {
1406 if (n_commands
>= allocated_commands
) {
1407 struct ctl_command
*c
;
1409 commands
= x2nrealloc(commands
, &allocated_commands
,
1411 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
1412 shash_moved(&c
->options
);
1415 parse_command(i
- start
, &argv
[start
], local_options
,
1416 &commands
[n_commands
++]);
1417 } else if (!shash_is_empty(local_options
)) {
1418 ctl_fatal("missing command name (use --help for help)");
1424 ctl_fatal("missing command name (use --help for help)");
1426 *n_commandsp
= n_commands
;
1430 /* Returns true if it looks like this set of arguments might modify the
1431 * database, otherwise false. (Not very smart, so it's prone to false
1434 ctl_might_write_to_db(char **argv
)
1436 for (; *argv
; argv
++) {
1437 const struct ctl_command_syntax
*p
= shash_find_data(&all_commands
, *argv
);
1438 if (p
&& p
->mode
== RW
) {
1446 ctl_fatal(const char *format
, ...)
1451 va_start(args
, format
);
1452 message
= xvasprintf(format
, args
);
1455 vlog_set_levels(&VLM_db_ctl_base
, VLF_CONSOLE
, VLL_OFF
);
1456 VLOG_ERR("%s", message
);
1457 ovs_error(0, "%s", message
);
1458 ctl_exit(EXIT_FAILURE
);
1461 /* Frees the current transaction and the underlying IDL and then calls
1464 * Freeing the transaction and the IDL is not strictly necessary, but it makes
1465 * for a clean memory leak report from valgrind in the normal case. That makes
1466 * it easier to notice real memory leaks. */
1468 ctl_exit(int status
)
1471 ovsdb_idl_txn_abort(the_idl_txn
);
1472 ovsdb_idl_txn_destroy(the_idl_txn
);
1474 ovsdb_idl_destroy(the_idl
);
1478 /* Comman database commands to be registered. */
1479 static const struct ctl_command_syntax db_ctl_commands
[] = {
1480 {"comment", 0, INT_MAX
, "[ARG]...", NULL
, NULL
, NULL
, "", RO
},
1481 {"get", 2, INT_MAX
, "TABLE RECORD [COLUMN[:KEY]]...",pre_cmd_get
, cmd_get
,
1482 NULL
, "--if-exists,--id=", RO
},
1483 {"list", 1, INT_MAX
, "TABLE [RECORD]...", pre_cmd_list
, cmd_list
, NULL
,
1484 "--if-exists,--columns=", RO
},
1485 {"find", 1, INT_MAX
, "TABLE [COLUMN[:KEY]=VALUE]...", pre_cmd_find
,
1486 cmd_find
, NULL
, "--columns=", RO
},
1487 {"set", 3, INT_MAX
, "TABLE RECORD COLUMN[:KEY]=VALUE...", pre_cmd_set
,
1488 cmd_set
, NULL
, "--if-exists", RW
},
1489 {"add", 4, INT_MAX
, "TABLE RECORD COLUMN [KEY=]VALUE...", pre_cmd_add
,
1490 cmd_add
, NULL
, "--if-exists", RW
},
1491 {"remove", 4, INT_MAX
, "TABLE RECORD COLUMN KEY|VALUE|KEY=VALUE...",
1492 pre_cmd_remove
, cmd_remove
, NULL
, "--if-exists", RW
},
1493 {"clear", 3, INT_MAX
, "TABLE RECORD COLUMN...", pre_cmd_clear
, cmd_clear
,
1494 NULL
, "--if-exists", RW
},
1495 {"create", 2, INT_MAX
, "TABLE COLUMN[:KEY]=VALUE...", pre_create
,
1496 cmd_create
, post_create
, "--id=", RW
},
1497 {"destroy", 1, INT_MAX
, "TABLE [RECORD]...", pre_cmd_destroy
, cmd_destroy
,
1498 NULL
, "--if-exists,--all", RW
},
1499 {"wait-until", 2, INT_MAX
, "TABLE RECORD [COLUMN[:KEY]=VALUE]...",
1500 pre_cmd_wait_until
, cmd_wait_until
, NULL
, "", RO
},
1501 {NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, RO
},
1504 /* Registers commands represented by 'struct ctl_command_syntax's to
1505 * 'all_commands'. The last element of 'commands' must be an all-NULL
1508 ctl_register_commands(const struct ctl_command_syntax
*commands
)
1510 const struct ctl_command_syntax
*p
;
1512 for (p
= commands
; p
->name
; p
++) {
1513 shash_add_assert(&all_commands
, p
->name
, p
);
1517 /* Registers the 'db_ctl_commands' to 'all_commands'. */
1521 ctl_register_commands(db_ctl_commands
);
1524 /* Returns 'all_commands'. */
1525 const struct shash
*
1526 ctl_get_all_commands(void)
1528 return &all_commands
;
1531 /* Returns the text for the database commands usage. */
1533 ctl_get_db_cmd_usage(void)
1535 return "Database commands:\n\
1536 list TBL [REC] list RECord (or all records) in TBL\n\
1537 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
1538 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
1539 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
1540 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
1541 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
1542 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
1543 create TBL COL[:KEY]=VALUE create and initialize new record\n\
1544 destroy TBL REC delete RECord from TBL\n\
1545 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
1546 Potentially unsafe database commands require --force option.\n";
1549 /* Initializes 'ctx' from 'command'. */
1551 ctl_context_init_command(struct ctl_context
*ctx
,
1552 struct ctl_command
*command
)
1554 ctx
->argc
= command
->argc
;
1555 ctx
->argv
= command
->argv
;
1556 ctx
->options
= command
->options
;
1558 ds_swap(&ctx
->output
, &command
->output
);
1559 ctx
->table
= command
->table
;
1560 ctx
->try_again
= false;
1563 /* Initializes the entire 'ctx'. */
1565 ctl_context_init(struct ctl_context
*ctx
, struct ctl_command
*command
,
1566 struct ovsdb_idl
*idl
, struct ovsdb_idl_txn
*txn
,
1567 struct ovsdb_symbol_table
*symtab
,
1568 void (*invalidate_cache
)(struct ctl_context
*))
1571 ctl_context_init_command(ctx
, command
);
1575 ctx
->symtab
= symtab
;
1576 ctx
->invalidate_cache
= invalidate_cache
;
1579 /* Completes processing of 'command' within 'ctx'. */
1581 ctl_context_done_command(struct ctl_context
*ctx
,
1582 struct ctl_command
*command
)
1584 ds_swap(&ctx
->output
, &command
->output
);
1585 command
->table
= ctx
->table
;
1588 /* Finishes up with 'ctx'.
1590 * If command is nonnull, first calls ctl_context_done_command() to complete
1591 * processing that command within 'ctx'. */
1593 ctl_context_done(struct ctl_context
*ctx
,
1594 struct ctl_command
*command
)
1597 ctl_context_done_command(ctx
, command
);
1599 invalidate_cache(ctx
);
1602 /* Finds and returns the "struct ctl_table_class *" with 'table_name' by
1603 * searching the 'tables'. */
1604 const struct ctl_table_class
*
1605 get_table(const char *table_name
)
1607 const struct ctl_table_class
*table
;
1608 const struct ctl_table_class
*best_match
= NULL
;
1609 unsigned int best_score
= 0;
1611 for (table
= tables
; table
->class; table
++) {
1612 unsigned int score
= score_partial_match(table
->class->name
,
1614 if (score
> best_score
) {
1617 } else if (score
== best_score
) {
1623 } else if (best_score
) {
1624 ctl_fatal("multiple table names match \"%s\"", table_name
);
1626 ctl_fatal("unknown table \"%s\"", table_name
);
1631 /* Sets the column of 'row' in 'table'. */
1633 set_column(const struct ctl_table_class
*table
,
1634 const struct ovsdb_idl_row
*row
, const char *arg
,
1635 struct ovsdb_symbol_table
*symtab
)
1637 const struct ovsdb_idl_column
*column
;
1638 char *key_string
, *value_string
;
1641 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
1642 NULL
, NULL
, 0, &value_string
);
1643 die_if_error(error
);
1644 if (!value_string
) {
1645 ctl_fatal("%s: missing value", arg
);
1647 check_mutable(row
, column
);
1650 union ovsdb_atom key
, value
;
1651 struct ovsdb_datum datum
;
1653 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
1654 ctl_fatal("cannot specify key to set for non-map column %s",
1658 die_if_error(ovsdb_atom_from_string(&key
, &column
->type
.key
,
1659 key_string
, symtab
));
1660 die_if_error(ovsdb_atom_from_string(&value
, &column
->type
.value
,
1661 value_string
, symtab
));
1663 ovsdb_datum_init_empty(&datum
);
1664 ovsdb_datum_add_unsafe(&datum
, &key
, &value
, &column
->type
);
1666 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
1667 ovsdb_atom_destroy(&value
, column
->type
.value
.type
);
1669 ovsdb_datum_union(&datum
, ovsdb_idl_read(row
, column
),
1670 &column
->type
, false);
1671 ovsdb_idl_txn_verify(row
, column
);
1672 ovsdb_idl_txn_write(row
, column
, &datum
);
1674 struct ovsdb_datum datum
;
1676 die_if_error(ovsdb_datum_from_string(&datum
, &column
->type
,
1677 value_string
, symtab
));
1678 ovsdb_idl_txn_write(row
, column
, &datum
);