Skip to main content

SQLite adapters

PRO
Pro preview

This feature is part of FD Components Pro, which is documented as a preview and is not publicly available yet. See Editions and Availability.

FDC Pro provides two SQLite adapter models:

  • FdcSqliteTableAdapter for writable table-backed CRUD datasets;
  • FdcSqliteQueryAdapter for read-only SQL result sets.

Table adapter

Use the table adapter when dataset fields map directly to SQLite columns.

final customers = FdcDataSet(
fields: const [
FdcIntegerField(name: 'customer_id', isKey: true),
FdcStringField(name: 'company', size: 120),
FdcStringField(name: 'city', size: 80),
FdcStringField(name: 'state', size: 2),
],
adapter: FdcSqliteTableAdapter(
databasePath: databasePath,
table: 'customers',
sorts: const [
FdcDataAdapterSort(
fieldName: 'company',
sortType: FdcSortType.ascending,
),
],
),
);

await customers.open();

Field names must match SQLite column names exactly. When the dataset does not provide explicit fields, the table adapter can infer schema information from PRAGMA table_info during open.

The path-backed constructor performs SQLite work through the adapter's worker-backed execution path.

Query adapter

Use the query adapter for read-only SQL results:

final sales = FdcDataSet(
fields: const [
FdcStringField(name: 'state', size: 2),
FdcDecimalField(name: 'total_sales', precision: 18, scale: 2),
],
adapter: FdcSqliteQueryAdapter(
databasePath: databasePath,
sql: '''
SELECT state, SUM(amount) AS total_sales
FROM orders
GROUP BY state
''',
),
);

The default query adapter runs the supplied SQL as a raw read-only source. It does not claim adapter-side filtering, sorting, or paging for arbitrary SQL.

Wrappable queries

For a simple SELECT that can safely be wrapped as a subquery, use FdcSqliteQueryAdapter.wrappable:

final adapter = FdcSqliteQueryAdapter.wrappable(
databasePath: databasePath,
sql: '''
SELECT
order_id,
customer_id,
order_date,
amount
FROM orders
''',
);

Wrappable mode can apply outer filtering, search, sorting, paging, and aggregates. Every projected column, including expressions, must expose a stable alias matching the FDC field name exactly.

Debugging and profiling

SQLite diagnostics are opt-in and exposed through a separate development entrypoint:

import 'package:flutter_data_components_pro/fdc_pro_debug.dart';

Normal application code should continue importing fdc_pro.dart. Import the debug entrypoint only in development or diagnostics code that needs low-level SQLite tracing.

SQL debug logging

Enable logSql to inspect the exact statements generated and executed by the SQLite adapters:

FdcSqliteDebug.logSql = true;
FdcSqliteDebug.logSqlArguments = true; // default

await customers.open();

SQL diagnostics use the [FDC-SQLITE-SQL] prefix. Depending on the operation, the trace can include generated SELECT, COUNT, PRAGMA, INSERT, UPDATE, DELETE, and transaction statements.

Bound arguments are logged separately when logSqlArguments is enabled. This is useful when a generated statement looks correct but a filter, search term, key value, or paging argument does not produce the expected result.

FdcSqliteDebug.logSql = true;
FdcSqliteDebug.logSqlArguments = false;

Disable argument logging when values are sensitive or when the SQL shape alone is sufficient for diagnosis.

For difficult call-path problems, stack traces can be enabled as well:

FdcSqliteDebug.logSql = true;
FdcSqliteDebug.logSqlStack = true;

logSqlStack is intentionally noisy and is best used for short, targeted debugging sessions.

Apply diagnostics

logApply is independent from SQL logging. It emits one summary line before each adapter apply call and reports insert, update, and delete counts together with the changed field names:

FdcSqliteDebug.logApply = true;

await customers.applyUpdates();

Apply diagnostics use the [FDC-SQLITE-APPLY] prefix. This mode is useful when investigating update lifecycle problems without printing every generated SQL statement.

For example, use it to answer questions such as:

  • Did the dataset send an apply call at all?
  • Was the change classified as an insert, update, or delete?
  • Which fields were marked as changed?
  • Was the submitted changeset empty?

SQL profiler

Enable logSqlTiming to profile SQLite operation timings and result sizes:

FdcSqliteDebug.logSqlTiming = true;

await customers.open();

Timing entries include elapsed milliseconds and, when available, row counts or affected-row counts. This makes the profiler useful for comparing query shapes, indexes, filters, paging strategies, and count-query cost.

You can profile timings without printing every SQL statement:

FdcSqliteDebug.logSql = false;
FdcSqliteDebug.logSqlTiming = true;

Or enable SQL and timing together when you need to correlate a slow operation with the generated statement:

FdcSqliteDebug.logSql = true;
FdcSqliteDebug.logSqlTiming = true;
FdcSqliteDebug.logSqlArguments = true;

A practical profiling workflow is:

  1. enable logSqlTiming alone to identify slow operations;
  2. enable logSql temporarily to inspect the SQL for a slow operation;
  3. inspect bound arguments when filters or paging behavior are suspicious;
  4. enable logSqlStack only when the caller itself is unclear;
  5. disable diagnostics after the investigation.

Diagnostic switches

OptionPurposeDefault
logSqlLogs generated and executed SQL statementsfalse
logSqlArgumentsIncludes bound argument values with SQL logstrue
logSqlStackPrints a stack trace after SQL/apply diagnosticsfalse
logSqlTimingLogs elapsed operation time and result countsfalse
logApplyLogs one summary before each adapter apply callfalse

When both logSql and logSqlTiming are disabled, FDC does not allocate or start timing stopwatches on the normal SQLite hot path. Keep diagnostics disabled in normal builds and enable only the level of tracing needed for the current investigation.

Resource lifecycle

Datasets dispose their adapters when the dataset is disposed. When application code owns an adapter directly and needs explicit completion of SQLite shutdown, the table adapter also exposes an asynchronous close() operation.