Skip to content

Provider Trait Matrix

Weasel supports five database providers — PostgreSQL, SQL Server, Oracle, MySQL, and SQLite — each with subtly different feature sets. The audit at #270 documented this matrix explicitly so users can write provider-agnostic schema code with confidence about what works everywhere versus what's provider-specific.

At a glance

FeaturePostgreSQLSQL ServerOracleMySQLSQLite
Default schemapublicdboWEASELpublicmain
Identifier quoting"name"[name]"NAME"`name`"name"
Identifier caseSensitiveFoldedFolded (upper)Folded (lower)Folded
Max identifier length6312812864(unlimited)
Auto-increment SQLSERIALIDENTITY(1,1)GENERATED…AS IDENTITYAUTO_INCREMENTAUTOINCREMENT
ALTER TABLE ADD COLUMN
ALTER TABLE DROP COLUMN✓ (3.35+)
ALTER TABLE ALTER COLUMN✗ (recreate)
ALTER TABLE ADD CONSTRAINT FK✗ (inline only)
ALTER TABLE DROP CONSTRAINT FK✗ (recreate)
Cascading actions: RESTRICT✗ (→ NoAction)✗ (→ NoAction)
Native sequencesTable-emulatedTable-emulated
Views✓ + materialized✓ (read-only)
Functions / Stored Procedures✓ (PL/pgSQL)✓ (T-SQL)✓ (PL/SQL)(limited)Connection-scoped
Partitioning✓ (hash/range/list)✓ (range)
JSON storagejsonb nativenvarchar(max)CLOBJSONTEXT (JSON1)
Array columns✗ (except byte[])
Statement terminator;;/ (PL/SQL blocks);;

Identity / auto-increment

In 9.0 every provider exposes a canonical .AutoIncrement() fluent method on Table.ColumnExpression. Previously each provider used a different spelling; the old names are kept as [Obsolete] aliases for one major-version cycle.

ProviderCanonical 9.0Pre-9.0 alias ([Obsolete])SQL Emitted
PostgreSQLAutoIncrement()Serial()SERIAL
PostgreSQLBigAutoIncrement()BigSerial()BIGSERIAL
PostgreSQLSmallAutoIncrement()SmallSerial()SMALLSERIAL
SQL ServerAutoIncrement()AutoNumber()IDENTITY(1,1)
OracleAutoIncrement()AutoNumber()GENERATED BY DEFAULT AS IDENTITY
MySQLAutoIncrement()AutoNumber()AUTO_INCREMENT
SQLiteAutoIncrement()(no change)AUTOINCREMENT
csharp
// Same code compiles against any of the five providers
table.AddColumn<int>("id").AsPrimaryKey().AutoIncrement();

Identifier comparison

Table.ColumnFor / HasColumn / IndexFor / HasIndex use a per-provider NameComparison:

ProviderNameComparisonRationale
PostgreSQLOrdinalPG is case-sensitive when quoted (the default for Weasel-generated DDL)
SQL ServerOrdinalIgnoreCaseSS identifier comparison is case-insensitive by default
OracleOrdinalIgnoreCaseOracle folds unquoted identifiers to upper case
MySQLOrdinalIgnoreCaseMySQL identifier comparison is case-insensitive on most platforms
SQLiteOrdinalIgnoreCaseSQLite identifiers are case-folded

RemoveColumn is always case-insensitive on every provider — every concrete provider used EqualsIgnoreCase historically.

Primary-key name defaults

When you don't supply a PrimaryKeyName, each provider generates one with its own convention:

ProviderDefault PrimaryKeyName
PostgreSQLpkey_{table}_{cols}
SQL Serverpkey_{table}_{cols}
Oraclepk_{table}_{cols}
MySQLpk_{table}_{cols}
SQLitepk_{table}

Schema-object base types

Most schema objects share a base class in Weasel.Core:

ObjectCore baseNotes
TablesTableBase<TColumn, TIndex, TForeignKey>New in 9.0 (#270 step 9)
Foreign keysForeignKeyBaseOwns Parse, LinkColumns, Equals, ReadReferentialActions
SequencesSequenceBasePG / SS / Oracle native, MySQL / SQLite table-emulated
FunctionsFunctionBasePG + SS only; Oracle uses procedures; SQLite functions are connection-scoped
ViewsViewBaseAll providers; SQLite is read-only
IndexesINamed onlyProvider-specific (PG is ~4× richer than the others)
Table columnsITableColumn onlyProvider-specific declaration formatting

DDL syntax strategy

The shared CREATE / DROP algorithm is gradually migrating to consume a IDdlSyntaxStrategy object per provider (#270 step 8). Currently routed through it:

  • WriteDropTable (PG appends CASCADE, SQLite doesn't)
  • WriteCreateTableHeader (with / without IF NOT EXISTS)

The remainder of WriteCreateStatement is still per-provider while the strategy shape settles. Plan is to migrate column / PK / FK emission as a follow-up.

Constructor pattern

All five Table classes share the same constructor signatures:

csharp
new Table(DbObjectName identifier);     // identifier wrapped in provider-specific subclass internally
new Table(string tableName);            // parsed via provider's DbObjectName.Parse

The PostgreSQL and SQLite implementations wrap the supplied DbObjectName in PostgresqlObjectName / SqliteObjectName respectively; SS / Oracle / MySQL pass through the DbObjectName directly. Either way, the public surface is uniform — polymorphic schema-building code doesn't need to know which provider it's targeting until DDL is emitted.

When you do need provider-specific code

Provider-specific extensions stay on the concrete Table / ColumnExpression:

  • PostgreSQL: MaterializedView, Partitioning (hash / range / list), IgnorePartitionsInMigration, FullTextIndex, UpsertFunction, NpgsqlRange<T> columns
  • SQL Server: SqlServerPartitioning (range), PartitionByRange
  • Oracle: PartitionStrategy, PartitionExpressions
  • MySQL: Engine, Charset, Collation, PartitionCount, AddFulltextIndex
  • SQLite: WithoutRowId, StrictTypes, GeneratedAs, JSON expression indexes via ForJsonPath

Polymorphic code uses the shared ITable / TableBase surface; code that needs provider extras casts to the concrete Table type.

Released under the MIT License.