[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/includes/vendor/aura/sql/src/ -> AbstractExtendedPdo.php (source)

   1  <?php
   2  /**
   3   *
   4   * This file is part of Aura for PHP.
   5   *
   6   * @license https://opensource.org/licenses/MIT MIT
   7   *
   8   */
   9  namespace Aura\Sql;
  10  
  11  use Aura\Sql\Parser\ParserInterface;
  12  use Aura\Sql\Profiler\ProfilerInterface;
  13  use BadMethodCallException;
  14  use Generator;
  15  use PDO;
  16  use PDOStatement;
  17  
  18  /**
  19   *
  20   * Provides array quoting, profiling, a new `perform()` method, new `fetch*()`
  21   * methods, and new `yield*()` methods.
  22   *
  23   * @package Aura.Sql
  24   *
  25   */
  26  abstract class AbstractExtendedPdo extends PDO implements ExtendedPdoInterface
  27  {
  28      /**
  29       *
  30       * The internal PDO connection.
  31       *
  32       * @var PDO|null
  33       *
  34       */
  35      protected ?PDO $pdo = null;
  36  
  37      /**
  38       *
  39       * Tracks and logs query profiles.
  40       *
  41       * @var ProfilerInterface
  42       *
  43       */
  44      protected ProfilerInterface $profiler;
  45  
  46      /**
  47       *
  48       * Parses queries to rebuild them for easier parameter binding.
  49       *
  50       * @var ParserInterface
  51       *
  52       */
  53      protected ParserInterface $parser;
  54  
  55      /**
  56       *
  57       * Prefix to use when quoting identifier names.
  58       *
  59       * @var string
  60       *
  61       */
  62      protected string $quoteNamePrefix = '"';
  63  
  64      /**
  65       *
  66       * Suffix to use when quoting identifier names.
  67       *
  68       * @var string
  69       *
  70       */
  71      protected string $quoteNameSuffix = '"';
  72  
  73      /**
  74       *
  75       * Find this string when escaping identifier names.
  76       *
  77       * @var string
  78       *
  79       */
  80      protected string $quoteNameEscapeFind = '"';
  81  
  82      /**
  83       *
  84       * Use this as the replacement when escaping identifier names.
  85       *
  86       * @var string
  87       *
  88       */
  89      protected string $quoteNameEscapeRepl = '""';
  90  
  91      /**
  92       *
  93       * Proxies to PDO methods created for specific drivers; in particular,
  94       * `sqlite` and `pgsql`.
  95       *
  96       * @param string $name The PDO method to call; e.g. `sqliteCreateFunction`
  97       * or `pgsqlGetPid`.
  98       *
  99       * @param array $arguments Arguments to pass to the called method.
 100       *
 101       * @return mixed
 102       *
 103       * @throws BadMethodCallException when the method does not exist.
 104       *
 105       */
 106      public function __call(string $name, array $arguments)
 107      {
 108          $this->lazyConnect();
 109  
 110          if (! method_exists($this->pdo, $name)) {
 111              $class = get_class($this);
 112              $message = "Class '$class' does not have a method '$name'";
 113              throw new BadMethodCallException($message);
 114          }
 115  
 116          return call_user_func_array([$this->pdo, $name], $arguments);
 117      }
 118  
 119      /**
 120       *
 121       * Begins a transaction and turns off autocommit mode.
 122       *
 123       * @return bool True on success, false on failure.
 124       *
 125       * @see http://php.net/manual/en/pdo.begintransaction.php
 126       *
 127       */
 128      public function beginTransaction(): bool
 129      {
 130          $this->lazyConnect();
 131          $this->profiler->start(__FUNCTION__);
 132          $result = $this->pdo->beginTransaction();
 133          $this->profiler->finish();
 134          return $result;
 135      }
 136  
 137      /**
 138       *
 139       * Commits the existing transaction and restores autocommit mode.
 140       *
 141       * @return bool True on success, false on failure.
 142       *
 143       * @see http://php.net/manual/en/pdo.commit.php
 144       *
 145       */
 146      public function commit(): bool
 147      {
 148          $this->lazyConnect();
 149          $this->profiler->start(__FUNCTION__);
 150          $result = $this->pdo->commit();
 151          $this->profiler->finish();
 152          return $result;
 153      }
 154  
 155      /**
 156       *
 157       * Connects to the database.
 158       *
 159       * @return void
 160       */
 161      abstract public function lazyConnect(): void;
 162  
 163      /**
 164       *
 165       * Disconnects from the database.
 166       *
 167       * @return void
 168       */
 169      abstract public function disconnect(): void;
 170  
 171      /**
 172       *
 173       * Gets the most recent error code.
 174       *
 175       * @return string|null
 176       *
 177       */
 178      public function errorCode(): ?string
 179      {
 180          $this->lazyConnect();
 181          return $this->pdo->errorCode();
 182      }
 183  
 184      /**
 185       *
 186       * Gets the most recent error info.
 187       *
 188       * @return array
 189       *
 190       */
 191      public function errorInfo(): array
 192      {
 193          $this->lazyConnect();
 194          return $this->pdo->errorInfo();
 195      }
 196  
 197      /**
 198       *
 199       * Executes an SQL statement and returns the number of affected rows.
 200       *
 201       * @param string $statement The SQL statement to prepare and execute.
 202       *
 203       * @return int|false The number of affected rows.
 204       *
 205       * @see http://php.net/manual/en/pdo.exec.php
 206       *
 207       */
 208      public function exec(string $statement): int|false
 209      {
 210          $this->lazyConnect();
 211          $this->profiler->start(__FUNCTION__);
 212          $affectedRows = $this->pdo->exec($statement);
 213          $this->profiler->finish($statement);
 214          return $affectedRows;
 215      }
 216  
 217      /**
 218       *
 219       * Performs a statement and returns the number of affected rows.
 220       *
 221       * @param string $statement The SQL statement to prepare and execute.
 222       *
 223       * @param array $values Values to bind to the query.
 224       *
 225       * @return int
 226       *
 227       */
 228      public function fetchAffected(string $statement, array $values = []): int
 229      {
 230          $sth = $this->perform($statement, $values);
 231          return $sth->rowCount();
 232      }
 233  
 234      /**
 235       *
 236       * Fetches a sequential array of rows from the database; the rows
 237       * are returned as associative arrays.
 238       *
 239       * @param string $statement The SQL statement to prepare and execute.
 240       *
 241       * @param array $values Values to bind to the query.
 242       *
 243       * @return array
 244       *
 245       */
 246      public function fetchAll(string $statement, array $values = []): array
 247      {
 248          $sth = $this->perform($statement, $values);
 249          return $sth->fetchAll(self::FETCH_ASSOC);
 250      }
 251  
 252      /**
 253       *
 254       * Fetches an associative array of rows from the database; the rows
 255       * are returned as associative arrays, and the array of rows is keyed
 256       * on the first column of each row.
 257       *
 258       * N.b.: If multiple rows have the same first column value, the last
 259       * row with that value will override earlier rows.
 260       *
 261       * @param string $statement The SQL statement to prepare and execute.
 262       *
 263       * @param array $values Values to bind to the query.
 264       *
 265       * @return array
 266       *
 267       */
 268      public function fetchAssoc(string $statement, array $values = []): array
 269      {
 270          $sth  = $this->perform($statement, $values);
 271          $data = [];
 272          while ($row = $sth->fetch(self::FETCH_ASSOC)) {
 273              $data[current($row)] = $row;
 274          }
 275          return $data;
 276      }
 277  
 278      /**
 279       *
 280       * Fetches the first column of rows as a sequential array.
 281       *
 282       * @param string $statement The SQL statement to prepare and execute.
 283       *
 284       * @param array $values Values to bind to the query.
 285       *
 286       * @return array
 287       *
 288       */
 289      public function fetchCol(string $statement, array $values = []): array
 290      {
 291          $sth = $this->perform($statement, $values);
 292          return $sth->fetchAll(self::FETCH_COLUMN, 0);
 293      }
 294  
 295      /**
 296       *
 297       * Fetches multiple from the database as an associative array. The first
 298       * column will be the index key.
 299       *
 300       * @param string $statement The SQL statement to prepare and execute.
 301       *
 302       * @param array $values Values to bind to the query.
 303       *
 304       * @param int $style a fetch style defaults to PDO::FETCH_COLUMN for single
 305       * values, use PDO::FETCH_NAMED when fetching a multiple columns
 306       *
 307       * @return array
 308       *
 309       */
 310      public function fetchGroup(
 311          string $statement,
 312          array $values = [],
 313          int $style = PDO::FETCH_COLUMN
 314      ): array {
 315          $sth = $this->perform($statement, $values);
 316          return $sth->fetchAll(self::FETCH_GROUP | $style);
 317      }
 318  
 319      /**
 320       *
 321       * Fetches one row from the database as an object where the column values
 322       * are mapped to object properties.
 323       *
 324       * Warning: PDO "injects property-values BEFORE invoking the constructor -
 325       * in other words, if your class initializes property-values to defaults
 326       * in the constructor, you will be overwriting the values injected by
 327       * fetchObject() !"
 328       *
 329       * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
 330       *
 331       * @param string $statement The SQL statement to prepare and execute.
 332       *
 333       * @param array $values Values to bind to the query.
 334       *
 335       * @param string $class The name of the class to create.
 336       *
 337       * @param array $args Arguments to pass to the object constructor.
 338       *
 339       * @return object
 340       *
 341       */
 342      public function fetchObject(
 343          string $statement,
 344          array $values = [],
 345          string $class = 'stdClass',
 346          array $args = []
 347      ): object|false {
 348          $sth = $this->perform($statement, $values);
 349  
 350          if (! empty($args)) {
 351              return $sth->fetchObject($class, $args);
 352          }
 353  
 354          return $sth->fetchObject($class);
 355      }
 356  
 357      /**
 358       *
 359       * Fetches a sequential array of rows from the database; the rows
 360       * are returned as objects where the column values are mapped to
 361       * object properties.
 362       *
 363       * Warning: PDO "injects property-values BEFORE invoking the constructor -
 364       * in other words, if your class initializes property-values to defaults
 365       * in the constructor, you will be overwriting the values injected by
 366       * fetchObject() !"
 367       *
 368       * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
 369       *
 370       * @param string $statement The SQL statement to prepare and execute.
 371       *
 372       * @param array $values Values to bind to the query.
 373       *
 374       * @param string $class The name of the class to create from each
 375       * row.
 376       *
 377       * @param array $args Arguments to pass to each object constructor.
 378       *
 379       * @return array
 380       *
 381       */
 382      public function fetchObjects(
 383          string $statement,
 384          array $values = [],
 385          string $class = 'stdClass',
 386          array $args = []
 387      ): array {
 388          $sth = $this->perform($statement, $values);
 389  
 390          if (! empty($args)) {
 391              return $sth->fetchAll(self::FETCH_CLASS, $class, $args);
 392          }
 393  
 394          return $sth->fetchAll(self::FETCH_CLASS, $class);
 395      }
 396  
 397      /**
 398       *
 399       * Fetches one row from the database as an associative array.
 400       *
 401       * @param string $statement The SQL statement to prepare and execute.
 402       *
 403       * @param array $values Values to bind to the query.
 404       *
 405       * @return array|false
 406       *
 407       */
 408      public function fetchOne(string $statement, array $values = []): array|false
 409      {
 410          $sth = $this->perform($statement, $values);
 411          return $sth->fetch(self::FETCH_ASSOC);
 412      }
 413  
 414      /**
 415       *
 416       * Fetches an associative array of rows as key-value pairs (first
 417       * column is the key, second column is the value).
 418       *
 419       * @param string $statement The SQL statement to prepare and execute.
 420       *
 421       * @param array $values Values to bind to the query.
 422       *
 423       * @return array
 424       *
 425       */
 426      public function fetchPairs(string $statement, array $values = []): array
 427      {
 428          $sth = $this->perform($statement, $values);
 429          return $sth->fetchAll(self::FETCH_KEY_PAIR);
 430      }
 431  
 432      /**
 433       *
 434       * Fetches the very first value (i.e., first column of the first row).
 435       *
 436       * @param string $statement The SQL statement to prepare and execute.
 437       *
 438       * @param array $values Values to bind to the query.
 439       *
 440       * @return mixed
 441       *
 442       */
 443      public function fetchValue(string $statement, array $values = []): mixed
 444      {
 445          $sth = $this->perform($statement, $values);
 446          return $sth->fetchColumn(0);
 447      }
 448  
 449      /**
 450       *
 451       * Returns the Parser instance.
 452       *
 453       * @return ParserInterface
 454       *
 455       */
 456      public function getParser(): ParserInterface
 457      {
 458          return $this->parser;
 459      }
 460  
 461      /**
 462       *
 463       * Return the inner PDO (if any)
 464       *
 465       * @return \PDO
 466       *
 467       */
 468      public function getPdo(): PDO
 469      {
 470          return $this->pdo;
 471      }
 472  
 473      /**
 474       *
 475       * Returns the Profiler instance.
 476       *
 477       * @return ProfilerInterface
 478       *
 479       */
 480      public function getProfiler(): ProfilerInterface
 481      {
 482          return $this->profiler;
 483      }
 484  
 485      /**
 486       *
 487       * Is a transaction currently active?
 488       *
 489       * @return bool
 490       *
 491       * @see http://php.net/manual/en/pdo.intransaction.php
 492       *
 493       */
 494      public function inTransaction(): bool
 495      {
 496          $this->lazyConnect();
 497          $this->profiler->start(__FUNCTION__);
 498          $result = $this->pdo->inTransaction();
 499          $this->profiler->finish();
 500          return $result;
 501      }
 502  
 503      /**
 504       *
 505       * Is the PDO connection active?
 506       *
 507       * @return bool
 508       *
 509       */
 510      public function isConnected(): bool
 511      {
 512          return (bool) $this->pdo;
 513      }
 514  
 515      /**
 516       *
 517       * Returns the last inserted autoincrement sequence value.
 518       *
 519       * @param string|null $name The name of the sequence to check; typically needed
 520       * only for PostgreSQL, where it takes the form of `<table>_<column>_seq`.
 521       *
 522       * @return string|false
 523       *
 524       * @see http://php.net/manual/en/pdo.lastinsertid.php
 525       */
 526      public function lastInsertId(?string $name = null): string|false
 527      {
 528          $this->lazyConnect();
 529          $this->profiler->start(__FUNCTION__);
 530          $result = $this->pdo->lastInsertId($name);
 531          $this->profiler->finish();
 532          return $result;
 533      }
 534  
 535      /**
 536       *
 537       * Performs a query with bound values and returns the resulting
 538       * PDOStatement; array values will be passed through `quote()` and their
 539       * respective placeholders will be replaced in the query string.
 540       *
 541       * @param string $statement The SQL statement to perform.
 542       *
 543       * @param array $values Values to bind to the query
 544       *
 545       * @return PDOStatement
 546       *
 547       * @throws \Aura\Sql\Exception\CannotBindValue
 548       * @see quote()
 549       *
 550       */
 551      public function perform(string $statement, array $values = []): PDOStatement
 552      {
 553          $this->lazyConnect();
 554          $sth = $this->prepareWithValues($statement, $values);
 555          $this->profiler->start(__FUNCTION__);
 556          $sth->execute();
 557          $this->profiler->finish($statement, $values);
 558          return $sth;
 559      }
 560  
 561      /**
 562       *
 563       * Prepares an SQL statement for execution.
 564       *
 565       * @param string $query The SQL statement to prepare for execution.
 566       *
 567       * @param array $options Set these attributes on the returned
 568       * PDOStatement.
 569       *
 570       * @return PDOStatement|false
 571       *
 572       * @see http://php.net/manual/en/pdo.prepare.php
 573       *
 574       */
 575      public function prepare(string $query, array $options = []): PDOStatement|false
 576      {
 577          $this->lazyConnect();
 578          $sth = $this->pdo->prepare($query, $options);
 579          return $sth;
 580      }
 581  
 582      /**
 583       *
 584       * Prepares an SQL statement with bound values.
 585       *
 586       * This method only binds values that have placeholders in the
 587       * statement, thereby avoiding errors from PDO regarding too many bound
 588       * values. It also binds all sequential (question-mark) placeholders.
 589       *
 590       * If a placeholder value is an array, the array is converted to a string
 591       * of comma-separated quoted values; e.g., for an `IN (...)` condition.
 592       * The quoted string is replaced directly into the statement instead of
 593       * using `PDOStatement::bindValue()` proper.
 594       *
 595       * @param string $statement The SQL statement to prepare for execution.
 596       *
 597       * @param array $values The values to bind to the statement, if any.
 598       *
 599       * @return PDOStatement
 600       *
 601       * @throws \Aura\Sql\Exception\CannotBindValue
 602       * @see http://php.net/manual/en/pdo.prepare.php
 603       *
 604       */
 605      public function prepareWithValues(string $statement, array $values = []): PDOStatement
 606      {
 607          // if there are no values to bind ...
 608          if (empty($values)) {
 609              // ... use the normal preparation
 610              return $this->prepare($statement);
 611          }
 612  
 613          $this->lazyConnect();
 614  
 615          // rebuild the statement and values
 616          $parser = clone $this->parser;
 617          list($statement, $values) = $parser->rebuild($statement, $values);
 618  
 619          // prepare the statement
 620          $sth = $this->pdo->prepare($statement);
 621  
 622          // for the placeholders we found, bind the corresponding data values
 623          foreach ($values as $key => $val) {
 624              $this->bindValue($sth, $key, $val);
 625          }
 626  
 627          // done
 628          return $sth;
 629      }
 630  
 631      /**
 632       *
 633       * Queries the database and returns a PDOStatement.
 634       *
 635       * @param string $query The SQL statement to prepare and execute.
 636       *
 637       * @param int|null $fetchMode
 638       *
 639       * @param mixed ...$fetch_mode_args Optional fetch-related parameters.
 640       *
 641       * @return PDOStatement|false
 642       *
 643       * @see http://php.net/manual/en/pdo.query.php
 644       *
 645       */
 646      public function query(string $query, ?int $fetchMode = null, mixed ...$fetch_mode_args): PDOStatement|false
 647      {
 648          $this->lazyConnect();
 649          $this->profiler->start(__FUNCTION__);
 650          $sth = $this->pdo->query($query, $fetchMode, ...$fetch_mode_args);
 651          $this->profiler->finish($sth->queryString);
 652          return $sth;
 653      }
 654  
 655      /**
 656       *
 657       * Quotes a value for use in an SQL statement.
 658       *
 659       * This differs from `PDO::quote()` in that it will convert an array into
 660       * a string of comma-separated quoted values.
 661       *
 662       * @param string|int|array|float|null $value The value to quote.
 663       *
 664       * @param int $type A data type hint for the database driver.
 665       *
 666       * @return string|false The quoted value or false if the driver does not support quoting in this way.
 667       *
 668       * @see http://php.net/manual/en/pdo.quote.php
 669       *
 670       */
 671      public function quote(string|int|array|float|null $value, int $type = self::PARAM_STR): string|false
 672      {
 673          $this->lazyConnect();
 674  
 675          $value = $value ?? "";
 676  
 677          // non-array quoting
 678          if (! is_array($value)) {
 679              return $this->pdo->quote($value, $type);
 680          }
 681  
 682          // quote array values, not keys, then combine with commas
 683          foreach ($value as $k => $v) {
 684              $value[$k] = $this->pdo->quote($v, $type);
 685          }
 686          return implode(', ', $value);
 687      }
 688  
 689      /**
 690       *
 691       * Quotes a multi-part (dotted) identifier name.
 692       *
 693       * @param string $name The multi-part identifier name.
 694       *
 695       * @return string The multi-part identifier name, quoted.
 696       *
 697       */
 698      public function quoteName(string $name): string
 699      {
 700          if (! str_contains($name, '.')) {
 701              return $this->quoteSingleName($name);
 702          }
 703  
 704          return implode(
 705              '.',
 706              array_map(
 707                  [$this, 'quoteSingleName'],
 708                  explode('.', $name)
 709              )
 710          );
 711      }
 712  
 713      /**
 714       *
 715       * Quotes a single identifier name.
 716       *
 717       * @param string $name The identifier name.
 718       *
 719       * @return string The quoted identifier name.
 720       *
 721       */
 722      public function quoteSingleName(string $name): string
 723      {
 724          $name = str_replace(
 725              $this->quoteNameEscapeFind,
 726              $this->quoteNameEscapeRepl,
 727              $name
 728          );
 729          return $this->quoteNamePrefix
 730              . $name
 731              . $this->quoteNameSuffix;
 732      }
 733  
 734      /**
 735       *
 736       * Rolls back the current transaction, and restores autocommit mode.
 737       *
 738       * @return bool True on success, false on failure.
 739       *
 740       * @see http://php.net/manual/en/pdo.rollback.php
 741       *
 742       */
 743      public function rollBack(): bool
 744      {
 745          $this->lazyConnect();
 746          $this->profiler->start(__FUNCTION__);
 747          $result = $this->pdo->rollBack();
 748          $this->profiler->finish();
 749          return $result;
 750      }
 751  
 752      /**
 753       *
 754       * Sets the Parser instance.
 755       *
 756       * @param ParserInterface $parser The Parser instance.
 757       *
 758       */
 759      public function setParser(ParserInterface $parser): void
 760      {
 761          $this->parser = $parser;
 762      }
 763  
 764      /**
 765       *
 766       * Sets the Profiler instance.
 767       *
 768       * @param ProfilerInterface $profiler The Profiler instance.
 769       *
 770       */
 771      public function setProfiler(ProfilerInterface $profiler): void
 772      {
 773          $this->profiler = $profiler;
 774      }
 775  
 776      /**
 777       *
 778       * Yields rows from the database.
 779       *
 780       * @param string $statement The SQL statement to prepare and execute.
 781       *
 782       * @param array $values Values to bind to the query.
 783       *
 784       * @return \Generator
 785       *
 786       */
 787      public function yieldAll(string $statement, array $values = []): Generator
 788      {
 789          $sth = $this->perform($statement, $values);
 790          while ($row = $sth->fetch(self::FETCH_ASSOC)) {
 791              yield $row;
 792          }
 793      }
 794  
 795      /**
 796       *
 797       * Yields rows from the database keyed on the first column of each row.
 798       *
 799       * @param string $statement The SQL statement to prepare and execute.
 800       *
 801       * @param array $values Values to bind to the query.
 802       *
 803       * @return \Generator
 804       *
 805       */
 806      public function yieldAssoc(string $statement, array $values = []): Generator
 807      {
 808          $sth = $this->perform($statement, $values);
 809          while ($row = $sth->fetch(self::FETCH_ASSOC)) {
 810              $key = current($row);
 811              yield $key => $row;
 812          }
 813      }
 814  
 815      /**
 816       *
 817       * Yields the first column of each row.
 818       *
 819       * @param string $statement The SQL statement to prepare and execute.
 820       *
 821       * @param array $values Values to bind to the query.
 822       *
 823       * @return \Generator
 824       *
 825       */
 826      public function yieldCol(string $statement, array $values = []): Generator
 827      {
 828          $sth = $this->perform($statement, $values);
 829          while ($row = $sth->fetch(self::FETCH_NUM)) {
 830              yield $row[0];
 831          }
 832      }
 833  
 834      /**
 835       *
 836       * Yields objects where the column values are mapped to object properties.
 837       *
 838       * Warning: PDO "injects property-values BEFORE invoking the constructor -
 839       * in other words, if your class initializes property-values to defaults
 840       * in the constructor, you will be overwriting the values injected by
 841       * fetchObject() !"
 842       * <http://www.php.net/manual/en/pdostatement.fetchobject.php#111744>
 843       *
 844       * @param string $statement The SQL statement to prepare and execute.
 845       *
 846       * @param array $values Values to bind to the query.
 847       *
 848       * @param string $class The name of the class to create from each
 849       * row.
 850       *
 851       * @param array $args Arguments to pass to each object constructor.
 852       *
 853       * @return \Generator
 854       *
 855       */
 856      public function yieldObjects(
 857          string $statement,
 858          array $values = [],
 859          string $class = 'stdClass',
 860          array $args = []
 861      ): Generator {
 862          $sth = $this->perform($statement, $values);
 863  
 864          if (empty($args)) {
 865              while ($instance = $sth->fetchObject($class)) {
 866                  yield $instance;
 867              }
 868          } else {
 869              while ($instance = $sth->fetchObject($class, $args)) {
 870                  yield $instance;
 871              }
 872          }
 873      }
 874  
 875      /**
 876       *
 877       * Yields key-value pairs (first column is the key, second column is the
 878       * value).
 879       *
 880       * @param string $statement The SQL statement to prepare and execute.
 881       *
 882       * @param array $values Values to bind to the query.
 883       *
 884       * @return \Generator
 885       *
 886       */
 887      public function yieldPairs(string $statement, array $values = []): Generator
 888      {
 889          $sth = $this->perform($statement, $values);
 890          while ($row = $sth->fetch(self::FETCH_NUM)) {
 891              yield $row[0] => $row[1];
 892          }
 893      }
 894  
 895      /**
 896       *
 897       * Bind a value using the proper PDO::PARAM_* type.
 898       *
 899       * @param PDOStatement $sth The statement to bind to.
 900       *
 901       * @param mixed $key The placeholder key.
 902       *
 903       * @param mixed $val The value to bind to the statement.
 904       *
 905       * @return bool
 906       *
 907       * @throws Exception\CannotBindValue when the value to be bound is not
 908       * bindable (e.g., array, object, or resource).
 909       *
 910       */
 911      protected function bindValue(PDOStatement $sth, mixed $key, mixed $val): bool
 912      {
 913          if (is_int($val)) {
 914              return $sth->bindValue($key, $val, self::PARAM_INT);
 915          }
 916  
 917          if (is_bool($val)) {
 918              return $sth->bindValue($key, $val, self::PARAM_BOOL);
 919          }
 920  
 921          if (is_null($val)) {
 922              return $sth->bindValue($key, $val, self::PARAM_NULL);
 923          }
 924  
 925          if (! is_scalar($val)) {
 926              $type = gettype($val);
 927              throw new Exception\CannotBindValue(
 928                  "Cannot bind value of type '{$type}' to placeholder '{$key}'"
 929              );
 930          }
 931  
 932          return $sth->bindValue($key, $val);
 933      }
 934  
 935      /**
 936       *
 937       * Returns a new Parser instance.
 938       *
 939       * @param string $driver Return a parser for this driver.
 940       *
 941       * @return ParserInterface
 942       *
 943       */
 944      protected function newParser(string $driver): ParserInterface
 945      {
 946          $class = 'Aura\Sql\Parser\\' . ucfirst($driver) . 'Parser';
 947          if (! class_exists($class)) {
 948              $class = 'Aura\Sql\Parser\SqliteParser';        
 949          }
 950          return new $class();
 951      }
 952  
 953      /**
 954       *
 955       * Sets quoting properties based on the PDO driver.
 956       *
 957       * @param string $driver The PDO driver name.
 958       *
 959       * @return void
 960       *
 961       */
 962      protected function setQuoteName(string $driver): void
 963      {
 964          switch ($driver) {
 965              case 'mysql':
 966                  $this->quoteNamePrefix = '`';
 967                  $this->quoteNameSuffix = '`';
 968                  $this->quoteNameEscapeFind = '`';
 969                  $this->quoteNameEscapeRepl = '``';
 970                  return;
 971              case 'sqlsrv':
 972                  $this->quoteNamePrefix = '[';
 973                  $this->quoteNameSuffix = ']';
 974                  $this->quoteNameEscapeFind = ']';
 975                  $this->quoteNameEscapeRepl = '][';
 976                  return;
 977              default:
 978                  $this->quoteNamePrefix = '"';
 979                  $this->quoteNameSuffix = '"';
 980                  $this->quoteNameEscapeFind = '"';
 981                  $this->quoteNameEscapeRepl = '""';
 982                  return;
 983          }
 984      }
 985  
 986      /**
 987       *
 988       * Retrieve a database connection attribute
 989       *
 990       * @param int $attribute
 991       * @return bool|int|string|array|null
 992       */
 993      public function getAttribute(int $attribute): bool|int|string|array|null
 994      {
 995          $this->lazyConnect();
 996          return $this->pdo->getAttribute($attribute);
 997      }
 998  
 999      /**
1000       *
1001       * Set a database connection attribute
1002       *
1003       * @param int $attribute
1004       * @param mixed $value
1005       * @return bool
1006       */
1007      public function setAttribute(int $attribute, mixed $value): bool
1008      {
1009          $this->lazyConnect();
1010          return $this->pdo->setAttribute($attribute, $value);
1011      }
1012  }


Generated: Mon Mar 31 05:10:02 2025 Cross-referenced by PHPXref 0.7.1