diff --git a/lang/en/cache.php b/lang/en/cache.php index a8005aee283..327da655308 100644 --- a/lang/en/cache.php +++ b/lang/en/cache.php @@ -63,6 +63,7 @@ $string['cachedef_search_results'] = 'Search results user data'; $string['cachedef_grade_categories'] = 'Grade category queries'; $string['cachedef_string'] = 'Language string cache'; $string['cachedef_tags'] = 'Tags collections and areas'; +$string['cachedef_temp_tables'] = 'Temporary tables cache'; $string['cachedef_userselections'] = 'Data used to persist user selections throughout Moodle'; $string['cachedef_yuimodules'] = 'YUI Module definitions'; $string['cachelock_file_default'] = 'Default file locking'; diff --git a/lib/db/caches.php b/lib/db/caches.php index f9b0bd6c7e4..f5bbb401b6f 100644 --- a/lib/db/caches.php +++ b/lib/db/caches.php @@ -276,4 +276,10 @@ $definitions = array( 'mode' => cache_store::MODE_REQUEST, 'simplekeys' => true, ), + + // Store temporary tables information. + 'temp_tables' => array( + 'mode' => cache_store::MODE_REQUEST, + 'simplekeys' => true + ) ); diff --git a/lib/ddl/database_manager.php b/lib/ddl/database_manager.php index a909f337209..aa01e3cba19 100644 --- a/lib/ddl/database_manager.php +++ b/lib/ddl/database_manager.php @@ -70,10 +70,11 @@ class database_manager { * This function will execute an array of SQL commands. * * @param string[] $sqlarr Array of sql statements to execute. + * @param array|null $tablenames an array of xmldb table names affected by this request. * @throws ddl_change_structure_exception This exception is thrown if any error is found. */ - protected function execute_sql_arr(array $sqlarr) { - $this->mdb->change_database_structure($sqlarr); + protected function execute_sql_arr(array $sqlarr, $tablenames = null) { + $this->mdb->change_database_structure($sqlarr, $tablenames); } /** @@ -107,6 +108,12 @@ class database_manager { public function reset_sequence($table) { if (!is_string($table) and !($table instanceof xmldb_table)) { throw new ddl_exception('ddlunknownerror', NULL, 'incorrect table parameter!'); + } else { + if ($table instanceof xmldb_table) { + $tablename = $table->getName(); + } else { + $tablename = $table; + } } // Do not test if table exists because it is slow @@ -115,7 +122,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'table reset sequence sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($tablename)); } /** @@ -322,8 +329,7 @@ class database_manager { if (!$sqlarr = $this->generator->getDropTableSQL($xmldb_table)) { throw new ddl_exception('ddlunknownerror', null, 'table drop sql not generated'); } - - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -409,7 +415,14 @@ class database_manager { if (!$sqlarr = $this->generator->getCreateStructureSQL($xmldb_structure)) { return; // nothing to do } - $this->execute_sql_arr($sqlarr); + + $tablenames = array(); + foreach ($xmldb_structure as $xmldb_table) { + if ($xmldb_table instanceof xmldb_table) { + $tablenames[] = $xmldb_table->getName(); + } + } + $this->execute_sql_arr($sqlarr, $tablenames); } /** @@ -428,7 +441,7 @@ class database_manager { if (!$sqlarr = $this->generator->getCreateTableSQL($xmldb_table)) { throw new ddl_exception('ddlunknownerror', null, 'table create sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -451,8 +464,7 @@ class database_manager { if (!$sqlarr = $this->generator->getCreateTempTableSQL($xmldb_table)) { throw new ddl_exception('ddlunknownerror', null, 'temp table create sql not generated'); } - - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -530,7 +542,7 @@ class database_manager { if (!$sqlarr = $this->generator->getAddFieldSQL($xmldb_table, $xmldb_field)) { throw new ddl_exception('ddlunknownerror', null, 'addfield sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -555,7 +567,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'drop_field sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -580,7 +592,7 @@ class database_manager { return; // probably nothing to do } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -643,7 +655,7 @@ class database_manager { return; //Empty array = nothing to do = no error } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -687,7 +699,7 @@ class database_manager { return; //Empty array = nothing to do = no error } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -741,7 +753,7 @@ class database_manager { return; //Empty array = nothing to do = no error } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -760,7 +772,7 @@ class database_manager { return; //Empty array = nothing to do = no error } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -784,7 +796,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support key renaming (MySQL, PostgreSQL, MsSQL). Rename skipped'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -811,7 +823,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'add_index sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -838,7 +850,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'drop_index sql not generated'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** @@ -870,7 +882,7 @@ class database_manager { throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support index renaming (MySQL). Rename skipped'); } - $this->execute_sql_arr($sqlarr); + $this->execute_sql_arr($sqlarr, array($xmldb_table->getName())); } /** diff --git a/lib/ddl/sql_generator.php b/lib/ddl/sql_generator.php index 8e50fe13b00..356fb719ddc 100644 --- a/lib/ddl/sql_generator.php +++ b/lib/ddl/sql_generator.php @@ -226,9 +226,12 @@ abstract class sql_generator { $tablename = $table->getName(); } + if ($this->temptables->is_temptable($tablename)) { + return true; + } + // Get all tables in moodle database. $tables = $this->mdb->get_tables(); - return isset($tables[$tablename]); } diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 1573ef51d38..4f74576e059 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -336,6 +336,15 @@ abstract class moodle_database { return cache::make('core', 'databasemeta', $properties); } + /** + * Handle the creation and caching of the temporary tables. + * + * @return cache_application The temp_tables cachestore to complete operations on. + */ + protected function get_temp_tables_cache() { + return cache::make('core', 'temp_tables'); + } + /** * Attempt to create the database * @param string $dbhost The database host. @@ -1040,13 +1049,32 @@ abstract class moodle_database { /** * Resets the internal column details cache + * + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return void */ - public function reset_caches() { - $this->tables = null; - // Purge MUC as well. - $this->get_metacache()->purge(); - $this->metacache = null; + public function reset_caches($tablenames = null) { + if (!empty($tablenames)) { + $temptablepurged = false; + $dbmetapurged = false; + foreach ($tablenames as $tablename) { + if ($temptablepurged === false && $this->temptables->is_temptable($tablename)) { + $this->get_temp_tables_cache()->purge(); + $temptablepurged = true; + } else if ($dbmetapurged === false) { + $this->tables = null; + $this->get_metacache()->purge(); + $this->metacache = null; + $dbmetapurged = true; + } + } + } else { + $this->get_temp_tables_cache()->purge(); + $this->tables = null; + // Purge MUC as well. + $this->get_metacache()->purge(); + $this->metacache = null; + } } /** @@ -1115,10 +1143,11 @@ abstract class moodle_database { /** * Do NOT use in code, this is for use by database_manager only! * @param string|array $sql query or array of queries + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public abstract function change_database_structure($sql); + public abstract function change_database_structure($sql, $tablenames = null); /** * Executes a general sql query. Should be used only when no other method suitable. diff --git a/lib/dml/mssql_native_moodle_database.php b/lib/dml/mssql_native_moodle_database.php index 6c9506ca053..fd1721abfb0 100644 --- a/lib/dml/mssql_native_moodle_database.php +++ b/lib/dml/mssql_native_moodle_database.php @@ -438,8 +438,14 @@ class mssql_native_moodle_database extends moodle_database { public function get_columns($table, $usecache=true) { if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -534,7 +540,11 @@ class mssql_native_moodle_database extends moodle_database { $this->free_result($result); if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; @@ -634,10 +644,11 @@ class mssql_native_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) $sqls = (array)$sql; @@ -648,11 +659,11 @@ class mssql_native_moodle_database extends moodle_database { $this->query_end($result); } } catch (ddl_change_structure_exception $e) { - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 32a5db7a887..e8015a276dd 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -576,10 +576,15 @@ class mysqli_native_moodle_database extends moodle_database { * @return database_column_info[] array of database_column_info objects indexed with column names */ public function get_columns($table, $usecache=true) { - if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -684,7 +689,11 @@ class mysqli_native_moodle_database extends moodle_database { } if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; @@ -887,10 +896,11 @@ class mysqli_native_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) if (is_array($sql)) { $sql = implode("\n;\n", $sql); @@ -913,11 +923,11 @@ class mysqli_native_moodle_database extends moodle_database { while (@$this->mysqli->more_results()) { @$this->mysqli->next_result(); } - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/oci_native_moodle_database.php b/lib/dml/oci_native_moodle_database.php index c19373df991..929ffbd13eb 100644 --- a/lib/dml/oci_native_moodle_database.php +++ b/lib/dml/oci_native_moodle_database.php @@ -470,8 +470,14 @@ class oci_native_moodle_database extends moodle_database { public function get_columns($table, $usecache=true) { if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -662,7 +668,11 @@ class oci_native_moodle_database extends moodle_database { } if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; @@ -887,10 +897,11 @@ class oci_native_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) $sqls = (array)$sql; @@ -903,11 +914,11 @@ class oci_native_moodle_database extends moodle_database { oci_free_statement($stmt); } } catch (ddl_change_structure_exception $e) { - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/pdo_moodle_database.php b/lib/dml/pdo_moodle_database.php index 29cdd65b5de..7f719059bd9 100644 --- a/lib/dml/pdo_moodle_database.php +++ b/lib/dml/pdo_moodle_database.php @@ -175,10 +175,11 @@ abstract class pdo_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) $sqls = (array)$sql; @@ -196,11 +197,11 @@ abstract class pdo_moodle_database extends moodle_database { $this->query_end($result); } } catch (ddl_change_structure_exception $e) { - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index 21f86e73314..efc5043eac6 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -390,8 +390,14 @@ class pgsql_native_moodle_database extends moodle_database { */ public function get_columns($table, $usecache=true) { if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -594,7 +600,11 @@ class pgsql_native_moodle_database extends moodle_database { pg_free_result($result); if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; @@ -650,10 +660,11 @@ class pgsql_native_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) if (is_array($sql)) { $sql = implode("\n;\n", $sql); @@ -673,11 +684,11 @@ class pgsql_native_moodle_database extends moodle_database { $result = @pg_query($this->pgsql, "ROLLBACK"); @pg_free_result($result); } - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/sqlite3_pdo_moodle_database.php b/lib/dml/sqlite3_pdo_moodle_database.php index 1196d67a9f4..58753bd9d24 100644 --- a/lib/dml/sqlite3_pdo_moodle_database.php +++ b/lib/dml/sqlite3_pdo_moodle_database.php @@ -201,8 +201,14 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database { public function get_columns($table, $usecache=true) { if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -298,7 +304,11 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database { } if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; diff --git a/lib/dml/sqlsrv_native_moodle_database.php b/lib/dml/sqlsrv_native_moodle_database.php index 904e7e3e19e..e2d253f1669 100644 --- a/lib/dml/sqlsrv_native_moodle_database.php +++ b/lib/dml/sqlsrv_native_moodle_database.php @@ -508,8 +508,14 @@ class sqlsrv_native_moodle_database extends moodle_database { */ public function get_columns($table, $usecache = true) { if ($usecache) { - if ($data = $this->get_metacache()->get($table)) { - return $data; + if ($this->temptables->is_temptable($table)) { + if ($data = $this->get_temp_tables_cache()->get($table)) { + return $data; + } + } else { + if ($data = $this->get_metacache()->get($table)) { + return $data; + } } } @@ -604,7 +610,11 @@ class sqlsrv_native_moodle_database extends moodle_database { $this->free_result($result); if ($usecache) { - $this->get_metacache()->set($table, $structure); + if ($this->temptables->is_temptable($table)) { + $this->get_temp_tables_cache()->set($table, $structure); + } else { + $this->get_metacache()->set($table, $structure); + } } return $structure; @@ -714,10 +724,11 @@ class sqlsrv_native_moodle_database extends moodle_database { /** * Do NOT use in code, to be used by database_manager only! * @param string|array $sql query + * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ - public function change_database_structure($sql) { + public function change_database_structure($sql, $tablenames = null) { $this->get_manager(); // Includes DDL exceptions classes ;-) $sqls = (array)$sql; @@ -728,11 +739,11 @@ class sqlsrv_native_moodle_database extends moodle_database { $this->query_end($result); } } catch (ddl_change_structure_exception $e) { - $this->reset_caches(); + $this->reset_caches($tablenames); throw $e; } - $this->reset_caches(); + $this->reset_caches($tablenames); return true; } diff --git a/lib/dml/tests/dml_test.php b/lib/dml/tests/dml_test.php index 7e9dc550bf3..b2bb25e9d0b 100644 --- a/lib/dml/tests/dml_test.php +++ b/lib/dml/tests/dml_test.php @@ -5510,7 +5510,7 @@ class moodle_database_for_testing extends moodle_database { protected function normalise_value($column, $value) {} public function set_debug($state) {} public function get_debug() {} - public function change_database_structure($sql) {} + public function change_database_structure($sql, $tablenames = null) {} public function execute($sql, array $params=null) {} public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {} public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {}