def run_idl(self, txn): table_schema = self.api._tables[self.table] idx = idlutils.get_index_column(table_schema) columns = self.columns or list(table_schema.columns.keys()) + ['_uuid'] # If there's an index for this table, we'll fetch all columns and # remove the unwanted ones based on self.records. Otherwise, let's try # to get the uuid of the wanted ones which is an O(n^2) operation. if not idx and self.records: rows = [] for record in self.records: try: rows.append(self.api.idl.lookup(self.table, record)) except idlutils.RowNotFound: if self.if_exists: continue raise else: rows = table_schema.rows.values() def _match(row): elem = getattr(row, idx) return elem in self.records def _match_remove(row): elem = getattr(row, idx) found = elem in self.records if found: records_found.remove(elem) return found def _match_true(row): return True records_found = [] if idx and self.records: if self.if_exists: match = _match else: # If we're using the approach of removing the unwanted # elements, we'll use a helper list to remove elements as we # find them in the DB contents. This will help us identify # quickly if there's some record missing to raise a RowNotFound # exception later. records_found = list(self.records) match = _match_remove else: match = _match_true self.result = [ rowview.RowView(row) if self.row else { c: idlutils.get_column_value(row, c) for c in columns } for row in rows if match(row) ] if records_found: raise idlutils.RowNotFound(table=self.table, col=idx, match=records_found[0])
def _lookup(self, table, record): if record == "": raise TypeError("Cannot look up record by empty string") # Handle commands by simply returning its result if isinstance(record, cmd.BaseCommand): return record.result t = self.tables[table] if isinstance(record, uuid.UUID): try: return t.rows[record] except KeyError: raise idlutils.RowNotFound(table=table, col='uuid', match=record) from None try: uuid_ = uuid.UUID(record) return t.rows[uuid_] except ValueError: # Not a UUID string, continue lookup by other means pass except KeyError: # If record isn't found by UUID , go ahead and look up by the table pass if not self.lookup_table: raise idlutils.RowNotFound(table=table, col='record', match=record) # NOTE (twilson) This is an approximation of the db-ctl implementation # that allows a partial table, assuming that if a table has a single # index, that we should be able to do a lookup by it. rl = self.lookup_table.get( table, idlutils.RowLookup(table, idlutils.get_index_column(t), None)) # no table means uuid only, no column means lookup table has one row if rl.table is None: raise idlutils.RowNotFound(table=table, col='uuid', match=record) if rl.column is None: if t.max_rows == 1: return next(iter(t.rows.values())) raise idlutils.RowNotFound(table=table, col='uuid', match=record) row = idlutils.row_by_value(self, rl.table, rl.column, record) if rl.uuid_column: rows = getattr(row, rl.uuid_column) if len(rows) != 1: raise idlutils.RowNotFound(table=table, col='record', match=record) row = rows[0] return row
def autocreate_indices(self): """Create simple one-column indexes This creates indexes for all lookup_table entries and for all defined indexes columns in the OVSDB schema, as long as they are simple one-column indexes (e.g. 'name') fields. """ tables = set(self.idl.tables.keys()) # lookup table indices for table, (lt, col, uuid_col) in self.lookup_table.items(): if table != lt or not col or uuid_col or table not in tables: # Just handle simple cases where we are looking up a single # column on a single table continue index_name = idlutils.index_name(col) try: idx = self.idl.tables[table].rows.index_create(index_name) except ValueError: LOG.debug("lookup_table index %s.%s already exists", table, index_name) else: idx.add_column(col) LOG.debug("Created lookup_table index %s.%s", table, index_name) tables.remove(table) # Simple ovsdb-schema indices for table in self.idl.tables.values(): if table.name not in tables: continue col = idlutils.get_index_column(table) if not col: continue index_name = idlutils.index_name(col) try: idx = table.rows.index_create(index_name) except ValueError: LOG.debug("schema index %s.%s already exists", table, index_name) else: idx.add_column(col) LOG.debug("Created schema index %s.%s", table.name, index_name) tables.remove(table.name)