<?php

namespace Doctrine\DBAL;

use Closure;
use Doctrine\DBAL\Cache\CacheException;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Types\Type;
use Throwable;

/**
 * @phpstan-type WrapperParameterType = string|Type|ParameterType|ArrayParameterType
 * @phpstan-type WrapperParameterTypeArray = array<int<0, max>, WrapperParameterType>|array<string, WrapperParameterType>
 */
class Connection
{
    /**
     * Executes an SQL statement with the given parameters and returns the number of affected rows.
     *
     * Could be used for:
     *  - DML statements: INSERT, UPDATE, DELETE, etc.
     *  - DDL statements: CREATE, DROP, ALTER, etc.
     *  - DCL statements: GRANT, REVOKE, etc.
     *  - Session control statements: ALTER SESSION, SET, DECLARE, etc.
     *  - Other statements that don't yield a row set.
     *
     * This method supports PDO binding types as well as DBAL mapping types.
     *
     * @param __doctrine-literal-string                   $sql    SQL statement
     * @param list<mixed>|array<string, mixed> $params Statement parameters
     * @param WrapperParameterTypeArray        $types  Parameter types
     *
     * @return int|string The number of affected rows.
     *
     * @throws Exception
     */
    public function executeStatement($sql, array $params = [], array $types = []);

    /**
     * Executes an, optionally parameterized, SQL query.
     *
     * If the query is parametrized, a prepared statement is used.
     * If an SQLLogger is configured, the execution is logged.
     *
     * @param __doctrine-literal-string                   $sql    SQL query
     * @param list<mixed>|array<string, mixed> $params Query parameters
     * @param WrapperParameterTypeArray        $types  Parameter types
     *
     * @throws Exception
     */
    public function executeQuery(
        string $sql,
        array $params = [],
        $types = [],
        ?QueryCacheProfile $qcp = null
    ): Result;

    /**
     * Executes a caching query.
     *
     * @param __doctrine-literal-string                   $sql    SQL query
     * @param list<mixed>|array<string, mixed> $params Query parameters
     * @param WrapperParameterTypeArray        $types  Parameter types
     *
     * @throws CacheException
     * @throws Exception
     */
    public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp): Result;

    /**
     * @param-immediately-invoked-callable $func
     * @param Closure(self): T $func
     * @return T
     *
     * @template T
     *
     * @throws Throwable
     */
    public function transactional(Closure $func);

    /**
     * Executes an SQL DELETE statement on a table.
     *
     * Table expression and columns are not escaped and are not safe for user-input.
     *
     * @param __doctrine-literal-string                                                             $table
     * @param array<__doctrine-literal-string, mixed>                                               $criteria
     * @param array<int<0,max>, string|ParameterType|Type>|array<string, string|ParameterType|Type> $types
     *
     * @return int|numeric-string The number of affected rows.
     *
     * @throws Exception
     */
    public function delete(string $table, array $criteria = [], array $types = []): int|string;

    /**
     * Executes an SQL UPDATE statement on a table.
     *
     * Table expression and columns are not escaped and are not safe for user-input.
     *
     * @param __doctrine-literal-string                                                             $table
     * @param array<__doctrine-literal-string, mixed>                                               $data
     * @param array<__doctrine-literal-string, mixed>                                               $criteria
     * @param array<int<0,max>, string|ParameterType|Type>|array<string, string|ParameterType|Type> $types
     *
     * @return int|numeric-string The number of affected rows.
     *
     * @throws Exception
     */
    public function update(string $table, array $data, array $criteria = [], array $types = []): int|string;

    /**
     * Inserts a table row with specified data.
     *
     * Table expression and columns are not escaped and are not safe for user-input.
     *
     * @param __doctrine-literal-string                                                             $table
     * @param array<__doctrine-literal-string, mixed>                                               $data
     * @param array<int<0,max>, string|ParameterType|Type>|array<string, string|ParameterType|Type> $types
     *
     * @return int|numeric-string The number of affected rows.
     *
     * @throws Exception
     */
    public function insert(string $table, array $data, array $types = []): int|string;
}
