From:  Arnoldo Lutz Guevara <arnoldo.lutz.guev...@hpe.com>

Generates and fill the default comparators for columns with
type int, real, string. Also creates the macros that allow
to iterate over the contents of the index, and perform
queries.

Signed-off-by: Arnoldo Lutz Guevara <arnoldo.lutz.guev...@hpe.com>
Signed-off-by: Esteban Rodriguez Betancourt <esteb...@hpe.com>
---
ovsdb/ovsdb-idlc.in     | 116 +++++++++++++++++++++
tests/idltest.ovsschema |   6 +-
tests/ovsdb-idl.at      | 267 ++++++++++++++++++++++++++++++++++++++++++++++++
tests/test-ovsdb.c      | 213 +++++++++++++++++++++++++++++++++++++-
4 files changed, 599 insertions(+), 3 deletions(-)

diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 26b0de4..38c0d51 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -8,9 +8,15 @@ import sys
import ovs.json
import ovs.db.error
import ovs.db.schema
+from ovs.db.types import StringType, IntegerType, RealType
 argv0 = sys.argv[0]
+def isColumnIndexable(column):
+    return not column.type.is_map()  and column.type.key.is_valid() \
+               and (column.type.is_scalar())  and \
+                column.type.key.toAtomicType() in ['OVSDB_TYPE_STRING', 
'OVSDB_TYPE_REAL', 'OVSDB_TYPE_INTEGER']
+
 def parseSchema(filename):
     return ovs.db.schema.IdlSchema.from_json(ovs.json.from_file(filename))
@@ -186,6 +192,25 @@ const struct %(s)s *%(s)s_track_get_next(const struct 
%(s)s *);
              (ROW); \\
              (ROW) = %(s)s_track_get_next(ROW))
+int %(s)s_index_compare(struct ovsdb_idl_index_cursor *, const struct %(s)s *, 
const struct %(s)s *);
+const struct %(s)s *%(s)s_index_first(struct ovsdb_idl_index_cursor *);
+const struct %(s)s *%(s)s_index_next(struct ovsdb_idl_index_cursor *);
+const struct %(s)s *%(s)s_index_find(struct ovsdb_idl_index_cursor *, const 
struct %(s)s *);
+const struct %(s)s *%(s)s_index_forward_to(struct ovsdb_idl_index_cursor *, 
const struct %(s)s *);
+const struct %(s)s *%(s)s_index_get_data(const struct ovsdb_idl_index_cursor 
*);
+#define %(S)s_FOR_EACH_RANGE(ROW, CURSOR, FROM, TO) \\
+        for ((ROW) = %(s)s_index_forward_to(CURSOR, FROM); \\
+             ((ROW) && %(s)s_index_compare(CURSOR, ROW, TO) <= 0); \\
+             (ROW) = %(s)s_index_next(CURSOR))
+#define %(S)s_FOR_EACH_EQUAL(ROW, CURSOR, KEY) \\
+        for ((ROW) = %(s)s_index_find(CURSOR, KEY); \\
+             ((ROW) && %(s)s_index_compare(CURSOR, ROW, KEY) == 0); \\
+             (ROW) = %(s)s_index_next(CURSOR))
+#define %(S)s_FOR_EACH_BYINDEX(ROW, CURSOR) \\
+        for ((ROW) = %(s)s_index_first(CURSOR); \\
+             (ROW); \\
+             (ROW) = %(s)s_index_next(CURSOR))
+
void %(s)s_init(struct %(s)s *);
void %(s)s_delete(const struct %(s)s *);
struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *);
@@ -216,6 +241,10 @@ bool %(s)s_is_updated(const struct %(s)s *, enum 
%(s)s_column_id);
             print '%s);' % ', '.join(args)
         print
+        for columnName, column in sorted(table.columns.iteritems()):
+            if isColumnIndexable(column):
+                print 'int %(s)s_index_%(c)s_cmp(const void *, const void *);' 
% {'s': structName, 'c': columnName}
+        print
     # Table indexes.
     printEnum("%stable_id" % prefix.lower(), ["%sTABLE_%s" % (prefix.upper(), 
tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % 
prefix.upper()])
@@ -746,7 +775,90 @@ const struct ovsdb_datum *
                    'S': structName.upper(),
                    'C': columnName.upper()}
             print "}"
