TableLocator class

This class serves as a facade to features of pg_gateway and the packages it depends on. It is also used to create table gateways and builders.

It is recommended to pass an instance of this class as a dependency instead of individual gateway objects.

Class API

namespace sad_spirit\pg_gateway;

use sad_spirit\pg_wrapper\Connection;
use sad_spirit\pg_builder\{
    NativeStatement,
    Parser,
    Statement,
    StatementFactory,
    converters\TypeNameNodeHandler,
    nodes\QualifiedName,
};
use Psr\Cache\CacheItemPoolInterface;

class TableLocator
{
    // Static helper methods
    public static function hash(mixed $value) : string;
    public static function generateAlias() : string;

    public function __construct(
        Connection $connection,
        iterable<TableGatewayFactory> $gatewayFactories = [],
        ?StatementFactory $statementFactory = null,
        ?CacheItemPoolInterface $statementCache = null
    );

    // factory for TableDefinition implementations
    public function getTableDefinitionFactory() : TableDefinitionFactory;
    public function setTableDefinitionFactory(TableDefinitionFactory $factory) : $this;

    // factory for gateways and builders
    public function addTableGatewayFactory(TableGatewayFactory $factory) : $this;

    // getters for constructor dependencies
    public function getConnection() : Connection;
    public function getStatementFactory() : StatementFactory;

    // facade methods
    public function atomic(callable $callback, bool $savepoint = false) : mixed;
    public function getParser() : Parser;
    public function createFromString(string $sql) : Statement;
    public function createFromAST(Statement $ast) : NativeStatement;
    public function getTypeConverterFactory() : TypeNameNodeHandler&ConfigurableTypeConverterFactory;
    public function createTypeNameNodeForOID($oid) : TypeName;

    // creating statements
    public function createNativeStatementUsingCache(\Closure $factoryMethod, ?string $cacheKey) : NativeStatement;

    // creating objects containing tables' metadata
    public function getTableDefinition(string|metadata\TableName|QualifiedName $name) : TableDefinition;

    // creating gateways and builders
    public function createGateway(string|metadata\TableName|QualifiedName $name) : TableGateway;
    public function createBuilder(string|metadata\TableName|QualifiedName $name) : builders\FragmentListBuilder;

    // Shorthand for createGateway($name)->select($fragments, $parameters)
    public function select(
        string|metadata\TableName|QualifiedName $name,
        null|iterable|\Closure|Fragment|FragmentBuilder $fragments = null,
        array $parameters = []
    ) : SelectProxy;
}

Constructor arguments

The only required argument is the Connection object:

$locator = new TableLocator(new Connection('...connection string...'));

$gatewayFactories, if given, will be used in createGateway() and createBuilder(). Otherwise, these methods will return instances of default gateways and default builder, respectively.

If $statementFactory is omitted, a factory for the given Connection will be created via StatementFactory::forConnection() method.

$statementCache can be any PSR-6 cache implementation. If given, it will be used for caching complete statements. Note that table metadata will be cached using the metadata cache of Connection object, if one is available.

Facade methods

atomic()

Calls Connection::atomic(), passing TableLocator instance as the first argument to the given callback. This executes the callback atomically (within database transaction).

getParser()

Returns an instance of Parser used by StatementFactory.

createFromString()

Calls the same method of StatementFactory, parses SQL of a complete statement returning its AST.

createFromAST()

Calls the same method of StatementFactory, builds an SQL string from AST and returns object encapsulating this string and parameter placeholder data.

getTypeConverterFactory()

Returns the type converter factory object used by Connection.

createTypeNameNodeForOID()

Calls the same method of TypeNameNodeHandler, returns TypeName node corresponding to database type OID that can be used in statement AST.

Getting metadata and creating gateways (the Locator part)

Note

It is recommended to always provide a qualified name (schema_name.table_name) to TableLocator methods: the package does not process search_path and will simply assume that an unqualified name belongs to the public schema.

getTableDefinition()

Returns metadata for a specific database table. It uses an implementation of TableDefinitionFactory interface under the hood.

setTableDefinitionFactory()

Sets the implementation of TableDefinitionFactory used by getTableDefinition().

getTableDefinitionFactory()

Returns the implementation of TableDefinitionFactory used by getTableDefinition(). This will set up and return a default instance of OrdinaryTableDefinitionFactory if a specific instance was not configured. That default implementation, as its name implies, only returns metadata for ordinary tables, using it with views / foreign tables / etc. will cause an exception.

Table metadata that is returned by getTableDefinition() is used for creating gateways and builders to that table:

createGateway()

Returns a TableGateway implementation for a given table name.

createBuilder()

Returns a fluent builder for a given table name.

These methods will call relevant methods of available TableGatewayFactory implementations in the order these were added (either in constructor or with addTableGatewayFactory()).

  • If a factory returns a non-null value it will become the method’s result.

  • If no factories are available or if all of them returned null, default gateway / builder implementations are created and returned.

Creating statements

createNativeStatementUsingCache() method is used by TableGateway and SelectProxy implementations for creating statements.

The goal of this method is to prevent parse / build operations and return the actual pre-built SQL. Thus its return value is an instance of NativeStatement encapsulating that SQL, hopefully coming from cache.

$factoryMethod closure, on the other hand, should return an instance of Statement, i.e. the AST. Consider the actual implementation of GenericTableGateway::createInsertStatement():

public function createInsertStatement(FragmentList $fragments): NativeStatement
{
    return $this->tableLocator->createNativeStatementUsingCache(
        function () use ($fragments): Insert {
            $insert = $this->tableLocator->getStatementFactory()->insert(new InsertTarget(
                $this->definition->getName()->createNode(),
                new Identifier(TableGateway::ALIAS_SELF)
            ));
            $fragments->applyTo($insert);
            return $insert;
        },
        $this->generateStatementKey(StatementType::Insert, $fragments)
    );
}