Skip to main content

Database Adapters

Text2SQL supports multiple database systems through dedicated adapters. Each adapter implements database-specific introspection, query validation, and SQL dialect handling.

Supported Databases

SQLite

Lightweight embedded database

PostgreSQL

Advanced open-source database

SQL Server

Microsoft enterprise database

MySQL

Popular open-source database

BigQuery

Google Cloud data warehouse

Adapter Comparison

FeatureSQLitePostgreSQLSQL ServerMySQLBigQuery
SchemasNoYesYesYesYes
Foreign KeysYesYesYesYesYes
IndexesYesYesYesYesLimited
ViewsYesYesYesYesYes
ConstraintsYesYesYesYesYes
Column StatsYesYesYesYesNo
Row CountsYesYesYesYesYes
TransactionsYesYesYesYesNo

Common Adapter Interface

All adapters implement the same core interface:
abstract class Adapter {
  // Execute SQL query
  abstract execute(sql: string): Promise<any[]>;
  
  // Validate SQL without executing
  abstract validate(sql: string): Promise<string | void>;
  
  // Introspect database schema
  async introspect(): Promise<ContextFragment[]>;
  
  // Quote identifier (table/column name)
  abstract quoteIdentifier(name: string): string;
  
  // Escape string value
  abstract escape(value: string): string;
  
  // Format SQL for the dialect
  format(sql: string): string;
  
  // Build sample query
  abstract buildSampleRowsQuery(
    tableName: string,
    columns: string[] | undefined,
    limit: number
  ): string;
}

Grounding Functions

Grounding functions control what schema metadata the AI receives. All adapters support these groundings:

Available Groundings

tables(config?)

Introspects tables, columns, and data types.
import { tables } from '@deepagents/text2sql/[adapter]';

grounding: [
  tables({
    include?: string[] | RegExp,  // Filter tables
    exclude?: string[] | RegExp   // Exclude tables
  })
]

views(config?)

Introspects database views.
import { views } from '@deepagents/text2sql/[adapter]';

grounding: [
  views({
    include?: string[] | RegExp
  })
]

info(config?)

Provides database version and metadata.
import { info } from '@deepagents/text2sql/[adapter]';

grounding: [info()]

indexes(config?)

Introspects table indexes for performance hints.
import { indexes } from '@deepagents/text2sql/[adapter]';

grounding: [indexes()]

constraints(config?)

Introspects constraints (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK).
import { constraints } from '@deepagents/text2sql/[adapter]';

grounding: [constraints()]

rowCount(config?)

Counts rows and classifies table sizes (tiny, small, medium, large, huge).
import { rowCount } from '@deepagents/text2sql/[adapter]';

grounding: [rowCount()]

columnStats(config?)

Collects column statistics (min, max, null fraction, correlation).
import { columnStats } from '@deepagents/text2sql/[adapter]';

grounding: [columnStats()]

columnValues(config?)

Fetches distinct values for low-cardinality columns (enums).
import { columnValues } from '@deepagents/text2sql/[adapter]';

grounding: [
  columnValues({
    limit: 20  // Max distinct values per column
  })
]

Minimal (Fast Introspection)

grounding: [
  tables(),
  info()
]

Balanced (Most Common)

grounding: [
  tables(),
  views(),
  info(),
  indexes(),
  constraints()
]

Comprehensive (Slower, Maximum Context)

grounding: [
  tables(),
  views(),
  info(),
  indexes(),
  constraints(),
  rowCount(),
  columnStats(),
  columnValues({ limit: 20 })
]

SQL Dialect Support

Each adapter formats SQL according to its database’s dialect:

Identifier Quoting

// PostgreSQL, SQLite, BigQuery
adapter.quoteIdentifier('my_table') // "my_table"

// SQL Server
adapter.quoteIdentifier('my_table') // [my_table]

// MySQL
adapter.quoteIdentifier('my_table') // `my_table`