+        # Column Index compare functions
+        for columnName, column in sorted(table.columns.iteritems()):
+            type = column.type
+            funcDict = {'OVSDB_TYPE_STRING': 'str', 'OVSDB_TYPE_REAL': 
'double', 'OVSDB_TYPE_INTEGER': 'int'}
+            if isColumnIndexable(column):
+                print '''
+/*  Call an internal function defined to compare  "%(f)s" type columns for 
"%(c)s" columns
+    in "%(s)s" tables.
+    Parameters: void *row1, void * row2. Data to be compared. Must be of type 
corresponding the record of
+    the table.
+    Return value: 0 if both data values are equal, -1 if first parameter is 
less than second and 1 otherwise.
+    For internal use only. Not recomended to be called directly. */ ''' % {'s' 
: structName, 'c' : columnName, 'f': type.key.toAtomicType()}
+                print 'int'
+                print '%(s)s_index_%(c)s_cmp(const void *row1, const void 
*row2)' % \
+                    {'s': structName, 'c': columnName}
+                print '{'
+                print '    struct %(s)s *data1 = (struct %(s)s *)row1;' % { 
's' : structName }
+                print '    struct %(s)s *data2 = (struct %(s)s *)row2;' % { 
's' : structName }
+                print '    return ovsdb_idl_index_%(f)scmp(data1->%(c)s, 
data2->%(c)s);' % \
+                    {'c': columnName, 'f': funcDict[type.key.toAtomicType()] }
+                print "}"
+# Index table related functions
+        print '''
+/*  This function is used to compare "%(s)s" records on table in iterartion 
loops for compound-index operations.
+    After been called, cursor point to current position in the index
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+                const struct "%(s)s" *const_data1,  const struct "%(s)s" 
*const_data2. Data to be compared.
+    Return value: 0 if both data values are equal, -1 if first parameter is 
less than second and 1 otherwise. */''' % {'s' : structName}
+        print 'int'
+        print '''%(s)s_index_compare(struct ovsdb_idl_index_cursor *cursor, 
const struct %(s)s *const_data1,  const struct %(s)s *const_data2)
+{
+    struct %(s)s *data1 = CONST_CAST(struct %(s)s *, const_data1);
+    struct %(s)s *data2 = CONST_CAST(struct %(s)s *, const_data2);
+    return ovsdb_idl_index_compare(cursor, &data1->header_, &data2->header_);
+}''' % { 's' : structName }
+        print '''
+/*  This function is called to position the cursor at the first row in "%(s)s" 
table on the associated compound-index.
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+    Return value: The first row in the corresponding index. */''' %  {'s' : 
structName }
+        print '''const struct %(s)s *\n%(s)s_index_first(struct 
ovsdb_idl_index_cursor *cursor)
+{
+    return %(s)s_cast(ovsdb_idl_index_first(cursor));
+}''' % { 's' : structName }
+        print '''
+/*  This function is called to position the cursor at the next row in "%(s)s" 
table on the associated compound-index.
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+    Return value: The next row in the corresponding index. */''' %  {'s' : 
structName, 'c' : columnName }
+        print '''const struct %(s)s *\n%(s)s_index_next(struct 
ovsdb_idl_index_cursor *cursor)
+{
+    return %(s)s_cast(ovsdb_idl_index_next(cursor));
+}''' % { 's' : structName }
+        print '''
+/*  This function is used to find the data of the row in "%(s)s" table that 
meet criteria with the requested data
+    associated in the compound-index.
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+                const struct %(s)s *const_data. Data to be searched.
+    Return value: The row in the corresponding index if found or NULL 
otherwise. */''' %  {'s' : structName }
+        print '''const struct %(s)s *\n%(s)s_index_find(struct 
ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data)
+{
+    struct %(s)s *data = CONST_CAST(struct %(s)s *, const_data);
+    return %(s)s_cast(ovsdb_idl_index_find(cursor, &data->header_));
+}''' % { 's' : structName }
+        print '''
+/*  This function is used to set the cursor pointing to the row in "%(s)s" 
table that meet criteria of the requested data
+    associated in the compound-index.
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+                const struct %(s)s *const_data. Data to be searched.
+    Return value: The row in the corresponding index closest to the criteria. 
*/''' %  {'s' : structName }
+        print '''const struct %(s)s *\n%(s)s_index_forward_to(struct 
ovsdb_idl_index_cursor *cursor, const struct %(s)s *const_data)
+{
+    struct %(s)s *data = CONST_CAST(struct %(s)s *, const_data);
+    return %(s)s_cast(ovsdb_idl_index_forward_to(cursor, &data->header_));
+}''' % { 's' : structName }
+        print '''
+/*  This function is used to get the data of the row in the current position 
pointed by the cursor in
+    "%(s)s" table.
+    Parameters: struct ovsdb_idl_index_cursor *cursor. Cursor used to iterate 
over the indexed data on this table.
+    Return value: The row in the corresponding index if found or NULL 
otherwise. */''' %  {'s' : structName, 'c' : columnName }
+        print '''const struct %(s)s *\n%(s)s_index_get_data(const struct 
ovsdb_idl_index_cursor *cursor)
+{
+    return %(s)s_cast(ovsdb_idl_index_data(CONST_CAST(struct 
ovsdb_idl_index_cursor*, cursor)));
+}''' % { 's' : structName }
+# End Index table related functions
         # Table columns.
         print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
             structName, structName.upper())
