vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 161

Open in your IDE?
  1. <?php
  2. namespace Doctrine\DBAL;
  3. use Doctrine\DBAL\Abstraction\Result;
  4. use Doctrine\DBAL\Driver\Exception;
  5. use Doctrine\DBAL\Driver\Statement as DriverStatement;
  6. use Doctrine\DBAL\Exception\NoKeyValue;
  7. use Doctrine\DBAL\Platforms\AbstractPlatform;
  8. use Doctrine\DBAL\Result as BaseResult;
  9. use Doctrine\DBAL\Types\Type;
  10. use Doctrine\Deprecations\Deprecation;
  11. use IteratorAggregate;
  12. use PDO;
  13. use PDOStatement;
  14. use ReturnTypeWillChange;
  15. use Throwable;
  16. use Traversable;
  17. use function array_shift;
  18. use function func_get_args;
  19. use function is_array;
  20. use function is_string;
  21. /**
  22.  * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
  23.  * for logging, DBAL mapping types, etc.
  24.  */
  25. class Statement implements IteratorAggregateDriverStatementResult
  26. {
  27.     /**
  28.      * The SQL statement.
  29.      *
  30.      * @var string
  31.      */
  32.     protected $sql;
  33.     /**
  34.      * The bound parameters.
  35.      *
  36.      * @var mixed[]
  37.      */
  38.     protected $params = [];
  39.     /**
  40.      * The parameter types.
  41.      *
  42.      * @var int[]|string[]
  43.      */
  44.     protected $types = [];
  45.     /**
  46.      * The underlying driver statement.
  47.      *
  48.      * @var \Doctrine\DBAL\Driver\Statement
  49.      */
  50.     protected $stmt;
  51.     /**
  52.      * The underlying database platform.
  53.      *
  54.      * @var AbstractPlatform
  55.      */
  56.     protected $platform;
  57.     /**
  58.      * The connection this statement is bound to and executed on.
  59.      *
  60.      * @var Connection
  61.      */
  62.     protected $conn;
  63.     /**
  64.      * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
  65.      *
  66.      * @internal The statement can be only instantiated by {@link Connection}.
  67.      *
  68.      * @param string     $sql  The SQL of the statement.
  69.      * @param Connection $conn The connection on which the statement should be executed.
  70.      */
  71.     public function __construct($sqlConnection $conn)
  72.     {
  73.         $this->sql      $sql;
  74.         $this->stmt     $conn->getWrappedConnection()->prepare($sql);
  75.         $this->conn     $conn;
  76.         $this->platform $conn->getDatabasePlatform();
  77.     }
  78.     /**
  79.      * Binds a parameter value to the statement.
  80.      *
  81.      * The value can optionally be bound with a PDO binding type or a DBAL mapping type.
  82.      * If bound with a DBAL mapping type, the binding type is derived from the mapping
  83.      * type and the value undergoes the conversion routines of the mapping type before
  84.      * being bound.
  85.      *
  86.      * @param string|int $param The name or position of the parameter.
  87.      * @param mixed      $value The value of the parameter.
  88.      * @param mixed      $type  Either a PDO binding type or a DBAL mapping type name or instance.
  89.      *
  90.      * @return bool TRUE on success, FALSE on failure.
  91.      */
  92.     public function bindValue($param$value$type ParameterType::STRING)
  93.     {
  94.         $this->params[$param] = $value;
  95.         $this->types[$param]  = $type;
  96.         if ($type !== null) {
  97.             if (is_string($type)) {
  98.                 $type Type::getType($type);
  99.             }
  100.             if ($type instanceof Type) {
  101.                 $value       $type->convertToDatabaseValue($value$this->platform);
  102.                 $bindingType $type->getBindingType();
  103.             } else {
  104.                 $bindingType $type;
  105.             }
  106.             return $this->stmt->bindValue($param$value$bindingType);
  107.         }
  108.         return $this->stmt->bindValue($param$value);
  109.     }
  110.     /**
  111.      * Binds a parameter to a value by reference.
  112.      *
  113.      * Binding a parameter by reference does not support DBAL mapping types.
  114.      *
  115.      * @param string|int $param    The name or position of the parameter.
  116.      * @param mixed      $variable The reference to the variable to bind.
  117.      * @param int        $type     The PDO binding type.
  118.      * @param int|null   $length   Must be specified when using an OUT bind
  119.      *                             so that PHP allocates enough memory to hold the returned value.
  120.      *
  121.      * @return bool TRUE on success, FALSE on failure.
  122.      */
  123.     public function bindParam($param, &$variable$type ParameterType::STRING$length null)
  124.     {
  125.         $this->params[$param] = $variable;
  126.         $this->types[$param]  = $type;
  127.         if ($this->stmt instanceof PDOStatement) {
  128.             $length $length ?? 0;
  129.         }
  130.         return $this->stmt->bindParam($param$variable$type$length);
  131.     }
  132.     /**
  133.      * Executes the statement with the currently bound parameters.
  134.      *
  135.      * @deprecated Statement::execute() is deprecated, use Statement::executeQuery() or executeStatement() instead
  136.      *
  137.      * @param mixed[]|null $params
  138.      *
  139.      * @return bool TRUE on success, FALSE on failure.
  140.      *
  141.      * @throws Exception
  142.      */
  143.     public function execute($params null)
  144.     {
  145.         Deprecation::triggerIfCalledFromOutside(
  146.             'doctrine/dbal',
  147.             'https://github.com/doctrine/dbal/pull/4580',
  148.             'Statement::execute() is deprecated, use Statement::executeQuery() or Statement::executeStatement() instead'
  149.         );
  150.         if (is_array($params)) {
  151.             $this->params $params;
  152.         }
  153.         $logger $this->conn->getConfiguration()->getSQLLogger();
  154.         if ($logger) {
  155.             $logger->startQuery($this->sql$this->params$this->types);
  156.         }
  157.         try {
  158.             $stmt $this->stmt->execute($params);
  159.         } catch (Throwable $ex) {
  160.             if ($logger) {
  161.                 $logger->stopQuery();
  162.             }
  163.             $this->conn->handleExceptionDuringQuery($ex$this->sql$this->params$this->types);
  164.         }
  165.         if ($logger) {
  166.             $logger->stopQuery();
  167.         }
  168.         return $stmt;
  169.     }
  170.     /**
  171.      * Executes the statement with the currently bound parameters and return result.
  172.      *
  173.      * @param mixed[] $params
  174.      *
  175.      * @throws Exception
  176.      */
  177.     public function executeQuery(array $params = []): BaseResult
  178.     {
  179.         if ($params === []) {
  180.             $params null// Workaround as long execute() exists and used internally.
  181.         }
  182.         $this->execute($params);
  183.         return new ForwardCompatibility\Result($this);
  184.     }
  185.     /**
  186.      * Executes the statement with the currently bound parameters and return affected rows.
  187.      *
  188.      * @param mixed[] $params
  189.      *
  190.      * @throws Exception
  191.      */
  192.     public function executeStatement(array $params = []): int
  193.     {
  194.         if ($params === []) {
  195.             $params null// Workaround as long execute() exists and used internally.
  196.         }
  197.         $this->execute($params);
  198.         return $this->rowCount();
  199.     }
  200.     /**
  201.      * Closes the cursor, freeing the database resources used by this statement.
  202.      *
  203.      * @deprecated Use Result::free() instead.
  204.      *
  205.      * @return bool TRUE on success, FALSE on failure.
  206.      */
  207.     public function closeCursor()
  208.     {
  209.         Deprecation::triggerIfCalledFromOutside(
  210.             'doctrine/dbal',
  211.             'https://github.com/doctrine/dbal/pull/4049',
  212.             'Statement::closeCursor() is deprecated, use Result::free() instead.'
  213.         );
  214.         return $this->stmt->closeCursor();
  215.     }
  216.     /**
  217.      * Returns the number of columns in the result set.
  218.      *
  219.      * @return int
  220.      */
  221.     public function columnCount()
  222.     {
  223.         return $this->stmt->columnCount();
  224.     }
  225.     /**
  226.      * Fetches the SQLSTATE associated with the last operation on the statement.
  227.      *
  228.      * @deprecated The error information is available via exceptions.
  229.      *
  230.      * @return string|int|bool
  231.      */
  232.     public function errorCode()
  233.     {
  234.         Deprecation::triggerIfCalledFromOutside(
  235.             'doctrine/dbal',
  236.             'https://github.com/doctrine/dbal/pull/3507',
  237.             'Connection::errorCode() is deprecated, use getCode() or getSQLState() on Exception instead.'
  238.         );
  239.         return $this->stmt->errorCode();
  240.     }
  241.     /**
  242.      * {@inheritDoc}
  243.      *
  244.      * @deprecated The error information is available via exceptions.
  245.      */
  246.     public function errorInfo()
  247.     {
  248.         Deprecation::triggerIfCalledFromOutside(
  249.             'doctrine/dbal',
  250.             'https://github.com/doctrine/dbal/pull/3507',
  251.             'Connection::errorInfo() is deprecated, use getCode() or getSQLState() on Exception instead.'
  252.         );
  253.         return $this->stmt->errorInfo();
  254.     }
  255.     /**
  256.      * {@inheritdoc}
  257.      *
  258.      * @deprecated Use one of the fetch- or iterate-related methods.
  259.      */
  260.     public function setFetchMode($fetchMode$arg2 null$arg3 null)
  261.     {
  262.         Deprecation::triggerIfCalledFromOutside(
  263.             'doctrine/dbal',
  264.             'https://github.com/doctrine/dbal/pull/4019',
  265.             'Statement::setFetchMode() is deprecated, use explicit Result::fetch*() APIs instead.'
  266.         );
  267.         if ($arg2 === null) {
  268.             return $this->stmt->setFetchMode($fetchMode);
  269.         }
  270.         if ($arg3 === null) {
  271.             return $this->stmt->setFetchMode($fetchMode$arg2);
  272.         }
  273.         return $this->stmt->setFetchMode($fetchMode$arg2$arg3);
  274.     }
  275.     /**
  276.      * Required by interface IteratorAggregate.
  277.      *
  278.      * @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
  279.      *
  280.      * {@inheritdoc}
  281.      */
  282.     #[ReturnTypeWillChange]
  283.     public function getIterator()
  284.     {
  285.         Deprecation::trigger(
  286.             'doctrine/dbal',
  287.             'https://github.com/doctrine/dbal/pull/4019',
  288.             'Statement::getIterator() is deprecated, use Result::iterateNumeric(), iterateAssociative() ' .
  289.             'or iterateColumn() instead.'
  290.         );
  291.         return $this->stmt;
  292.     }
  293.     /**
  294.      * {@inheritdoc}
  295.      *
  296.      * @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
  297.      */
  298.     public function fetch($fetchMode null$cursorOrientation PDO::FETCH_ORI_NEXT$cursorOffset 0)
  299.     {
  300.         Deprecation::triggerIfCalledFromOutside(
  301.             'doctrine/dbal',
  302.             'https://github.com/doctrine/dbal/pull/4019',
  303.             'Statement::fetch() is deprecated, use Result::fetchNumeric(), fetchAssociative() or fetchOne() instead.'
  304.         );
  305.         return $this->stmt->fetch(...func_get_args());
  306.     }
  307.     /**
  308.      * {@inheritdoc}
  309.      *
  310.      * @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
  311.      */
  312.     public function fetchAll($fetchMode null$fetchArgument null$ctorArgs null)
  313.     {
  314.         Deprecation::triggerIfCalledFromOutside(
  315.             'doctrine/dbal',
  316.             'https://github.com/doctrine/dbal/pull/4019',
  317.             'Statement::fetchAll() is deprecated, use Result::fetchAllNumeric(), fetchAllAssociative() or ' .
  318.             'fetchFirstColumn() instead.'
  319.         );
  320.         if ($ctorArgs !== null) {
  321.             return $this->stmt->fetchAll($fetchMode$fetchArgument$ctorArgs);
  322.         }
  323.         if ($fetchArgument !== null) {
  324.             return $this->stmt->fetchAll($fetchMode$fetchArgument);
  325.         }
  326.         return $this->stmt->fetchAll($fetchMode);
  327.     }
  328.     /**
  329.      * {@inheritDoc}
  330.      *
  331.      * @deprecated Use fetchOne() instead.
  332.      */
  333.     public function fetchColumn($columnIndex 0)
  334.     {
  335.         Deprecation::triggerIfCalledFromOutside(
  336.             'doctrine/dbal',
  337.             'https://github.com/doctrine/dbal/pull/4019',
  338.             'Statement::fetchColumn() is deprecated, use Result::fetchOne() instead.'
  339.         );
  340.         return $this->stmt->fetchColumn($columnIndex);
  341.     }
  342.     /**
  343.      * {@inheritdoc}
  344.      *
  345.      * @deprecated Use Result::fetchNumeric() instead
  346.      *
  347.      * @throws Exception
  348.      */
  349.     public function fetchNumeric()
  350.     {
  351.         Deprecation::triggerIfCalledFromOutside(
  352.             'doctrine/dbal',
  353.             'https://github.com/doctrine/dbal/issues/4554',
  354.             'Statement::%s() is deprecated, use Result::%s() instead.',
  355.             __FUNCTION__,
  356.             __FUNCTION__
  357.         );
  358.         try {
  359.             if ($this->stmt instanceof Result) {
  360.                 return $this->stmt->fetchNumeric();
  361.             }
  362.             return $this->stmt->fetch(FetchMode::NUMERIC);
  363.         } catch (Exception $e) {
  364.             $this->conn->handleDriverException($e);
  365.         }
  366.     }
  367.     /**
  368.      * {@inheritdoc}
  369.      *
  370.      * @deprecated Use Result::fetchAssociative() instead
  371.      *
  372.      * @throws Exception
  373.      */
  374.     public function fetchAssociative()
  375.     {
  376.         Deprecation::triggerIfCalledFromOutside(
  377.             'doctrine/dbal',
  378.             'https://github.com/doctrine/dbal/issues/4554',
  379.             'Statement::%s() is deprecated, use Result::%s() instead.',
  380.             __FUNCTION__,
  381.             __FUNCTION__
  382.         );
  383.         try {
  384.             if ($this->stmt instanceof Result) {
  385.                 return $this->stmt->fetchAssociative();
  386.             }
  387.             return $this->stmt->fetch(FetchMode::ASSOCIATIVE);
  388.         } catch (Exception $e) {
  389.             $this->conn->handleDriverException($e);
  390.         }
  391.     }
  392.     /**
  393.      * {@inheritDoc}
  394.      *
  395.      * @deprecated Use Result::fetchOne() instead
  396.      *
  397.      * @throws Exception
  398.      */
  399.     public function fetchOne()
  400.     {
  401.         Deprecation::triggerIfCalledFromOutside(
  402.             'doctrine/dbal',
  403.             'https://github.com/doctrine/dbal/issues/4554',
  404.             'Statement::%s() is deprecated, use Result::%s() instead.',
  405.             __FUNCTION__,
  406.             __FUNCTION__
  407.         );
  408.         try {
  409.             if ($this->stmt instanceof Result) {
  410.                 return $this->stmt->fetchOne();
  411.             }
  412.             return $this->stmt->fetch(FetchMode::COLUMN);
  413.         } catch (Exception $e) {
  414.             $this->conn->handleDriverException($e);
  415.         }
  416.     }
  417.     /**
  418.      * {@inheritdoc}
  419.      *
  420.      * @deprecated Use Result::fetchAllNumeric() instead
  421.      *
  422.      * @throws Exception
  423.      */
  424.     public function fetchAllNumeric(): array
  425.     {
  426.         Deprecation::triggerIfCalledFromOutside(
  427.             'doctrine/dbal',
  428.             'https://github.com/doctrine/dbal/issues/4554',
  429.             'Statement::%s() is deprecated, use Result::%s() instead.',
  430.             __FUNCTION__,
  431.             __FUNCTION__
  432.         );
  433.         try {
  434.             if ($this->stmt instanceof Result) {
  435.                 return $this->stmt->fetchAllNumeric();
  436.             }
  437.             return $this->stmt->fetchAll(FetchMode::NUMERIC);
  438.         } catch (Exception $e) {
  439.             $this->conn->handleDriverException($e);
  440.         }
  441.     }
  442.     /**
  443.      * {@inheritdoc}
  444.      *
  445.      * @deprecated Use Result::fetchAllAssociative() instead
  446.      *
  447.      * @throws Exception
  448.      */
  449.     public function fetchAllAssociative(): array
  450.     {
  451.         Deprecation::triggerIfCalledFromOutside(
  452.             'doctrine/dbal',
  453.             'https://github.com/doctrine/dbal/issues/4554',
  454.             'Statement::%s() is deprecated, use Result::%s() instead.',
  455.             __FUNCTION__,
  456.             __FUNCTION__
  457.         );
  458.         try {
  459.             if ($this->stmt instanceof Result) {
  460.                 return $this->stmt->fetchAllAssociative();
  461.             }
  462.             return $this->stmt->fetchAll(FetchMode::ASSOCIATIVE);
  463.         } catch (Exception $e) {
  464.             $this->conn->handleDriverException($e);
  465.         }
  466.     }
  467.     /**
  468.      * Returns an associative array with the keys mapped to the first column and the values mapped to the second column.
  469.      *
  470.      * The result must contain at least two columns.
  471.      *
  472.      * @deprecated Use Result::fetchAllKeyValue() instead
  473.      *
  474.      * @return array<mixed,mixed>
  475.      *
  476.      * @throws Exception
  477.      */
  478.     public function fetchAllKeyValue(): array
  479.     {
  480.         Deprecation::triggerIfCalledFromOutside(
  481.             'doctrine/dbal',
  482.             'https://github.com/doctrine/dbal/issues/4554',
  483.             'Statement::%s() is deprecated, use Result::%s() instead.',
  484.             __FUNCTION__,
  485.             __FUNCTION__
  486.         );
  487.         $this->ensureHasKeyValue();
  488.         $data = [];
  489.         foreach ($this->fetchAllNumeric() as [$key$value]) {
  490.             $data[$key] = $value;
  491.         }
  492.         return $data;
  493.     }
  494.     /**
  495.      * Returns an associative array with the keys mapped to the first column and the values being
  496.      * an associative array representing the rest of the columns and their values.
  497.      *
  498.      * @deprecated Use Result::fetchAllAssociativeIndexed() instead
  499.      *
  500.      * @return array<mixed,array<string,mixed>>
  501.      *
  502.      * @throws Exception
  503.      */
  504.     public function fetchAllAssociativeIndexed(): array
  505.     {
  506.         Deprecation::triggerIfCalledFromOutside(
  507.             'doctrine/dbal',
  508.             'https://github.com/doctrine/dbal/issues/4554',
  509.             'Statement::%s() is deprecated, use Result::%s() instead.',
  510.             __FUNCTION__,
  511.             __FUNCTION__
  512.         );
  513.         $data = [];
  514.         foreach ($this->fetchAll(FetchMode::ASSOCIATIVE) as $row) {
  515.             $data[array_shift($row)] = $row;
  516.         }
  517.         return $data;
  518.     }
  519.     /**
  520.      * {@inheritdoc}
  521.      *
  522.      * @deprecated Use Result::fetchFirstColumn() instead
  523.      *
  524.      * @throws Exception
  525.      */
  526.     public function fetchFirstColumn(): array
  527.     {
  528.         Deprecation::triggerIfCalledFromOutside(
  529.             'doctrine/dbal',
  530.             'https://github.com/doctrine/dbal/issues/4554',
  531.             'Statement::%s() is deprecated, use Result::%s() instead.',
  532.             __FUNCTION__,
  533.             __FUNCTION__
  534.         );
  535.         try {
  536.             if ($this->stmt instanceof Result) {
  537.                 return $this->stmt->fetchFirstColumn();
  538.             }
  539.             return $this->stmt->fetchAll(FetchMode::COLUMN);
  540.         } catch (Exception $e) {
  541.             $this->conn->handleDriverException($e);
  542.         }
  543.     }
  544.     /**
  545.      * {@inheritDoc}
  546.      *
  547.      * @deprecated Use Result::iterateNumeric() instead
  548.      *
  549.      * @return Traversable<int,array<int,mixed>>
  550.      *
  551.      * @throws Exception
  552.      */
  553.     public function iterateNumeric(): Traversable
  554.     {
  555.         Deprecation::triggerIfCalledFromOutside(
  556.             'doctrine/dbal',
  557.             'https://github.com/doctrine/dbal/issues/4554',
  558.             'Statement::%s() is deprecated, use Result::%s() instead.',
  559.             __FUNCTION__,
  560.             __FUNCTION__
  561.         );
  562.         try {
  563.             if ($this->stmt instanceof Result) {
  564.                 while (($row $this->stmt->fetchNumeric()) !== false) {
  565.                     yield $row;
  566.                 }
  567.             } else {
  568.                 while (($row $this->stmt->fetch(FetchMode::NUMERIC)) !== false) {
  569.                     yield $row;
  570.                 }
  571.             }
  572.         } catch (Exception $e) {
  573.             $this->conn->handleDriverException($e);
  574.         }
  575.     }
  576.     /**
  577.      * {@inheritDoc}
  578.      *
  579.      * @deprecated Use Result::iterateAssociative() instead
  580.      *
  581.      * @return Traversable<int,array<string,mixed>>
  582.      *
  583.      * @throws Exception
  584.      */
  585.     public function iterateAssociative(): Traversable
  586.     {
  587.         Deprecation::triggerIfCalledFromOutside(
  588.             'doctrine/dbal',
  589.             'https://github.com/doctrine/dbal/issues/4554',
  590.             'Statement::%s() is deprecated, use Result::%s() instead.',
  591.             __FUNCTION__,
  592.             __FUNCTION__
  593.         );
  594.         try {
  595.             if ($this->stmt instanceof Result) {
  596.                 while (($row $this->stmt->fetchAssociative()) !== false) {
  597.                     yield $row;
  598.                 }
  599.             } else {
  600.                 while (($row $this->stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) {
  601.                     yield $row;
  602.                 }
  603.             }
  604.         } catch (Exception $e) {
  605.             $this->conn->handleDriverException($e);
  606.         }
  607.     }
  608.     /**
  609.      * Returns an iterator over the result set with the keys mapped to the first column
  610.      * and the values mapped to the second column.
  611.      *
  612.      * The result must contain at least two columns.
  613.      *
  614.      * @deprecated Use Result::iterateKeyValue() instead
  615.      *
  616.      * @return Traversable<mixed,mixed>
  617.      *
  618.      * @throws Exception
  619.      */
  620.     public function iterateKeyValue(): Traversable
  621.     {
  622.         Deprecation::triggerIfCalledFromOutside(
  623.             'doctrine/dbal',
  624.             'https://github.com/doctrine/dbal/issues/4554',
  625.             'Statement::%s() is deprecated, use Result::%s() instead.',
  626.             __FUNCTION__,
  627.             __FUNCTION__
  628.         );
  629.         $this->ensureHasKeyValue();
  630.         foreach ($this->iterateNumeric() as [$key$value]) {
  631.             yield $key => $value;
  632.         }
  633.     }
  634.     /**
  635.      * Returns an iterator over the result set with the keys mapped to the first column and the values being
  636.      * an associative array representing the rest of the columns and their values.
  637.      *
  638.      * @deprecated Use Result::iterateAssociativeIndexed() instead
  639.      *
  640.      * @return Traversable<mixed,array<string,mixed>>
  641.      *
  642.      * @throws Exception
  643.      */
  644.     public function iterateAssociativeIndexed(): Traversable
  645.     {
  646.         Deprecation::triggerIfCalledFromOutside(
  647.             'doctrine/dbal',
  648.             'https://github.com/doctrine/dbal/issues/4554',
  649.             'Statement::%s() is deprecated, use Result::%s() instead.',
  650.             __FUNCTION__,
  651.             __FUNCTION__
  652.         );
  653.         while (($row $this->stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) {
  654.             yield array_shift($row) => $row;
  655.         }
  656.     }
  657.     /**
  658.      * {@inheritDoc}
  659.      *
  660.      * @deprecated Use Result::iterateColumn() instead
  661.      *
  662.      * @return Traversable<int,mixed>
  663.      *
  664.      * @throws Exception
  665.      */
  666.     public function iterateColumn(): Traversable
  667.     {
  668.         Deprecation::triggerIfCalledFromOutside(
  669.             'doctrine/dbal',
  670.             'https://github.com/doctrine/dbal/issues/4554',
  671.             'Statement::%s() is deprecated, use Result::%s() instead.',
  672.             __FUNCTION__,
  673.             __FUNCTION__
  674.         );
  675.         try {
  676.             if ($this->stmt instanceof Result) {
  677.                 while (($value $this->stmt->fetchOne()) !== false) {
  678.                     yield $value;
  679.                 }
  680.             } else {
  681.                 while (($value $this->stmt->fetch(FetchMode::COLUMN)) !== false) {
  682.                     yield $value;
  683.                 }
  684.             }
  685.         } catch (Exception $e) {
  686.             $this->conn->handleDriverException($e);
  687.         }
  688.     }
  689.     /**
  690.      * Returns the number of rows affected by the last execution of this statement.
  691.      *
  692.      * @return int|string The number of affected rows.
  693.      */
  694.     public function rowCount()
  695.     {
  696.         return $this->stmt->rowCount();
  697.     }
  698.     public function free(): void
  699.     {
  700.         if ($this->stmt instanceof Result) {
  701.             $this->stmt->free();
  702.             return;
  703.         }
  704.         $this->stmt->closeCursor();
  705.     }
  706.     /**
  707.      * Gets the wrapped driver statement.
  708.      *
  709.      * @return \Doctrine\DBAL\Driver\Statement
  710.      */
  711.     public function getWrappedStatement()
  712.     {
  713.         return $this->stmt;
  714.     }
  715.     private function ensureHasKeyValue(): void
  716.     {
  717.         $columnCount $this->columnCount();
  718.         if ($columnCount 2) {
  719.             throw NoKeyValue::fromColumnCount($columnCount);
  720.         }
  721.     }
  722. }