installTable function

Future<void> installTable(
  1. RoomClient room,
  2. RequiredTable table, {
  3. Logger? logger,
  4. bool optimize = true,
})

Install (create + index + optimize) a RequiredTable in the current room.

  • create_table_with_schema(mode=create_if_not_exists)
  • list_indexes + index_exists(column in i.columns)
  • create missing indexes (vector / full-text / scalar), each guarded w/ try/catch
  • optimize(table)

Implementation

Future<void> installTable(RoomClient room, RequiredTable table, {Logger? logger, bool optimize = true}) async {
  logger ??= Logger.root;

  final database = room.database;

  // 1) Create table (idempotent)
  await database.createTableWithSchema(
    name: table.name,
    mode: CreateMode.createIfNotExists,
    schema: table.schema,
    namespace: table.namespace,
  );

  // 2) Read current indexes once
  final indexes = await database.listIndexes(table.name, namespace: table.namespace);

  bool indexExists(String column) {
    for (final idx in indexes) {
      if (idx.columns.contains(column)) return true;
    }
    return false;
  }

  // 3) Create missing vector indexes
  for (final vi in table.vectorIndexes ?? const <String>[]) {
    if (indexExists(vi)) continue;

    try {
      await database.createVectorIndex(table: table.name, column: vi, namespace: table.namespace, replace: true);
    } catch (e, st) {
      logger.warning('unable to create vector index for "$vi": $e', e, st);
    }
  }

  // 4) Create missing full text search indexes
  for (final ti in table.fullTextSearchIndexes ?? const <String>[]) {
    if (indexExists(ti)) continue;

    try {
      await database.createFullTextSearchIndex(table: table.name, column: ti, namespace: table.namespace, replace: true);
    } catch (e, st) {
      logger.warning('unable to create full text search index for "$ti": $e', e, st);
    }
  }

  // 5) Create missing scalar indexes
  for (final si in table.scalarIndexes ?? const <String>[]) {
    if (indexExists(si)) continue;

    try {
      await database.createScalarIndex(table: table.name, column: si, namespace: table.namespace, replace: true);
    } catch (e, st) {
      logger.warning('unable to create scalar index for "$si": $e', e, st);
    }
  }

  if (optimize) {
    logger.info('optimizing table ${table.name} in ${table.namespace}');
    // TODO: use index_stats to determine when indexes need to be updated
    await database.optimize(table: table.name, namespace: table.namespace);
  }
}