String Escaping

// All adapters escape single quotes
adapter.escape("O'Reilly") // O''Reilly

LIMIT vs TOP

// PostgreSQL, SQLite, MySQL, BigQuery
SELECT * FROM users LIMIT 10

// SQL Server
SELECT TOP 10 * FROM users

Schema Filtering

PostgreSQL, SQL Server, MySQL, and BigQuery support schema filtering:
const adapter = new Postgres({
  execute: async (sql) => { /* ... */ },
  grounding: [tables(), constraints()],
  schemas: ['public', 'analytics']  // Only introspect these schemas
});
Without schemas, system schemas are excluded automatically:
  • PostgreSQL: pg_catalog, information_schema
  • SQL Server: sys, INFORMATION_SCHEMA
  • MySQL: information_schema, mysql, performance_schema

Error Handling

Each adapter provides database-specific error formatting:
try {
  const sql = await text2sql.toSql('Show me invalid_table');
} catch (error) {
  console.error(error);
}
Error response includes:
{
  "error": "no such table: invalid_table",
  "error_type": "MISSING_TABLE",
  "suggestion": "Check the database schema for the correct table name.",
  "sql_attempted": "SELECT * FROM invalid_table"
}

Error Types

  • MISSING_TABLE - Referenced table does not exist
  • INVALID_COLUMN - Referenced column does not exist or is ambiguous
  • SYNTAX_ERROR - SQL syntax error
  • INVALID_FUNCTION - Function or operator not recognized
  • CONSTRAINT_ERROR - Constraint violation
  • UNKNOWN_ERROR - Unclassified error

Validation

All adapters validate SQL using EXPLAIN before execution:
const validationError = await adapter.validate(
  'SELECT * FROM invalid_table'
);

if (validationError) {
  console.error('Invalid SQL:', validationError);
}
Custom validation:
const adapter = new Postgres({
  execute: async (sql) => { /* ... */ },
  validate: async (sql) => {
    // Custom validation logic
    if (sql.includes('DROP')) {
      throw new Error('DROP statements not allowed');
    }
  },
  grounding: [tables()]
});

Performance Considerations

Introspection Performance

Introspection speed varies by grounding:
GroundingSpeedNotes
tables()FastBasic metadata query
views()FastBasic metadata query
info()FastSingle query
indexes()FastSingle query
constraints()FastSingle query
rowCount()SlowCounts every table
columnStats()SlowScans every column
columnValues()MediumLimited by limit parameter

Caching

Introspection results are automatically cached:
// First call: introspects database
const sql1 = await text2sql.toSql('query 1');

// Subsequent calls: uses cache
const sql2 = await text2sql.toSql('query 2');
Cache is keyed by version parameter:
const text2sql = new Text2Sql({
  version: 'v1',  // Change to invalidate cache
  // ...
});

Manual Cache Control

// Manually trigger introspection
const fragments = await text2sql.index();

// Clear cache by changing version
const text2sqlV2 = new Text2Sql({
  version: 'v2',  // New version
  // ...
});

Adapter-Specific Features

Each adapter has unique capabilities:

PostgreSQL

  • Full schema support
  • Advanced constraint introspection
  • Column statistics from pg_stats
  • Correlation and n_distinct metadata

SQLite

  • Embedded database (no network latency)
  • Simple constraint model
  • Fast introspection

SQL Server

  • Multiple schema support
  • Advanced index metadata
  • T-SQL dialect

MySQL

  • MariaDB compatibility
  • InnoDB and MyISAM support
  • Character set handling

BigQuery

  • Serverless execution
  • Dataset and table partitioning
  • Nested and repeated fields

Next Steps

SQLite Adapter

Setup and configuration for SQLite

PostgreSQL Adapter

Setup and configuration for PostgreSQL

Teachables

Inject domain knowledge

API Reference

Full adapter API documentation

Build docs developers (and LLMs) love