@@ -770,6 +882,10 @@ static void\n%s_columns_init(void)
             print "    c->mutable = %s;" % mutable
             print "    c->parse = %(s)s_parse_%(c)s;" % d
             print "    c->unparse = %(s)s_unparse_%(c)s;" % d
+            if isColumnIndexable(column):
+                print '    c->compare = %(s)s_index_%(c)s_cmp;' % d
+            else:
+                print '    c->compare = NULL;'
         print "}"
     # Table classes.
diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema
index 1d073aa..6c7f8a9 100644
--- a/tests/idltest.ovsschema
+++ b/tests/idltest.ovsschema
@@ -34,7 +34,8 @@
             "min": 0
           }
         }
-      }
+      },
+      "isRoot":true
     },
     "link2": {
       "columns": {
@@ -104,7 +105,8 @@
             "min": 0
           }
         }
-      }
+      },
+      "isRoot":true
     }
   }
}
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 33d508c..3773c43 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -800,3 +800,270 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially 
empty, various ops],
014: updated columns: ba i ia r ra s
015: done
]])
+
+# Tests to verify the functionality of the one column compound index.
+# It tests index for one column string and integer indexes.
+# The run of test-ovsdb generates the output of the display of data using the 
different indexes defined in
+# the program.
+# Then, some at_checks are used to verify the correctness of the corresponding 
index as well as the existence
+# of all the rows involved in the test.
+m4_define([OVSDB_CHECK_IDL_COMPOUND_INDEX_SINGLE_COLUMN_C],
+  [AT_SETUP([$1 - C])
+   AT_KEYWORDS([ovsdb server idl compound_index_single_column compound_index 
positive $5])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach 
--no-chdir --pidfile="`pwd`"/pid --remote=punix:socket 
--unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   m4_if([$2], [], [],
+     [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], 
[ignore], [kill `cat pid`])])
+# Generate the data to be tested.
+   AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c 
idl-compound-index unix:socket $3],
+            [0], [stdout], [ignore], [kill `cat pid`])
+# Filter the rows of data that corresponds to the string index eliminating the 
extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected 
order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sed -e 's/ i=.*//g']],
+            [0], [$4], [], [kill `cat pid`])
+# Here, the data is filtered and sorted in order to have all the rows in the 
index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sort -k 1,1n -k 2,2 
-k 3,3]],
+            [0], [$5], [], [kill `cat pid`])
+# Filter the rows of data that corresponds to the integer index eliminating 
the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected 
order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sed -e 's/ s=.*//g']],
+            [0], [$6], [], [kill `cat pid`])
+# Here again, the data is filtered and sorted in order to have all the rows in 
the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sort -k 1,1n -k 2,2 
-k 3,3]],
+            [0], [$7], [], [kill `cat pid`])
+   OVSDB_SERVER_SHUTDOWN
+   AT_CLEANUP])
+
+OVSDB_CHECK_IDL_COMPOUND_INDEX_SINGLE_COLUMN_C([Compound_index, single column 
test ],
+    [['["idltest",
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 1, 
"b":true, "r":101.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 2, 
"b":false, "r":102.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 10, 
"b":true, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 1, 
"b":false, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, 
"b":true, "r":120.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, 
"b":true, "r":122.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 4, 
"b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List005", "i": 5, 
"b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 20, 
"b":true, "r":220.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 19, 
"b":true, "r":219.0}}
+      ]']],
+    [idl_compound_index_single_column],
+    [001: s=List000
+001: s=List000
+001: s=List000
+001: s=List001
+001: s=List001
+001: s=List001
+001: s=List001
+001: s=List005
+001: s=List020
+001: s=List020
+003: s=List001
+003: s=List001
+003: s=List001
+003: s=List001
+],
+[001: s=List000 i=1 b=True r=101.000000
+001: s=List000 i=10 b=True r=110.000000
+001: s=List000 i=2 b=False r=102.000000
+001: s=List001 i=1 b=False r=110.000000
+001: s=List001 i=2 b=True r=120.000000
+001: s=List001 i=2 b=True r=122.000000
+001: s=List001 i=4 b=True r=130.000000
+001: s=List005 i=5 b=True r=130.000000
+001: s=List020 i=19 b=True r=219.000000
+001: s=List020 i=20 b=True r=220.000000
+003: s=List001 i=1 b=False r=110.000000
+003: s=List001 i=2 b=True r=120.000000
+003: s=List001 i=2 b=True r=122.000000
+003: s=List001 i=4 b=True r=130.000000
+],
+[002: i=1
+002: i=1
+002: i=2
+002: i=2
+002: i=2
+002: i=4
+002: i=5
+002: i=10
+002: i=19
+002: i=20
+004: i=5
+005: i=4
+005: i=5
+006: i=5
+006: i=10
+006: i=19
+006: i=20
+006: i=54
+],
+[002: i=1 s=List000 b=True r=101.000000
+002: i=1 s=List001 b=False r=110.000000
+002: i=10 s=List000 b=True r=110.000000
+002: i=19 s=List020 b=True r=219.000000
+002: i=2 s=List000 b=False r=102.000000
+002: i=2 s=List001 b=True r=120.000000
+002: i=2 s=List001 b=True r=122.000000
+002: i=20 s=List020 b=True r=220.000000
+002: i=4 s=List001 b=True r=130.000000
+002: i=5 s=List005 b=True r=130.000000
+004: i=5 s=List005 b=True r=130.000000
+005: i=4 s=List001 b=True r=130.000000
+005: i=5 s=List005 b=True r=130.000000
+006: i=10 s=List000 b=True r=110.000000
+006: i=19 s=List020 b=True r=219.000000
+006: i=20 s=List020 b=True r=220.000000
+006: i=5 s=List005 b=True r=130.000000
+006: i=54 s=Lista054 b=False r=0.000000
+])
+
+# Tests to verify the functionality of two column compound index.
+# It tests index for two columns using string and integer fields.
+# The run of test-ovsdb generates the output of the display of data using the 
different indexes defined in
+# the program.
+# Then, some at_checks are used to verify the correctness of the corresponding 
index as well as the existence
+# of all the rows involved in the test.
+m4_define([OVSDB_CHECK_IDL_COMPOUND_INDEX_DOUBLE_COLUMN_C],
+  [AT_SETUP([$1 - C])
+   AT_KEYWORDS([ovsdb server idl compound_index_double_column compound_index 
positive $5])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach 
--no-chdir --pidfile="`pwd`"/pid --remote=punix:socket 
--unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   m4_if([$2], [], [],
+     [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], 
[ignore], [kill `cat pid`])])
+# Generate the data to be tested.
+   AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c 
idl-compound-index unix:socket $3],
+            [0], [stdout], [ignore], [kill `cat pid`])
+# Filter the rows of data that corresponds to the string-integer index 
eliminating the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected 
order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sed -e 's/ b=.*//g']],
+            [0], [$4], [], [kill `cat pid`])
+# Here, the data is filtered and sorted in order to have all the rows in the 
index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sort -k 1,1n -k 2,2 
-k 3,3]],
+            [0], [$5], [], [kill `cat pid`])
+# Filter the rows of data that corresponds to the integer index eliminating 
the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected 
order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sed -e 's/ b=.*//g']],
+            [0], [$6], [], [kill `cat pid`])
+# Here again, the data is filtered and sorted in order to have all the rows in 
the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sort -k 1,1n -k 2,2 
-k 3,3]],
+            [0], [$7], [], [kill `cat pid`])
+   OVSDB_SERVER_SHUTDOWN
+   AT_CLEANUP])
+
+OVSDB_CHECK_IDL_COMPOUND_INDEX_DOUBLE_COLUMN_C([Compound_index, double column 
test ],
+    [['["idltest",
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 1, 
"b":true, "r":101.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 2, 
"b":false, "r":102.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 10, 
"b":true, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 1, 
"b":false, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, 
"b":true, "r":120.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, 
"b":true, "r":122.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 4, 
"b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List005", "i": 5, 
"b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 20, 
"b":true, "r":220.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 19, 
"b":true, "r":219.0}}
+      ]']],
+    [idl_compound_index_double_column],
+    [001: s=List000 i=1
+001: s=List000 i=2
+001: s=List000 i=10
+001: s=List001 i=1
+001: s=List001 i=2
+001: s=List001 i=2
+001: s=List001 i=4
+001: s=List005 i=5
+001: s=List020 i=19
+001: s=List020 i=20
+002: s=List000 i=10
+002: s=List000 i=2
+002: s=List000 i=1
+002: s=List001 i=4
+002: s=List001 i=2
+002: s=List001 i=2
+002: s=List001 i=1
+002: s=List005 i=5
+002: s=List020 i=20
+002: s=List020 i=19
+003: s=List000 i=10
+004: s=List001 i=1
+004: s=List001 i=2
+004: s=List001 i=2
+004: s=List001 i=4
+004: s=List005 i=5
+],
+    [001: s=List000 i=1 b=True r=101.000000
+001: s=List000 i=10 b=True r=110.000000
+001: s=List000 i=2 b=False r=102.000000
+001: s=List001 i=1 b=False r=110.000000
+001: s=List001 i=2 b=True r=120.000000
+001: s=List001 i=2 b=True r=122.000000
+001: s=List001 i=4 b=True r=130.000000
+001: s=List005 i=5 b=True r=130.000000
+001: s=List020 i=19 b=True r=219.000000
+001: s=List020 i=20 b=True r=220.000000
+002: s=List000 i=1 b=True r=101.000000
+002: s=List000 i=10 b=True r=110.000000
+002: s=List000 i=2 b=False r=102.000000
+002: s=List001 i=1 b=False r=110.000000
+002: s=List001 i=2 b=True r=120.000000
+002: s=List001 i=2 b=True r=122.000000
+002: s=List001 i=4 b=True r=130.000000
+002: s=List005 i=5 b=True r=130.000000
+002: s=List020 i=19 b=True r=219.000000
+002: s=List020 i=20 b=True r=220.000000
+003: s=List000 i=10 b=True r=110.000000
+004: s=List001 i=1 b=False r=110.000000
+004: s=List001 i=2 b=True r=120.000000
+004: s=List001 i=2 b=True r=122.000000
+004: s=List001 i=4 b=True r=130.000000
+004: s=List005 i=5 b=True r=130.000000
+],
+    [005: i=1 s=List000
+005: i=1 s=List001
+005: i=2 s=List000
+005: i=2 s=List001
+005: i=2 s=List001
+005: i=4 s=List001
+005: i=5 s=List005
+005: i=10 s=List000
+005: i=19 s=List020
+005: i=20 s=List020
+006: i=20 s=List020
+006: i=19 s=List020
+006: i=10 s=List000
+006: i=5 s=List005
+006: i=4 s=List001
+006: i=2 s=List000
+006: i=2 s=List001
+006: i=2 s=List001
+006: i=1 s=List000
+006: i=1 s=List001
+],
+    [005: i=1 s=List000 b=True r=101.000000
+005: i=1 s=List001 b=False r=110.000000
+005: i=10 s=List000 b=True r=110.000000
+005: i=19 s=List020 b=True r=219.000000
+005: i=2 s=List000 b=False r=102.000000
+005: i=2 s=List001 b=True r=120.000000
+005: i=2 s=List001 b=True r=122.000000
+005: i=20 s=List020 b=True r=220.000000
+005: i=4 s=List001 b=True r=130.000000
+005: i=5 s=List005 b=True r=130.000000
+006: i=1 s=List000 b=True r=101.000000
+006: i=1 s=List001 b=False r=110.000000
+006: i=10 s=List000 b=True r=110.000000
+006: i=19 s=List020 b=True r=219.000000
+006: i=2 s=List000 b=False r=102.000000
+006: i=2 s=List001 b=True r=120.000000
+006: i=2 s=List001 b=True r=122.000000
+006: i=20 s=List020 b=True r=220.000000
+006: i=4 s=List001 b=True r=130.000000
+006: i=5 s=List005 b=True r=130.000000
+])
+
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index e6af729..45d51b0 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -197,7 +197,14 @@ usage(void)
            "    connect to SERVER and dump the contents of the database\n"
            "    as seen initially by the IDL implementation and after\n"
            "    executing each TRANSACTION.  (Each TRANSACTION must modify\n"
