From 5c80d874b2ac959fc0a47eab5b0ca511d2fd1f35 Mon Sep 17 00:00:00 2001 From: Chauncey McAskill Date: Thu, 30 Apr 2020 16:34:52 -0400 Subject: [PATCH 1/2] Rename performTableExists method --- src/Charcoal/Source/DatabaseSource.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Charcoal/Source/DatabaseSource.php b/src/Charcoal/Source/DatabaseSource.php index 8645e950..170c32c1 100644 --- a/src/Charcoal/Source/DatabaseSource.php +++ b/src/Charcoal/Source/DatabaseSource.php @@ -273,18 +273,18 @@ public function tableExists() return $dbh->tableExists[$table]; } - $exists = $this->performTableExists(); + $exists = $this->queryTableExists(); $this->setTableExists($exists); return $exists; } /** - * Perform a source table exists operation. + * Query the data source to determine if the source table exists. * * @return boolean TRUE if the table exists, otherwise FALSE. */ - protected function performTableExists() + protected function queryTableExists() { $dbh = $this->db(); $table = $this->table(); From 3561c6ee2b288b6ae4bac9953da1f6a91c0fab62 Mon Sep 17 00:00:00 2001 From: Chauncey McAskill Date: Wed, 29 Apr 2020 20:33:33 -0400 Subject: [PATCH 2/2] Add caching for DB table structure operations Similar to ac6f81d3 for table exists checks. By remembering the table structure, we don't need to look it up each time we want to insert or update a row. Saves a little bit of time off mass-inserts/updates. Until we can improve `alterTable()`, the cached table structure is cleared whenever a change is made to the table. Added: - Method `setTableStructure()` to store copy of table schema on PDO instance - Method `queryTableStructure()` to prepare and run actual table schema retrieval Changed: - Method `tableStructure()` to delegate and remember lookup - Method `alterTable() to clear cached table structure --- src/Charcoal/Source/DatabaseSource.php | 63 ++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/Charcoal/Source/DatabaseSource.php b/src/Charcoal/Source/DatabaseSource.php index 170c32c1..2b933297 100644 --- a/src/Charcoal/Source/DatabaseSource.php +++ b/src/Charcoal/Source/DatabaseSource.php @@ -141,6 +141,8 @@ public function table() /** * Create a table from a model's metadata. * + * @todo {@see self::setTableStructure() Save a copy} of the table structure. + * * @return boolean TRUE if the table was created, otherwise FALSE. */ public function createTable() @@ -196,6 +198,8 @@ public function createTable() /** * Alter an existing table to match the model's metadata. * + * @todo {@see self::setTableStructure() Save a copy} of the table structure. + * * @return boolean TRUE if the table was altered, otherwise FALSE. */ public function alterTable() @@ -208,12 +212,14 @@ public function alterTable() $table = $this->table(); $fields = $this->getModelFields($this->model()); $cols = $this->tableStructure(); + $alter = false; foreach ($fields as $field) { $ident = $field->ident(); if (!array_key_exists($ident, $cols)) { $fieldSql = $field->sql(); if ($fieldSql) { + $alter = true; // The key does not exist at all. $query = 'ALTER TABLE `'.$table.'` ADD '.$fieldSql; $this->logger->debug($query); @@ -228,6 +234,7 @@ public function alterTable() // The key exists. Validate. $col = $cols[$ident]; $alter = true; + if (strtolower($col['Type']) !== strtolower($field->sqlType())) { $alter = true; } @@ -256,6 +263,10 @@ public function alterTable() } } + if ($alter === true) { + $this->setTableStructure(null); + } + return true; } @@ -269,7 +280,7 @@ public function tableExists() $dbh = $this->db(); $table = $this->table(); - if (isset($dbh->tableExists, $dbh->tableExists[$table])) { + if (isset($dbh->tableExists[$table])) { return $dbh->tableExists[$table]; } @@ -322,14 +333,37 @@ protected function setTableExists($exists = true) } /** - * Get the table columns information. + * Retrieve the table columns structure. * - * @return array An associative array. + * @return array|null An associative array of the table schema, + * or an empty array if no table was found or if an error occurred. */ public function tableStructure() { $dbh = $this->db(); $table = $this->table(); + + if (isset($dbh->tableStructure[$table])) { + return $dbh->tableStructure[$table]; + } + + $struct = $this->queryTableStructure(); + $this->setTableStructure($struct); + + return $struct; + } + + /** + * Query the data source to retrieve the table columns structure. + * + * @return array|null An associative array of the table schema, + * or an empty array if no table was found or if an error occurred. + */ + protected function queryTableStructure() + { + $dbh = $this->db(); + $table = $this->table(); + $driver = $dbh->getAttribute(PDO::ATTR_DRIVER_NAME); if ($driver === self::SQLITE_DRIVER_NAME) { $query = sprintf('PRAGMA table_info("%s") ', $table); @@ -353,10 +387,29 @@ public function tableStructure() 'Extra' => '', ]; } + return $struct; - } else { - return $cols; } + + return $cols; + } + + /** + * Store a copy of the table columns information. + * + * @param array|null $struct An associative array. + * @return void + */ + protected function setTableStructure(array $struct = null) + { + $dbh = $this->db(); + $table = $this->table(); + + if (!isset($dbh->tableStructure)) { + $dbh->tableStructure = []; + } + + $dbh->tableStructure[$table] = $struct; } /**