Accessing table metadata
The package loads and uses the following metadata:
List of table columns, represented by an implementation of
metadata\Columnsinterface. It is used for configuring the list of columns returned by the query, for setting of column values inINSERTandUPDATEqueries, and for Conditions on specific columns;PRIMARY KEYconstraint, represented by an implementation ofmetadata\PrimaryKeyinterface. It allows accessing table rows by primary key and performingupsert()andreplaceRelated()operations;FOREIGN KEYconstraints, represented by an implementation ofmetadata\Referencesinterface. These are used to perform joins in all the relevant Fragments.
Value objects
These are used throughout the package to represent simpler database objects.
metadata\TableName
This class represents an always-qualified name of a table (or possibly another relation). Unlike QualifiedName from
pg_builder package it always has two parts: schema (defaulting to public) and relation name.
It also does not need to be cloned (QualifiedName contains a link to its parent node,
so using the same instance in multiple queries is not possible). The API is the following:
namespace sad_spirit\pg_gateway\metadata;
use sad_spirit\pg_builder\nodes\QualifiedName;
final class TableName implements \Stringable
{
public readonly string $schema;
public readonly string $relation;
public function __construct(string ...$nameParts);
// Converting to QualifiedName and back
public static function createFromNode(QualifiedName $qualifiedName) : self;
public function createNode() : QualifiedName;
// Checks whether the two names are equal
public function equals(self $other) : bool;
// Returns the string representation, this uses QualifiedName internally
public function __toString() : string;
}
metadata\Column
This class represents properties of a table column.
namespace sad_spirit\pg_gateway\metadata;
final readonly class Column
{
/** Column name */
public string $name;
/** Whether column is nullable */
public bool $nullable;
/** OID of the column data type */
public int|numeric-string $typeOID;
}
metadata\ForeignKey
This class represents properties of a foreign key between two tables.
namespace sad_spirit\pg_gateway\metadata;
final readonly class ForeignKey implements \IteratorAggregate<string, string>
{
/** Name of the child table (the one to which the FOREIGN KEY constraint was added) */
public TableName $childTable;
/** Names of the columns in the child table */
public string[] $childColumns;
/** Name of the referenced / parent table (the one mentioned in the REFERENCES clause of FOREIGN KEY) */
public TableName $referencedTable;
/** Names of the columns in the referenced table*/
public string[] $referencedColumns;
/** Name of the FOREIGN KEY constraint (always available, autogenerated by Postgres if not given explicitly) */
public string $constraintName;
/** Iterates over a mapping ['child column' => 'referenced column'] */
public function getIterator() : \ArrayIterator<string, string>;
/** Returns whether a foreign key is recursive, i.e. refers back to the same table */
public function isRecursive() : bool;
}
Base interfaces
metadata\Columns
Implementations of Columns serve as containers for Column value objects, allowing iteration over these
and providing some additional methods:
namespace sad_spirit\pg_gateway\metadata;
interface Columns extends \IteratorAggregate<string, Column>, \Countable
{
public function getAll() : Column[];
public function getNames() : string[];
public function has(string $column) : bool;
public function get(string $column) : Column;
}
get() will throw an OutOfBoundsException if a column with the given name was not found.
As the interface extends \IteratorAggregate and \Countable, the following is possible:
$columns = $definition->getColumns();
echo "The table has " . \count($columns) . " column(s), specifically:\n";
foreach ($columns as $column) {
echo $column->getName() . "\n";
}
metadata\PrimaryKey
This is also a container for Column objects, representing columns that form the table’s primary key:
namespace sad_spirit\pg_gateway\metadata;
interface PrimaryKey extends \IteratorAggregate<int, Column>, \Countable
{
public function getAll() : Column[];
public function getNames() : string[];
public function isGenerated() : bool;
}
isGenerated() returns whether table’s primary key is automatically generated. This includes the
SQL standard GENERATED columns, Postgres specific SERIAL,
and those having nextval('sequence_name') for a default value.
metadata\References
Implementations serve as containers for ForeignKey value objects,
representing both FOREIGN KEY constraints added to the table and those referencing it:
namespace sad_spirit\pg_gateway\metadata;
interface References extends \IteratorAggregate<int, ForeignKey>, \Countable
{
public function get(TableName $relatedTable, string[] $keyColumns = []) : ForeignKey;
public function from(TableName $referencedTable, string[] $keyColumns = []) : ForeignKey[];
public function to(TableName $childTable, string[] $keyColumns = []) : ForeignKey[];
}
get()Returns a single
ForeignKeyobject matching the given related table and constraint columns (if given). The columns are always those on the child side of the relationship. Will throw anInvalidArgumentExceptionunless exactly one matching key is found.from()Returns foreign keys defined on the given table referencing the current one.
to()Returns foreign keys on the current table referencing the given one.
Default implementations
The default implementations of the above interfaces are named metadata\TableColumns, metadata\TablePrimaryKey,
and metadata\TableReferences, respectively. These will work with ordinary tables, but not other relations like views
or foreign tables. All of these extend base CachedMetadataLoader class, which tries to use metadata cache from
Connection object if that cache is available before loading metadata from database.
Of course, it is highly recommended to use metadata cache in production.
Metadata containers
TableDefinition interface
Implementations of this aggregate metadata for a particular table (or possibly some other relation):
namespace sad_spirit\pg_gateway;
interface TableDefinition
{
public function getName() : metadata\TableName;
public function getColumns() : metadata\Columns;
public function getPrimaryKey() : metadata\PrimaryKey;
public function getReferences() : metadata\References;
}
The package contains a default implementation of this interface, OrdinaryTableDefinition class.
It represents metadata of an ordinary table with its methods returning the default Table* implementations
of metadata interfaces described above.
TableAccessor interface
This interface should be implemented by classes that perform queries to a specific table:
namespace sad_spirit\pg_gateway;
use sad_spirit\pg_wrapper\Connection;
interface TableAccessor
{
public function getConnection(): Connection;
public function getDefinition(): TableDefinition;
}
it is extended by TableGateway and SelectProxy, these have default implementations in the package.