/**
  * Translates Flourish SQL `ALTER TABLE * RENAME TO` statements to the appropriate
  * statements for SQLite
  *
  * @param string $sql                The SQL statements that will be executed against the database
  * @param array  &$extra_statements  Any extra SQL statements required for SQLite
  * @param array  $data               Data parsed from the `ALTER TABLE` statement
  * @return string  The modified SQL statement
  */
 private function translateSQLiteRenameTableStatements($sql, &$extra_statements, $data)
 {
     $tables = $this->getSQLiteTables();
     if (in_array($data['new_table_name'], $tables)) {
         $this->throwException(self::compose('A table with the name "%1$s" already exists', $data['new_table_name']), $sql);
     }
     if (!in_array($data['table'], $tables)) {
         $this->throwException(self::compose('The table specified, "%1$s", does not exist', $data['table']), $sql);
     }
     // We start by dropping all references to this table
     $foreign_keys = $this->getSQLiteForeignKeys($data['table']);
     foreach ($foreign_keys as $foreign_key) {
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("ALTER TABLE %r DROP FOREIGN KEY (%r)", array($foreign_key['table'], $foreign_key['column']), TRUE));
     }
     // SQLite 2 does not natively support renaming tables, so we have to do
     // it by creating a new table name and copying all data and indexes
     if (version_compare($this->database->getVersion(), 3, '<')) {
         $renamed_create_sql = preg_replace('#^\\s*CREATE\\s+TABLE\\s+["\\[`\']?\\w+["\\]`\']?\\s+#i', 'CREATE TABLE "' . $data['new_table_name'] . '" ', $this->getSQLiteCreateTable($data['table']));
         $this->addSQLiteTable($data['new_table_name'], $renamed_create_sql);
         // We rename string placeholders to prevent confusion with
         // string placeholders that are added by call to fDatabase
         $renamed_create_sql = str_replace(':string_', ':sub_string_', $renamed_create_sql);
         $create_statements = str_replace(':sub_string_', ':string_', $this->database->preprocess($renamed_create_sql, array(), TRUE));
         $extra_statements[] = array_shift($create_statements);
         // Recreate the indexes on the new table
         $indexes = $this->getSQLiteIndexes($data['table']);
         foreach ($indexes as $name => $index) {
             $create_sql = $index['sql'];
             preg_match('#^\\s*CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:[\'"`\\[]?\\w+[\'"`\\]]?\\.)?[\'"`\\[]?\\w+[\'"`\\]]?\\s+(ON\\s+[\'"`\\[]?\\w+[\'"`\\]]?)\\s*(\\((\\s*(?:\\s*[\'"`\\[]?\\w+[\'"`\\]]?\\s*,\\s*)*[\'"`\\[]?\\w+[\'"`\\]]?\\s*)\\))\\s*$#Di', $create_sql, $match);
             // Fix the table name to the new table
             $create_sql = str_replace($match[1], preg_replace('#(?:`|\'|"|\\[|\\b)?' . preg_quote($data['table'], '#') . '(?:`|\'|"|\\]|\\b)?#i', '"' . $data['new_table_name'] . '"', $match[1]), $create_sql);
             // We change the name of the index to keep it in sync
             // with the new table name
             $new_name = preg_replace('#^' . preg_quote($data['table'], '#') . '_#i', $data['new_table_name'] . '_', $name);
             $create_sql = preg_replace('#[\'"`\\[]?' . preg_quote($name, '#') . '[\'"`\\]]?(\\s+ON\\s+)#i', '"' . $new_name . '"\\1', $create_sql);
             $extra_statements[] = $create_sql;
             $this->addSQLiteIndex($new_name, $data['new_table_name'], $create_sql);
         }
         $column_names = $this->getSQLiteColumns($data['table']);
         $extra_statements[] = $this->database->escape("INSERT INTO %r (%r) SELECT %r FROM %r", $data['new_table_name'], $column_names, $column_names, $data['table']);
         $extra_statements = array_merge($extra_statements, $create_statements);
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("DROP TABLE %r", array($data['table']), TRUE));
         // SQLite 3 natively supports renaming tables, but it does not fix
         // references to the old table name inside of trigger bodies
     } else {
         // We add the rename SQL in the middle so it happens after we drop the
         // foreign key constraints and before we re-add them
         $extra_statements[] = $sql;
         $this->addSQLiteTable($data['new_table_name'], preg_replace('#^\\s*CREATE\\s+TABLE\\s+[\'"\\[`]?\\w+[\'"\\]`]?\\s+#i', 'CREATE TABLE "' . $data['new_table_name'] . '" ', $this->getSQLiteCreateTable($data['table'])));
         $this->removeSQLiteTable($data['table']);
         // Copy the trigger definitions to the new table name
         foreach ($this->getSQLiteTriggers() as $name => $trigger) {
             if ($trigger['table'] == $data['table']) {
                 $this->addSQLiteTrigger($name, $data['new_table_name'], $trigger['sql']);
             }
         }
         // Move the index definitions to the new table name
         foreach ($this->getSQLiteIndexes($data['table']) as $name => $index) {
             $this->addSQLiteIndex($name, $data['new_table_name'], preg_replace('#(\\s+ON\\s+)["\'`\\[]?\\w+["\'`\\]]?#', '\\1"' . preg_quote($data['new_table_name'], '#') . '"', $index['sql']));
         }
         foreach ($this->getSQLiteTriggers() as $name => $trigger) {
             $create_sql = $trigger['sql'];
             $create_sql = preg_replace('#( on table )"' . $data['table'] . '"#i', '\\1"' . $data['new_table_name'] . '"', $create_sql);
             $create_sql = preg_replace('#(\\s+FROM\\s+)(`' . $data['table'] . '`|"' . $data['table'] . '"|\'' . $data['table'] . '\'|' . $data['table'] . '|\\[' . $data['table'] . '\\])#i', '\\1"' . $data['new_table_name'] . '"', $create_sql);
             if ($create_sql != $trigger['sql']) {
                 $extra_statements[] = $this->database->escape("DROP TRIGGER %r", $name);
                 $this->removeSQLiteTrigger($name);
                 $this->addSQLiteTrigger($name, $data['new_table_name'], $create_sql);
                 $extra_statements[] = $create_sql;
             }
         }
     }
     // Here we recreate the references that we dropped at the beginning
     foreach ($foreign_keys as $foreign_key) {
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("ALTER TABLE %r ADD FOREIGN KEY (%r) REFERENCES %r(%r) ON UPDATE " . $foreign_key['on_update'] . " ON DELETE " . $foreign_key['on_delete'], array($foreign_key['table'], $foreign_key['column'], $data['new_table_name'], $foreign_key['foreign_column']), TRUE));
     }
     // Remove any nested transactions
     $extra_statements = array_diff($extra_statements, array("BEGIN", "COMMIT"));
     // Since the actual rename or create/drop has to happen after adjusting
     // foreign keys, we previously added it in the appropriate place and
     // now need to provide the first statement to be run
     return array_shift($extra_statements);
 }