Connection.php 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. <?php
  2. namespace Illuminate\Database;
  3. use Carbon\CarbonInterval;
  4. use Closure;
  5. use DateTimeInterface;
  6. use Exception;
  7. use Illuminate\Contracts\Events\Dispatcher;
  8. use Illuminate\Database\Events\QueryExecuted;
  9. use Illuminate\Database\Events\StatementPrepared;
  10. use Illuminate\Database\Events\TransactionBeginning;
  11. use Illuminate\Database\Events\TransactionCommitted;
  12. use Illuminate\Database\Events\TransactionCommitting;
  13. use Illuminate\Database\Events\TransactionRolledBack;
  14. use Illuminate\Database\Query\Builder as QueryBuilder;
  15. use Illuminate\Database\Query\Expression;
  16. use Illuminate\Database\Query\Grammars\Grammar as QueryGrammar;
  17. use Illuminate\Database\Query\Processors\Processor;
  18. use Illuminate\Database\Schema\Builder as SchemaBuilder;
  19. use Illuminate\Support\Arr;
  20. use Illuminate\Support\InteractsWithTime;
  21. use Illuminate\Support\Traits\Macroable;
  22. use PDO;
  23. use PDOStatement;
  24. use RuntimeException;
  25. class Connection implements ConnectionInterface
  26. {
  27. use DetectsConcurrencyErrors,
  28. DetectsLostConnections,
  29. Concerns\ManagesTransactions,
  30. InteractsWithTime,
  31. Macroable;
  32. /**
  33. * The active PDO connection.
  34. *
  35. * @var \PDO|\Closure
  36. */
  37. protected $pdo;
  38. /**
  39. * The active PDO connection used for reads.
  40. *
  41. * @var \PDO|\Closure
  42. */
  43. protected $readPdo;
  44. /**
  45. * The name of the connected database.
  46. *
  47. * @var string
  48. */
  49. protected $database;
  50. /**
  51. * The type of the connection.
  52. *
  53. * @var string|null
  54. */
  55. protected $readWriteType;
  56. /**
  57. * The table prefix for the connection.
  58. *
  59. * @var string
  60. */
  61. protected $tablePrefix = '';
  62. /**
  63. * The database connection configuration options.
  64. *
  65. * @var array
  66. */
  67. protected $config = [];
  68. /**
  69. * The reconnector instance for the connection.
  70. *
  71. * @var callable
  72. */
  73. protected $reconnector;
  74. /**
  75. * The query grammar implementation.
  76. *
  77. * @var \Illuminate\Database\Query\Grammars\Grammar
  78. */
  79. protected $queryGrammar;
  80. /**
  81. * The schema grammar implementation.
  82. *
  83. * @var \Illuminate\Database\Schema\Grammars\Grammar
  84. */
  85. protected $schemaGrammar;
  86. /**
  87. * The query post processor implementation.
  88. *
  89. * @var \Illuminate\Database\Query\Processors\Processor
  90. */
  91. protected $postProcessor;
  92. /**
  93. * The event dispatcher instance.
  94. *
  95. * @var \Illuminate\Contracts\Events\Dispatcher
  96. */
  97. protected $events;
  98. /**
  99. * The default fetch mode of the connection.
  100. *
  101. * @var int
  102. */
  103. protected $fetchMode = PDO::FETCH_OBJ;
  104. /**
  105. * The number of active transactions.
  106. *
  107. * @var int
  108. */
  109. protected $transactions = 0;
  110. /**
  111. * The transaction manager instance.
  112. *
  113. * @var \Illuminate\Database\DatabaseTransactionsManager
  114. */
  115. protected $transactionsManager;
  116. /**
  117. * Indicates if changes have been made to the database.
  118. *
  119. * @var bool
  120. */
  121. protected $recordsModified = false;
  122. /**
  123. * Indicates if the connection should use the "write" PDO connection.
  124. *
  125. * @var bool
  126. */
  127. protected $readOnWriteConnection = false;
  128. /**
  129. * All of the queries run against the connection.
  130. *
  131. * @var array
  132. */
  133. protected $queryLog = [];
  134. /**
  135. * Indicates whether queries are being logged.
  136. *
  137. * @var bool
  138. */
  139. protected $loggingQueries = false;
  140. /**
  141. * The duration of all executed queries in milliseconds.
  142. *
  143. * @var float
  144. */
  145. protected $totalQueryDuration = 0.0;
  146. /**
  147. * All of the registered query duration handlers.
  148. *
  149. * @var array
  150. */
  151. protected $queryDurationHandlers = [];
  152. /**
  153. * Indicates if the connection is in a "dry run".
  154. *
  155. * @var bool
  156. */
  157. protected $pretending = false;
  158. /**
  159. * All of the callbacks that should be invoked before a transaction is started.
  160. *
  161. * @var \Closure[]
  162. */
  163. protected $beforeStartingTransaction = [];
  164. /**
  165. * All of the callbacks that should be invoked before a query is executed.
  166. *
  167. * @var \Closure[]
  168. */
  169. protected $beforeExecutingCallbacks = [];
  170. /**
  171. * The connection resolvers.
  172. *
  173. * @var \Closure[]
  174. */
  175. protected static $resolvers = [];
  176. /**
  177. * Create a new database connection instance.
  178. *
  179. * @param \PDO|\Closure $pdo
  180. * @param string $database
  181. * @param string $tablePrefix
  182. * @param array $config
  183. * @return void
  184. */
  185. public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
  186. {
  187. $this->pdo = $pdo;
  188. // First we will setup the default properties. We keep track of the DB
  189. // name we are connected to since it is needed when some reflective
  190. // type commands are run such as checking whether a table exists.
  191. $this->database = $database;
  192. $this->tablePrefix = $tablePrefix;
  193. $this->config = $config;
  194. // We need to initialize a query grammar and the query post processors
  195. // which are both very important parts of the database abstractions
  196. // so we initialize these to their default values while starting.
  197. $this->useDefaultQueryGrammar();
  198. $this->useDefaultPostProcessor();
  199. }
  200. /**
  201. * Set the query grammar to the default implementation.
  202. *
  203. * @return void
  204. */
  205. public function useDefaultQueryGrammar()
  206. {
  207. $this->queryGrammar = $this->getDefaultQueryGrammar();
  208. }
  209. /**
  210. * Get the default query grammar instance.
  211. *
  212. * @return \Illuminate\Database\Query\Grammars\Grammar
  213. */
  214. protected function getDefaultQueryGrammar()
  215. {
  216. ($grammar = new QueryGrammar)->setConnection($this);
  217. return $grammar;
  218. }
  219. /**
  220. * Set the schema grammar to the default implementation.
  221. *
  222. * @return void
  223. */
  224. public function useDefaultSchemaGrammar()
  225. {
  226. $this->schemaGrammar = $this->getDefaultSchemaGrammar();
  227. }
  228. /**
  229. * Get the default schema grammar instance.
  230. *
  231. * @return \Illuminate\Database\Schema\Grammars\Grammar|null
  232. */
  233. protected function getDefaultSchemaGrammar()
  234. {
  235. //
  236. }
  237. /**
  238. * Set the query post processor to the default implementation.
  239. *
  240. * @return void
  241. */
  242. public function useDefaultPostProcessor()
  243. {
  244. $this->postProcessor = $this->getDefaultPostProcessor();
  245. }
  246. /**
  247. * Get the default post processor instance.
  248. *
  249. * @return \Illuminate\Database\Query\Processors\Processor
  250. */
  251. protected function getDefaultPostProcessor()
  252. {
  253. return new Processor;
  254. }
  255. /**
  256. * Get a schema builder instance for the connection.
  257. *
  258. * @return \Illuminate\Database\Schema\Builder
  259. */
  260. public function getSchemaBuilder()
  261. {
  262. if (is_null($this->schemaGrammar)) {
  263. $this->useDefaultSchemaGrammar();
  264. }
  265. return new SchemaBuilder($this);
  266. }
  267. /**
  268. * Begin a fluent query against a database table.
  269. *
  270. * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Contracts\Database\Query\Expression|string $table
  271. * @param string|null $as
  272. * @return \Illuminate\Database\Query\Builder
  273. */
  274. public function table($table, $as = null)
  275. {
  276. return $this->query()->from($table, $as);
  277. }
  278. /**
  279. * Get a new query builder instance.
  280. *
  281. * @return \Illuminate\Database\Query\Builder
  282. */
  283. public function query()
  284. {
  285. return new QueryBuilder(
  286. $this, $this->getQueryGrammar(), $this->getPostProcessor()
  287. );
  288. }
  289. /**
  290. * Run a select statement and return a single result.
  291. *
  292. * @param string $query
  293. * @param array $bindings
  294. * @param bool $useReadPdo
  295. * @return mixed
  296. */
  297. public function selectOne($query, $bindings = [], $useReadPdo = true)
  298. {
  299. $records = $this->select($query, $bindings, $useReadPdo);
  300. return array_shift($records);
  301. }
  302. /**
  303. * Run a select statement and return the first column of the first row.
  304. *
  305. * @param string $query
  306. * @param array $bindings
  307. * @param bool $useReadPdo
  308. * @return mixed
  309. *
  310. * @throws \Illuminate\Database\MultipleColumnsSelectedException
  311. */
  312. public function scalar($query, $bindings = [], $useReadPdo = true)
  313. {
  314. $record = $this->selectOne($query, $bindings, $useReadPdo);
  315. if (is_null($record)) {
  316. return null;
  317. }
  318. $record = (array) $record;
  319. if (count($record) > 1) {
  320. throw new MultipleColumnsSelectedException;
  321. }
  322. return reset($record);
  323. }
  324. /**
  325. * Run a select statement against the database.
  326. *
  327. * @param string $query
  328. * @param array $bindings
  329. * @return array
  330. */
  331. public function selectFromWriteConnection($query, $bindings = [])
  332. {
  333. return $this->select($query, $bindings, false);
  334. }
  335. /**
  336. * Run a select statement against the database.
  337. *
  338. * @param string $query
  339. * @param array $bindings
  340. * @param bool $useReadPdo
  341. * @return array
  342. */
  343. public function select($query, $bindings = [], $useReadPdo = true)
  344. {
  345. return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
  346. if ($this->pretending()) {
  347. return [];
  348. }
  349. // For select statements, we'll simply execute the query and return an array
  350. // of the database result set. Each element in the array will be a single
  351. // row from the database table, and will either be an array or objects.
  352. $statement = $this->prepared(
  353. $this->getPdoForSelect($useReadPdo)->prepare($query)
  354. );
  355. $this->bindValues($statement, $this->prepareBindings($bindings));
  356. $statement->execute();
  357. return $statement->fetchAll();
  358. });
  359. }
  360. /**
  361. * Run a select statement against the database and returns all of the result sets.
  362. *
  363. * @param string $query
  364. * @param array $bindings
  365. * @param bool $useReadPdo
  366. * @return array
  367. */
  368. public function selectResultSets($query, $bindings = [], $useReadPdo = true)
  369. {
  370. return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
  371. if ($this->pretending()) {
  372. return [];
  373. }
  374. $statement = $this->prepared(
  375. $this->getPdoForSelect($useReadPdo)->prepare($query)
  376. );
  377. $this->bindValues($statement, $this->prepareBindings($bindings));
  378. $statement->execute();
  379. $sets = [];
  380. do {
  381. $sets[] = $statement->fetchAll();
  382. } while ($statement->nextRowset());
  383. return $sets;
  384. });
  385. }
  386. /**
  387. * Run a select statement against the database and returns a generator.
  388. *
  389. * @param string $query
  390. * @param array $bindings
  391. * @param bool $useReadPdo
  392. * @return \Generator
  393. */
  394. public function cursor($query, $bindings = [], $useReadPdo = true)
  395. {
  396. $statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
  397. if ($this->pretending()) {
  398. return [];
  399. }
  400. // First we will create a statement for the query. Then, we will set the fetch
  401. // mode and prepare the bindings for the query. Once that's done we will be
  402. // ready to execute the query against the database and return the cursor.
  403. $statement = $this->prepared($this->getPdoForSelect($useReadPdo)
  404. ->prepare($query));
  405. $this->bindValues(
  406. $statement, $this->prepareBindings($bindings)
  407. );
  408. // Next, we'll execute the query against the database and return the statement
  409. // so we can return the cursor. The cursor will use a PHP generator to give
  410. // back one row at a time without using a bunch of memory to render them.
  411. $statement->execute();
  412. return $statement;
  413. });
  414. while ($record = $statement->fetch()) {
  415. yield $record;
  416. }
  417. }
  418. /**
  419. * Configure the PDO prepared statement.
  420. *
  421. * @param \PDOStatement $statement
  422. * @return \PDOStatement
  423. */
  424. protected function prepared(PDOStatement $statement)
  425. {
  426. $statement->setFetchMode($this->fetchMode);
  427. $this->event(new StatementPrepared($this, $statement));
  428. return $statement;
  429. }
  430. /**
  431. * Get the PDO connection to use for a select query.
  432. *
  433. * @param bool $useReadPdo
  434. * @return \PDO
  435. */
  436. protected function getPdoForSelect($useReadPdo = true)
  437. {
  438. return $useReadPdo ? $this->getReadPdo() : $this->getPdo();
  439. }
  440. /**
  441. * Run an insert statement against the database.
  442. *
  443. * @param string $query
  444. * @param array $bindings
  445. * @return bool
  446. */
  447. public function insert($query, $bindings = [])
  448. {
  449. return $this->statement($query, $bindings);
  450. }
  451. /**
  452. * Run an update statement against the database.
  453. *
  454. * @param string $query
  455. * @param array $bindings
  456. * @return int
  457. */
  458. public function update($query, $bindings = [])
  459. {
  460. return $this->affectingStatement($query, $bindings);
  461. }
  462. /**
  463. * Run a delete statement against the database.
  464. *
  465. * @param string $query
  466. * @param array $bindings
  467. * @return int
  468. */
  469. public function delete($query, $bindings = [])
  470. {
  471. return $this->affectingStatement($query, $bindings);
  472. }
  473. /**
  474. * Execute an SQL statement and return the boolean result.
  475. *
  476. * @param string $query
  477. * @param array $bindings
  478. * @return bool
  479. */
  480. public function statement($query, $bindings = [])
  481. {
  482. return $this->run($query, $bindings, function ($query, $bindings) {
  483. if ($this->pretending()) {
  484. return true;
  485. }
  486. $statement = $this->getPdo()->prepare($query);
  487. $this->bindValues($statement, $this->prepareBindings($bindings));
  488. $this->recordsHaveBeenModified();
  489. return $statement->execute();
  490. });
  491. }
  492. /**
  493. * Run an SQL statement and get the number of rows affected.
  494. *
  495. * @param string $query
  496. * @param array $bindings
  497. * @return int
  498. */
  499. public function affectingStatement($query, $bindings = [])
  500. {
  501. return $this->run($query, $bindings, function ($query, $bindings) {
  502. if ($this->pretending()) {
  503. return 0;
  504. }
  505. // For update or delete statements, we want to get the number of rows affected
  506. // by the statement and return that back to the developer. We'll first need
  507. // to execute the statement and then we'll use PDO to fetch the affected.
  508. $statement = $this->getPdo()->prepare($query);
  509. $this->bindValues($statement, $this->prepareBindings($bindings));
  510. $statement->execute();
  511. $this->recordsHaveBeenModified(
  512. ($count = $statement->rowCount()) > 0
  513. );
  514. return $count;
  515. });
  516. }
  517. /**
  518. * Run a raw, unprepared query against the PDO connection.
  519. *
  520. * @param string $query
  521. * @return bool
  522. */
  523. public function unprepared($query)
  524. {
  525. return $this->run($query, [], function ($query) {
  526. if ($this->pretending()) {
  527. return true;
  528. }
  529. $this->recordsHaveBeenModified(
  530. $change = $this->getPdo()->exec($query) !== false
  531. );
  532. return $change;
  533. });
  534. }
  535. /**
  536. * Execute the given callback in "dry run" mode.
  537. *
  538. * @param \Closure $callback
  539. * @return array
  540. */
  541. public function pretend(Closure $callback)
  542. {
  543. return $this->withFreshQueryLog(function () use ($callback) {
  544. $this->pretending = true;
  545. // Basically to make the database connection "pretend", we will just return
  546. // the default values for all the query methods, then we will return an
  547. // array of queries that were "executed" within the Closure callback.
  548. $callback($this);
  549. $this->pretending = false;
  550. return $this->queryLog;
  551. });
  552. }
  553. /**
  554. * Execute the given callback without "pretending".
  555. *
  556. * @param \Closure $callback
  557. * @return mixed
  558. */
  559. public function withoutPretending(Closure $callback)
  560. {
  561. if (! $this->pretending) {
  562. return $callback();
  563. }
  564. $this->pretending = false;
  565. $result = $callback();
  566. $this->pretending = true;
  567. return $result;
  568. }
  569. /**
  570. * Execute the given callback in "dry run" mode.
  571. *
  572. * @param \Closure $callback
  573. * @return array
  574. */
  575. protected function withFreshQueryLog($callback)
  576. {
  577. $loggingQueries = $this->loggingQueries;
  578. // First we will back up the value of the logging queries property and then
  579. // we'll be ready to run callbacks. This query log will also get cleared
  580. // so we will have a new log of all the queries that are executed now.
  581. $this->enableQueryLog();
  582. $this->queryLog = [];
  583. // Now we'll execute this callback and capture the result. Once it has been
  584. // executed we will restore the value of query logging and give back the
  585. // value of the callback so the original callers can have the results.
  586. $result = $callback();
  587. $this->loggingQueries = $loggingQueries;
  588. return $result;
  589. }
  590. /**
  591. * Bind values to their parameters in the given statement.
  592. *
  593. * @param \PDOStatement $statement
  594. * @param array $bindings
  595. * @return void
  596. */
  597. public function bindValues($statement, $bindings)
  598. {
  599. foreach ($bindings as $key => $value) {
  600. $statement->bindValue(
  601. is_string($key) ? $key : $key + 1,
  602. $value,
  603. match (true) {
  604. is_int($value) => PDO::PARAM_INT,
  605. is_resource($value) => PDO::PARAM_LOB,
  606. default => PDO::PARAM_STR
  607. },
  608. );
  609. }
  610. }
  611. /**
  612. * Prepare the query bindings for execution.
  613. *
  614. * @param array $bindings
  615. * @return array
  616. */
  617. public function prepareBindings(array $bindings)
  618. {
  619. $grammar = $this->getQueryGrammar();
  620. foreach ($bindings as $key => $value) {
  621. // We need to transform all instances of DateTimeInterface into the actual
  622. // date string. Each query grammar maintains its own date string format
  623. // so we'll just ask the grammar for the format to get from the date.
  624. if ($value instanceof DateTimeInterface) {
  625. $bindings[$key] = $value->format($grammar->getDateFormat());
  626. } elseif (is_bool($value)) {
  627. $bindings[$key] = (int) $value;
  628. }
  629. }
  630. return $bindings;
  631. }
  632. /**
  633. * Run a SQL statement and log its execution context.
  634. *
  635. * @param string $query
  636. * @param array $bindings
  637. * @param \Closure $callback
  638. * @return mixed
  639. *
  640. * @throws \Illuminate\Database\QueryException
  641. */
  642. protected function run($query, $bindings, Closure $callback)
  643. {
  644. foreach ($this->beforeExecutingCallbacks as $beforeExecutingCallback) {
  645. $beforeExecutingCallback($query, $bindings, $this);
  646. }
  647. $this->reconnectIfMissingConnection();
  648. $start = microtime(true);
  649. // Here we will run this query. If an exception occurs we'll determine if it was
  650. // caused by a connection that has been lost. If that is the cause, we'll try
  651. // to re-establish connection and re-run the query with a fresh connection.
  652. try {
  653. $result = $this->runQueryCallback($query, $bindings, $callback);
  654. } catch (QueryException $e) {
  655. $result = $this->handleQueryException(
  656. $e, $query, $bindings, $callback
  657. );
  658. }
  659. // Once we have run the query we will calculate the time that it took to run and
  660. // then log the query, bindings, and execution time so we will report them on
  661. // the event that the developer needs them. We'll log time in milliseconds.
  662. $this->logQuery(
  663. $query, $bindings, $this->getElapsedTime($start)
  664. );
  665. return $result;
  666. }
  667. /**
  668. * Run a SQL statement.
  669. *
  670. * @param string $query
  671. * @param array $bindings
  672. * @param \Closure $callback
  673. * @return mixed
  674. *
  675. * @throws \Illuminate\Database\QueryException
  676. */
  677. protected function runQueryCallback($query, $bindings, Closure $callback)
  678. {
  679. // To execute the statement, we'll simply call the callback, which will actually
  680. // run the SQL against the PDO connection. Then we can calculate the time it
  681. // took to execute and log the query SQL, bindings and time in our memory.
  682. try {
  683. return $callback($query, $bindings);
  684. }
  685. // If an exception occurs when attempting to run a query, we'll format the error
  686. // message to include the bindings with SQL, which will make this exception a
  687. // lot more helpful to the developer instead of just the database's errors.
  688. catch (Exception $e) {
  689. if ($this->isUniqueConstraintError($e)) {
  690. throw new UniqueConstraintViolationException(
  691. $this->getName(), $query, $this->prepareBindings($bindings), $e
  692. );
  693. }
  694. throw new QueryException(
  695. $this->getName(), $query, $this->prepareBindings($bindings), $e
  696. );
  697. }
  698. }
  699. /**
  700. * Determine if the given database exception was caused by a unique constraint violation.
  701. *
  702. * @param \Exception $exception
  703. * @return bool
  704. */
  705. protected function isUniqueConstraintError(Exception $exception)
  706. {
  707. return false;
  708. }
  709. /**
  710. * Log a query in the connection's query log.
  711. *
  712. * @param string $query
  713. * @param array $bindings
  714. * @param float|null $time
  715. * @return void
  716. */
  717. public function logQuery($query, $bindings, $time = null)
  718. {
  719. $this->totalQueryDuration += $time ?? 0.0;
  720. $this->event(new QueryExecuted($query, $bindings, $time, $this));
  721. $query = $this->pretending === true
  722. ? $this->queryGrammar?->substituteBindingsIntoRawSql($query, $bindings) ?? $query
  723. : $query;
  724. if ($this->loggingQueries) {
  725. $this->queryLog[] = compact('query', 'bindings', 'time');
  726. }
  727. }
  728. /**
  729. * Get the elapsed time since a given starting point.
  730. *
  731. * @param int $start
  732. * @return float
  733. */
  734. protected function getElapsedTime($start)
  735. {
  736. return round((microtime(true) - $start) * 1000, 2);
  737. }
  738. /**
  739. * Register a callback to be invoked when the connection queries for longer than a given amount of time.
  740. *
  741. * @param \DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold
  742. * @param callable $handler
  743. * @return void
  744. */
  745. public function whenQueryingForLongerThan($threshold, $handler)
  746. {
  747. $threshold = $threshold instanceof DateTimeInterface
  748. ? $this->secondsUntil($threshold) * 1000
  749. : $threshold;
  750. $threshold = $threshold instanceof CarbonInterval
  751. ? $threshold->totalMilliseconds
  752. : $threshold;
  753. $this->queryDurationHandlers[] = [
  754. 'has_run' => false,
  755. 'handler' => $handler,
  756. ];
  757. $key = count($this->queryDurationHandlers) - 1;
  758. $this->listen(function ($event) use ($threshold, $handler, $key) {
  759. if (! $this->queryDurationHandlers[$key]['has_run'] && $this->totalQueryDuration() > $threshold) {
  760. $handler($this, $event);
  761. $this->queryDurationHandlers[$key]['has_run'] = true;
  762. }
  763. });
  764. }
  765. /**
  766. * Allow all the query duration handlers to run again, even if they have already run.
  767. *
  768. * @return void
  769. */
  770. public function allowQueryDurationHandlersToRunAgain()
  771. {
  772. foreach ($this->queryDurationHandlers as $key => $queryDurationHandler) {
  773. $this->queryDurationHandlers[$key]['has_run'] = false;
  774. }
  775. }
  776. /**
  777. * Get the duration of all run queries in milliseconds.
  778. *
  779. * @return float
  780. */
  781. public function totalQueryDuration()
  782. {
  783. return $this->totalQueryDuration;
  784. }
  785. /**
  786. * Reset the duration of all run queries.
  787. *
  788. * @return void
  789. */
  790. public function resetTotalQueryDuration()
  791. {
  792. $this->totalQueryDuration = 0.0;
  793. }
  794. /**
  795. * Handle a query exception.
  796. *
  797. * @param \Illuminate\Database\QueryException $e
  798. * @param string $query
  799. * @param array $bindings
  800. * @param \Closure $callback
  801. * @return mixed
  802. *
  803. * @throws \Illuminate\Database\QueryException
  804. */
  805. protected function handleQueryException(QueryException $e, $query, $bindings, Closure $callback)
  806. {
  807. if ($this->transactions >= 1) {
  808. throw $e;
  809. }
  810. return $this->tryAgainIfCausedByLostConnection(
  811. $e, $query, $bindings, $callback
  812. );
  813. }
  814. /**
  815. * Handle a query exception that occurred during query execution.
  816. *
  817. * @param \Illuminate\Database\QueryException $e
  818. * @param string $query
  819. * @param array $bindings
  820. * @param \Closure $callback
  821. * @return mixed
  822. *
  823. * @throws \Illuminate\Database\QueryException
  824. */
  825. protected function tryAgainIfCausedByLostConnection(QueryException $e, $query, $bindings, Closure $callback)
  826. {
  827. if ($this->causedByLostConnection($e->getPrevious())) {
  828. $this->reconnect();
  829. return $this->runQueryCallback($query, $bindings, $callback);
  830. }
  831. throw $e;
  832. }
  833. /**
  834. * Reconnect to the database.
  835. *
  836. * @return mixed|false
  837. *
  838. * @throws \Illuminate\Database\LostConnectionException
  839. */
  840. public function reconnect()
  841. {
  842. if (is_callable($this->reconnector)) {
  843. return call_user_func($this->reconnector, $this);
  844. }
  845. throw new LostConnectionException('Lost connection and no reconnector available.');
  846. }
  847. /**
  848. * Reconnect to the database if a PDO connection is missing.
  849. *
  850. * @return void
  851. */
  852. public function reconnectIfMissingConnection()
  853. {
  854. if (is_null($this->pdo)) {
  855. $this->reconnect();
  856. }
  857. }
  858. /**
  859. * Disconnect from the underlying PDO connection.
  860. *
  861. * @return void
  862. */
  863. public function disconnect()
  864. {
  865. $this->setPdo(null)->setReadPdo(null);
  866. }
  867. /**
  868. * Register a hook to be run just before a database transaction is started.
  869. *
  870. * @param \Closure $callback
  871. * @return $this
  872. */
  873. public function beforeStartingTransaction(Closure $callback)
  874. {
  875. $this->beforeStartingTransaction[] = $callback;
  876. return $this;
  877. }
  878. /**
  879. * Register a hook to be run just before a database query is executed.
  880. *
  881. * @param \Closure $callback
  882. * @return $this
  883. */
  884. public function beforeExecuting(Closure $callback)
  885. {
  886. $this->beforeExecutingCallbacks[] = $callback;
  887. return $this;
  888. }
  889. /**
  890. * Register a database query listener with the connection.
  891. *
  892. * @param \Closure $callback
  893. * @return void
  894. */
  895. public function listen(Closure $callback)
  896. {
  897. $this->events?->listen(Events\QueryExecuted::class, $callback);
  898. }
  899. /**
  900. * Fire an event for this connection.
  901. *
  902. * @param string $event
  903. * @return array|null
  904. */
  905. protected function fireConnectionEvent($event)
  906. {
  907. return $this->events?->dispatch(match ($event) {
  908. 'beganTransaction' => new TransactionBeginning($this),
  909. 'committed' => new TransactionCommitted($this),
  910. 'committing' => new TransactionCommitting($this),
  911. 'rollingBack' => new TransactionRolledBack($this),
  912. default => null,
  913. });
  914. }
  915. /**
  916. * Fire the given event if possible.
  917. *
  918. * @param mixed $event
  919. * @return void
  920. */
  921. protected function event($event)
  922. {
  923. $this->events?->dispatch($event);
  924. }
  925. /**
  926. * Get a new raw query expression.
  927. *
  928. * @param mixed $value
  929. * @return \Illuminate\Contracts\Database\Query\Expression
  930. */
  931. public function raw($value)
  932. {
  933. return new Expression($value);
  934. }
  935. /**
  936. * Escape a value for safe SQL embedding.
  937. *
  938. * @param string|float|int|bool|null $value
  939. * @param bool $binary
  940. * @return string
  941. */
  942. public function escape($value, $binary = false)
  943. {
  944. if ($value === null) {
  945. return 'null';
  946. } elseif ($binary) {
  947. return $this->escapeBinary($value);
  948. } elseif (is_int($value) || is_float($value)) {
  949. return (string) $value;
  950. } elseif (is_bool($value)) {
  951. return $this->escapeBool($value);
  952. } elseif (is_array($value)) {
  953. throw new RuntimeException('The database connection does not support escaping arrays.');
  954. } else {
  955. if (str_contains($value, "\00")) {
  956. throw new RuntimeException('Strings with null bytes cannot be escaped. Use the binary escape option.');
  957. }
  958. if (preg_match('//u', $value) === false) {
  959. throw new RuntimeException('Strings with invalid UTF-8 byte sequences cannot be escaped.');
  960. }
  961. return $this->escapeString($value);
  962. }
  963. }
  964. /**
  965. * Escape a string value for safe SQL embedding.
  966. *
  967. * @param string $value
  968. * @return string
  969. */
  970. protected function escapeString($value)
  971. {
  972. return $this->getReadPdo()->quote($value);
  973. }
  974. /**
  975. * Escape a boolean value for safe SQL embedding.
  976. *
  977. * @param bool $value
  978. * @return string
  979. */
  980. protected function escapeBool($value)
  981. {
  982. return $value ? '1' : '0';
  983. }
  984. /**
  985. * Escape a binary value for safe SQL embedding.
  986. *
  987. * @param string $value
  988. * @return string
  989. */
  990. protected function escapeBinary($value)
  991. {
  992. throw new RuntimeException('The database connection does not support escaping binary values.');
  993. }
  994. /**
  995. * Determine if the database connection has modified any database records.
  996. *
  997. * @return bool
  998. */
  999. public function hasModifiedRecords()
  1000. {
  1001. return $this->recordsModified;
  1002. }
  1003. /**
  1004. * Indicate if any records have been modified.
  1005. *
  1006. * @param bool $value
  1007. * @return void
  1008. */
  1009. public function recordsHaveBeenModified($value = true)
  1010. {
  1011. if (! $this->recordsModified) {
  1012. $this->recordsModified = $value;
  1013. }
  1014. }
  1015. /**
  1016. * Set the record modification state.
  1017. *
  1018. * @param bool $value
  1019. * @return $this
  1020. */
  1021. public function setRecordModificationState(bool $value)
  1022. {
  1023. $this->recordsModified = $value;
  1024. return $this;
  1025. }
  1026. /**
  1027. * Reset the record modification state.
  1028. *
  1029. * @return void
  1030. */
  1031. public function forgetRecordModificationState()
  1032. {
  1033. $this->recordsModified = false;
  1034. }
  1035. /**
  1036. * Indicate that the connection should use the write PDO connection for reads.
  1037. *
  1038. * @param bool $value
  1039. * @return $this
  1040. */
  1041. public function useWriteConnectionWhenReading($value = true)
  1042. {
  1043. $this->readOnWriteConnection = $value;
  1044. return $this;
  1045. }
  1046. /**
  1047. * Get the current PDO connection.
  1048. *
  1049. * @return \PDO
  1050. */
  1051. public function getPdo()
  1052. {
  1053. if ($this->pdo instanceof Closure) {
  1054. return $this->pdo = call_user_func($this->pdo);
  1055. }
  1056. return $this->pdo;
  1057. }
  1058. /**
  1059. * Get the current PDO connection parameter without executing any reconnect logic.
  1060. *
  1061. * @return \PDO|\Closure|null
  1062. */
  1063. public function getRawPdo()
  1064. {
  1065. return $this->pdo;
  1066. }
  1067. /**
  1068. * Get the current PDO connection used for reading.
  1069. *
  1070. * @return \PDO
  1071. */
  1072. public function getReadPdo()
  1073. {
  1074. if ($this->transactions > 0) {
  1075. return $this->getPdo();
  1076. }
  1077. if ($this->readOnWriteConnection ||
  1078. ($this->recordsModified && $this->getConfig('sticky'))) {
  1079. return $this->getPdo();
  1080. }
  1081. if ($this->readPdo instanceof Closure) {
  1082. return $this->readPdo = call_user_func($this->readPdo);
  1083. }
  1084. return $this->readPdo ?: $this->getPdo();
  1085. }
  1086. /**
  1087. * Get the current read PDO connection parameter without executing any reconnect logic.
  1088. *
  1089. * @return \PDO|\Closure|null
  1090. */
  1091. public function getRawReadPdo()
  1092. {
  1093. return $this->readPdo;
  1094. }
  1095. /**
  1096. * Set the PDO connection.
  1097. *
  1098. * @param \PDO|\Closure|null $pdo
  1099. * @return $this
  1100. */
  1101. public function setPdo($pdo)
  1102. {
  1103. $this->transactions = 0;
  1104. $this->pdo = $pdo;
  1105. return $this;
  1106. }
  1107. /**
  1108. * Set the PDO connection used for reading.
  1109. *
  1110. * @param \PDO|\Closure|null $pdo
  1111. * @return $this
  1112. */
  1113. public function setReadPdo($pdo)
  1114. {
  1115. $this->readPdo = $pdo;
  1116. return $this;
  1117. }
  1118. /**
  1119. * Set the reconnect instance on the connection.
  1120. *
  1121. * @param callable $reconnector
  1122. * @return $this
  1123. */
  1124. public function setReconnector(callable $reconnector)
  1125. {
  1126. $this->reconnector = $reconnector;
  1127. return $this;
  1128. }
  1129. /**
  1130. * Get the database connection name.
  1131. *
  1132. * @return string|null
  1133. */
  1134. public function getName()
  1135. {
  1136. return $this->getConfig('name');
  1137. }
  1138. /**
  1139. * Get the database connection full name.
  1140. *
  1141. * @return string|null
  1142. */
  1143. public function getNameWithReadWriteType()
  1144. {
  1145. return $this->getName().($this->readWriteType ? '::'.$this->readWriteType : '');
  1146. }
  1147. /**
  1148. * Get an option from the configuration options.
  1149. *
  1150. * @param string|null $option
  1151. * @return mixed
  1152. */
  1153. public function getConfig($option = null)
  1154. {
  1155. return Arr::get($this->config, $option);
  1156. }
  1157. /**
  1158. * Get the PDO driver name.
  1159. *
  1160. * @return string
  1161. */
  1162. public function getDriverName()
  1163. {
  1164. return $this->getConfig('driver');
  1165. }
  1166. /**
  1167. * Get the query grammar used by the connection.
  1168. *
  1169. * @return \Illuminate\Database\Query\Grammars\Grammar
  1170. */
  1171. public function getQueryGrammar()
  1172. {
  1173. return $this->queryGrammar;
  1174. }
  1175. /**
  1176. * Set the query grammar used by the connection.
  1177. *
  1178. * @param \Illuminate\Database\Query\Grammars\Grammar $grammar
  1179. * @return $this
  1180. */
  1181. public function setQueryGrammar(Query\Grammars\Grammar $grammar)
  1182. {
  1183. $this->queryGrammar = $grammar;
  1184. return $this;
  1185. }
  1186. /**
  1187. * Get the schema grammar used by the connection.
  1188. *
  1189. * @return \Illuminate\Database\Schema\Grammars\Grammar
  1190. */
  1191. public function getSchemaGrammar()
  1192. {
  1193. return $this->schemaGrammar;
  1194. }
  1195. /**
  1196. * Set the schema grammar used by the connection.
  1197. *
  1198. * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
  1199. * @return $this
  1200. */
  1201. public function setSchemaGrammar(Schema\Grammars\Grammar $grammar)
  1202. {
  1203. $this->schemaGrammar = $grammar;
  1204. return $this;
  1205. }
  1206. /**
  1207. * Get the query post processor used by the connection.
  1208. *
  1209. * @return \Illuminate\Database\Query\Processors\Processor
  1210. */
  1211. public function getPostProcessor()
  1212. {
  1213. return $this->postProcessor;
  1214. }
  1215. /**
  1216. * Set the query post processor used by the connection.
  1217. *
  1218. * @param \Illuminate\Database\Query\Processors\Processor $processor
  1219. * @return $this
  1220. */
  1221. public function setPostProcessor(Processor $processor)
  1222. {
  1223. $this->postProcessor = $processor;
  1224. return $this;
  1225. }
  1226. /**
  1227. * Get the event dispatcher used by the connection.
  1228. *
  1229. * @return \Illuminate\Contracts\Events\Dispatcher
  1230. */
  1231. public function getEventDispatcher()
  1232. {
  1233. return $this->events;
  1234. }
  1235. /**
  1236. * Set the event dispatcher instance on the connection.
  1237. *
  1238. * @param \Illuminate\Contracts\Events\Dispatcher $events
  1239. * @return $this
  1240. */
  1241. public function setEventDispatcher(Dispatcher $events)
  1242. {
  1243. $this->events = $events;
  1244. return $this;
  1245. }
  1246. /**
  1247. * Unset the event dispatcher for this connection.
  1248. *
  1249. * @return void
  1250. */
  1251. public function unsetEventDispatcher()
  1252. {
  1253. $this->events = null;
  1254. }
  1255. /**
  1256. * Set the transaction manager instance on the connection.
  1257. *
  1258. * @param \Illuminate\Database\DatabaseTransactionsManager $manager
  1259. * @return $this
  1260. */
  1261. public function setTransactionManager($manager)
  1262. {
  1263. $this->transactionsManager = $manager;
  1264. return $this;
  1265. }
  1266. /**
  1267. * Unset the transaction manager for this connection.
  1268. *
  1269. * @return void
  1270. */
  1271. public function unsetTransactionManager()
  1272. {
  1273. $this->transactionsManager = null;
  1274. }
  1275. /**
  1276. * Determine if the connection is in a "dry run".
  1277. *
  1278. * @return bool
  1279. */
  1280. public function pretending()
  1281. {
  1282. return $this->pretending === true;
  1283. }
  1284. /**
  1285. * Get the connection query log.
  1286. *
  1287. * @return array
  1288. */
  1289. public function getQueryLog()
  1290. {
  1291. return $this->queryLog;
  1292. }
  1293. /**
  1294. * Get the connection query log with embedded bindings.
  1295. *
  1296. * @return array
  1297. */
  1298. public function getRawQueryLog()
  1299. {
  1300. return array_map(fn (array $log) => [
  1301. 'raw_query' => $this->queryGrammar->substituteBindingsIntoRawSql(
  1302. $log['query'],
  1303. $this->prepareBindings($log['bindings'])
  1304. ),
  1305. 'time' => $log['time'],
  1306. ], $this->getQueryLog());
  1307. }
  1308. /**
  1309. * Clear the query log.
  1310. *
  1311. * @return void
  1312. */
  1313. public function flushQueryLog()
  1314. {
  1315. $this->queryLog = [];
  1316. }
  1317. /**
  1318. * Enable the query log on the connection.
  1319. *
  1320. * @return void
  1321. */
  1322. public function enableQueryLog()
  1323. {
  1324. $this->loggingQueries = true;
  1325. }
  1326. /**
  1327. * Disable the query log on the connection.
  1328. *
  1329. * @return void
  1330. */
  1331. public function disableQueryLog()
  1332. {
  1333. $this->loggingQueries = false;
  1334. }
  1335. /**
  1336. * Determine whether we're logging queries.
  1337. *
  1338. * @return bool
  1339. */
  1340. public function logging()
  1341. {
  1342. return $this->loggingQueries;
  1343. }
  1344. /**
  1345. * Get the name of the connected database.
  1346. *
  1347. * @return string
  1348. */
  1349. public function getDatabaseName()
  1350. {
  1351. return $this->database;
  1352. }
  1353. /**
  1354. * Set the name of the connected database.
  1355. *
  1356. * @param string $database
  1357. * @return $this
  1358. */
  1359. public function setDatabaseName($database)
  1360. {
  1361. $this->database = $database;
  1362. return $this;
  1363. }
  1364. /**
  1365. * Set the read / write type of the connection.
  1366. *
  1367. * @param string|null $readWriteType
  1368. * @return $this
  1369. */
  1370. public function setReadWriteType($readWriteType)
  1371. {
  1372. $this->readWriteType = $readWriteType;
  1373. return $this;
  1374. }
  1375. /**
  1376. * Get the table prefix for the connection.
  1377. *
  1378. * @return string
  1379. */
  1380. public function getTablePrefix()
  1381. {
  1382. return $this->tablePrefix;
  1383. }
  1384. /**
  1385. * Set the table prefix in use by the connection.
  1386. *
  1387. * @param string $prefix
  1388. * @return $this
  1389. */
  1390. public function setTablePrefix($prefix)
  1391. {
  1392. $this->tablePrefix = $prefix;
  1393. $this->getQueryGrammar()->setTablePrefix($prefix);
  1394. return $this;
  1395. }
  1396. /**
  1397. * Set the table prefix and return the grammar.
  1398. *
  1399. * @param \Illuminate\Database\Grammar $grammar
  1400. * @return \Illuminate\Database\Grammar
  1401. */
  1402. public function withTablePrefix(Grammar $grammar)
  1403. {
  1404. $grammar->setTablePrefix($this->tablePrefix);
  1405. return $grammar;
  1406. }
  1407. /**
  1408. * Get the server version for the connection.
  1409. *
  1410. * @return string
  1411. */
  1412. public function getServerVersion(): string
  1413. {
  1414. return $this->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
  1415. }
  1416. /**
  1417. * Register a connection resolver.
  1418. *
  1419. * @param string $driver
  1420. * @param \Closure $callback
  1421. * @return void
  1422. */
  1423. public static function resolverFor($driver, Closure $callback)
  1424. {
  1425. static::$resolvers[$driver] = $callback;
  1426. }
  1427. /**
  1428. * Get the connection resolver for the given driver.
  1429. *
  1430. * @param string $driver
  1431. * @return mixed
  1432. */
  1433. public static function getResolver($driver)
  1434. {
  1435. return static::$resolvers[$driver] ?? null;
  1436. }
  1437. }