NAME

DBIO::Introspect::Base - Base class for DBIO driver introspectors

VERSION

version 0.900000

DESCRIPTION

Base class for the driver-specific introspectors (DBIO::PostgreSQL::Introspect, DBIO::SQLite::Introspect, DBIO::MySQL::Introspect). Provides new, the dbh accessor, and the lazy model builder. Subclasses must implement _build_model.

ATTRIBUTES

dbh

The connected DBI database handle. Required.

METHODS

model

The introspected database model hashref. Built lazily on first access via "_build_model". The shape varies by driver.

_aggregate_by

my $by_table = $class->_aggregate_by(\@rows, 'table_name');

Groups a flat array of row hashrefs into { $key_value = [\%row, ...] }>. Preserves row order within each group. The \@rows arrayref is consumed (rows are shifted off); pass a copy if you need the original.

_aggregate_by_ordered

my $groups = $class->_aggregate_by_ordered(\@rows, 'constraint_name');
for my $pair (@$groups) {
  my ($key, $group_rows) = @$pair;
  ...
}

Like "_aggregate_by", but returns an ArrayRef of [ $key, [\%row, ...] ] pairs in first-seen key order, so callers that need deterministic group ordering (e.g. composite foreign-key columns, which must keep their declared local/remote pairing) do not have to reimplement the grouping. Row order within each group is preserved. Rows whose key field is undef are skipped.

table_keys

Returns an ArrayRef of opaque table-key strings (typically schema.table or just table). These are passed as $key to all other contract methods. Default: the sorted bare table names from the canonical tables section.

table_columns

my \@names = $intro->table_columns($key);

Ordered list of column names for $key. Default: the column_name of each entry in the canonical columns section, in declaration order.

table_columns_info

my \%info = %{ $intro->table_columns_info($key) };

Hashref { col_name = { data_type, size, is_nullable, default_value, is_auto_increment, ... } }>. Default: built from the canonical columns section -- is_nullable is the inverse of not_null; size and is_auto_increment are included only when present on the column.

table_pk_info

my \@pk_cols = @{ $intro->table_pk_info($key) };

Ordered list of primary key column names. Default: the is_pk columns from the canonical columns section, ordered by pk_position (composite keys keep their declared order).

table_uniq_info

my \@constraints = @{ $intro->table_uniq_info($key) };

List of [ $constraint_name, \@col_names ] pairs. Default: the canonical unique_constraints section for $key if that section exists; otherwise derived from the indexes section (unique indexes, skipping primary-key backed ones and any index literally named PRIMARY).

table_fk_info

my \@fks = @{ $intro->table_fk_info($key) };

Each FK is a hashref:

{
  local_columns  => [qw/author_id/],
  remote_table   => 'authors',
  remote_schema  => 'public',   # may be undef
  remote_columns => [qw/id/],   # may be [] (use remote PK)
  attrs          => {},
}

Default: built from the canonical foreign_keys section. remote_schema is always undef (single-schema), and attrs carries on_delete / on_update.

table_is_view

Returns true if $key is a view rather than a base table. Default: true when the canonical tables entry has kind => 'view'.

view_definition

SQL text of the view definition, or undef.

table_comment

Comment string for the table, or undef.

column_comment

Comment string for a column, or undef.

result_class_extra_statements

my @stmts = $intro->result_class_extra_statements($key);

Optional hook for driver-specific emitter statements. Each element is an arrayref [ $method_name, @args ] which DBIO::Generate emits verbatim as __PACKAGE__-method_name(@args)>. Defaults to an empty list.

CANONICAL MODEL

The hashref returned by "model" is the substrate every contract method reads. Its shape varies by driver, but there is one canonical shape -- the un-qualified, single-database shape shared by the single-schema drivers (MySQL, Firebird, SQLite). The default contract implementations below are written against it, so any driver whose _build_model produces this shape inherits a working contract for free. Drivers that diverge (PostgreSQL: schema-qualified keys, case normalization, enum/identity/generated columns) override the methods they need.

The canonical model has up to five top-level sections, each a hashref keyed by table name (bare, un-qualified):

  • tables -- { $table => { table_name => $table, kind => 'table'|'view' } }

  • columns -- { $table => [ \%column, ... ] } in declaration order. Each column: column_name, data_type (bare SQL type), size (undef, a scalar length, or a [precision, scale] pair), not_null (0/1), default_value (or undef), is_pk / pk_position (primary-key membership and 1-based ordinal), and optionally is_auto_increment.

  • indexes -- { $table => { $index_name => { is_unique, columns => [...], origin } } }. origin is 'pk' for a primary-key-backed index (skipped by "table_uniq_info").

  • unique_constraints -- (optional) { $table => [ [ $name, \@cols ], ... ] }. When present, it is the authoritative source for "table_uniq_info"; when absent, unique constraints are derived from the indexes section.

  • foreign_keys -- { $table => [ \%fk, ... ] }. Each FK: from_columns, to_table, to_columns, on_update, on_delete, and optionally constraint_name -- the live, server-assigned constraint name, carried by drivers that can introspect it so the diff/deploy layer can prefer the real name for FK DROP/ALTER instead of a generated one. constraint_name is FK metadata, not a compared attribute. See ADR 0021.

NORMALIZED CONTRACT

Subclasses that are used as a generation source for DBIO::Generate implement these methods. The first seven ship default implementations that read the "CANONICAL MODEL"; a single-schema driver inherits them unchanged and a divergent driver overrides what it needs. The remaining four return safe defaults.

AUTHOR

DBIO & DBIx::Class Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.