-           "    the database or this command will hang.)\n",
+           "    the database or this command will hang.)\n"
+           "  idl-compound-index TEST_TO_EXECUTE\n"
+           "    Execute the tests to verify compound-index feature.\n"
+           "    The TEST_TO_EXECUTE are:\n"
+           "        idl_compound_index_single_column:\n"
+           "            test for indexes using one column as part of the 
index.\n"
+           "        idl_compound_index_double_column:\n"
+           "            test for indexes using two columns as part of 
index.\n",
            program_name, program_name);
     vlog_usage();
     printf("\nOther options:\n"
@@ -2178,6 +2185,209 @@ do_idl(struct ovs_cmdl_context *ctx)
     printf("%03d: done\n", step);
}
+static int
+test_idl_compound_index_single_column(struct ovsdb_idl *idl,
+        struct ovsdb_idl_index_cursor* sCursor,
+        struct ovsdb_idl_index_cursor* iCursor)
+{
+    const struct idltest_simple* myRow;
+    struct ovsdb_idl_txn *txn;
+    int step=0;
+
+     /* Display records by string index -> sCursor */
+     ++step;
+     IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, sCursor)
+     {
+         printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, 
myRow->i, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor */
+     ++step;
+     IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, iCursor)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  
myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by string index -> sCursor with filtering where 
s=\"List001\ */
+     ++step;
+     struct idltest_simple equal;
+     equal.s = "List001";
+     IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, sCursor, &equal)
+     {
+         printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, 
myRow->i, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor with filtering where i=5 */
+     ++step;
+     equal.i=5;
+     IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, iCursor, &equal) {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  
myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor in range i=[3,7] */
+     ++step;
+     struct idltest_simple from, to;
+     from.i = 3;
+     to.i = 7;
+     IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, iCursor, &from, &to)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  
myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Delete record i=4 and insert i=54 by integer index -> iCursor */
+     ++step;
+     struct idltest_simple toDelete, *toInsert;
+     toDelete.i = 4;
+     myRow = &toDelete;
+     myRow = idltest_simple_index_find(iCursor, myRow);
+     txn = ovsdb_idl_txn_create(idl);
+     idltest_simple_delete(myRow);
+     toInsert = idltest_simple_insert(txn);
+     idltest_simple_set_i(toInsert, 54);
+     idltest_simple_set_s(toInsert, "Lista054");
+     ovsdb_idl_txn_commit_block(txn);
+     ovsdb_idl_txn_destroy(txn);
+     to.i = 60;
+     IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, iCursor, &from, &to)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  myRow->i, 
myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     return step;
+}
+
+static int
+test_idl_compound_index_double_column(struct ovsdb_idl_index_cursor* siCursor,
+        struct ovsdb_idl_index_cursor* sidCursor,
+        struct ovsdb_idl_index_cursor* isCursor,
+        struct ovsdb_idl_index_cursor* idsCursor)
+{
+    const struct idltest_simple* myRow;
+    int step = 0;
+
+    /* Display records by string-integer index -> siCursor */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, siCursor)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, 
myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer(down order) index -> sidCursor */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, sidCursor)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, 
myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer index -> siCursor with filtering 
where s="List000" and i=10 */
+    step++;
+    struct idltest_simple equal;
+    equal.s = "List000";
+    equal.i = 10;
+    IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, siCursor, &equal)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, 
myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer index -> siCursor in range i=[0,100] 
and s=[\"List002\",\"List003\"] */
+    step++;
+    struct idltest_simple from, to;
+    from.i = 0;
+    from.s = "List001";
+    to.i = 100;
+    to.s = "List005";
+    IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, siCursor, &from, &to)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, 
myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records using integer-string index. */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, isCursor) {
+        printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s, 
myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records using integer(descend)-string index. */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, idsCursor) {
+        printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s, 
myRow->b?"True":"False", myRow->r);
+    }
+    return step;
+}
+
+static void
+do_idl_compound_index(struct ovs_cmdl_context *ctx)
+{
+    struct ovsdb_idl *idl;
+    struct ovsdb_idl_index_cursor sCursor, iCursor, siCursor, sidCursor,
+                    isCursor, idsCursor;
+    enum TESTS { IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN,
+            IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
+    };
+    int step = 0;
+    int i;
+
+    idltest_init();
+
+    idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, false, true);
+
+    /* Add tables/columns and initialize index data needed for tests */
+    ovsdb_idl_add_table(idl, &idltest_table_simple);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_s);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_i);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_r);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_b);
+
+    struct ovsdb_idl_index *index;
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, 
NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "integer");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, 
NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, 
"string-integer");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, 
NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, 
NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, 
"string-integerd");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, 
NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC, 
NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, 
"integer-string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, 
NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, 
NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, 
"integerd-string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC, 
NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, 
NULL);
+
+    /* wait for replica to be updated */
+    ovsdb_idl_get_initial_snapshot(idl);
+
+    /* Initialize cursors to be used by indexes */
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string", 
&sCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer", 
&iCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integer", 
&siCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integerd", 
&sidCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer-string", 
&isCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integerd-string", 
&idsCursor);
+
+    setvbuf(stdout, NULL, _IONBF, 0);
+    int test_to_run = -1;
+    for (i = 2; i < ctx->argc; i++) {
+        char *arg = ctx->argv[i];
+
+        if(strcmp(arg,"idl_compound_index_single_column")== 0) {
+            test_to_run = IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN;
+        } else if(strcmp(arg, "idl_compound_index_double_column")==0) {
+            test_to_run = IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN;
+        }
+
+        switch(test_to_run) {
+            case IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN:
+                test_idl_compound_index_single_column(idl, &sCursor, &iCursor);
+                break;
+            case IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN:
+                test_idl_compound_index_double_column(&siCursor,
+                        &sidCursor, &isCursor, &idsCursor);
+                break;
+            default:
+                printf("%03d: Test %s not implemented.\n", step++, arg);
+        }
+    }
+    ovsdb_idl_destroy(idl);
+    printf("%03d: done\n", step);
+}
+
static struct ovs_cmdl_command all_commands[] = {
     { "log-io", NULL, 2, INT_MAX, do_log_io },
     { "default-atoms", NULL, 0, 0, do_default_atoms },
@@ -2206,6 +2416,7 @@ static struct ovs_cmdl_command all_commands[] = {
     { "execute", NULL, 2, INT_MAX, do_execute },
     { "trigger", NULL, 2, INT_MAX, do_trigger },
     { "idl", NULL, 1, INT_MAX, do_idl },
+    { "idl-compound-index", NULL, 2, 2, do_idl_compound_index },
     { "help", NULL, 0, INT_MAX, do_help },
     { NULL, NULL, 0, 0, NULL },
};
--
1.9.1
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to