Habari\SQLiteConnection::dbdelta PHP Method

dbdelta() public method

automatic diffing function - used for determining required database upgrades based on Owen Winkler's microwiki upgrade function
public dbdelta ( $queries, $execute = true, $silent = true, $doinserts = false ) : string
return string translated SQL string
    function dbdelta($queries, $execute = true, $silent = true, $doinserts = false)
    {
        if (!is_array($queries)) {
            $queries = explode(';', $queries);
            if ('' == $queries[count($queries) - 1]) {
                array_pop($queries);
            }
        }
        $cqueries = array();
        $indexqueries = array();
        $iqueries = array();
        $pqueries = array();
        $for_update = array();
        $allqueries = array();
        foreach ($queries as $qry) {
            if (preg_match("|CREATE TABLE ([^ ]*)|", $qry, $matches)) {
                $cqueries[strtolower($matches[1])] = $qry;
                $for_update[$matches[1]] = 'Created table ' . $matches[1];
            } else {
                if (preg_match("|CREATE (UNIQUE )?INDEX ([^ ]*)|", $qry, $matches)) {
                    $indexqueries[] = $qry;
                } else {
                    if (preg_match("|INSERT INTO ([^ ]*)|", $qry, $matches)) {
                        $iqueries[] = $qry;
                    } else {
                        if (preg_match("|UPDATE ([^ ]*)|", $qry, $matches)) {
                            $iqueries[] = $qry;
                        } else {
                            if (preg_match("|PRAGMA ([^ ]*)|", $qry, $matches)) {
                                $pqueries[] = $qry;
                            } else {
                                // Unrecognized query type
                            }
                        }
                    }
                }
            }
        }
        // Merge the queries into allqueries; pragmas MUST go first
        $allqueries = array_merge($pqueries);
        $tables = $this->get_column("SELECT name FROM sqlite_master WHERE type = 'table';");
        foreach ($cqueries as $tablename => $query) {
            if (in_array($tablename, $tables)) {
                $sql = $this->get_value("SELECT sql FROM sqlite_master WHERE type = 'table' AND name='" . $tablename . "';");
                $sql = preg_replace('%\\s+%', ' ', $sql) . ';';
                $query = preg_replace('%\\s+%', ' ', $query);
                if ($sql != $query) {
                    $this->query("ALTER TABLE {$tablename} RENAME TO {$tablename}__temp;");
                    $this->query($query);
                    $new_fields_temp = $this->get_results("pragma table_info({$tablename});");
                    $new_fields = array();
                    foreach ($new_fields_temp as $field) {
                        $new_fields[$field->name] = $field;
                    }
                    $old_fields = $this->get_results("pragma table_info({$tablename}__temp);");
                    $new_field_names = array_map(array($this, 'filter_fieldnames'), $new_fields);
                    $old_field_names = array_map(array($this, 'filter_fieldnames'), $old_fields);
                    $used_field_names = array_intersect($new_field_names, $old_field_names);
                    $used_field_names = implode(',', $used_field_names);
                    $needed_fields = array_diff($new_field_names, $old_field_names);
                    foreach ($needed_fields as $needed_field_name) {
                        $used_field_names .= ",'" . $new_fields[$needed_field_name]->dflt_value . "' as " . $needed_field_name;
                    }
                    $this->query("INSERT INTO {$tablename} SELECT {$used_field_names} FROM {$tablename}__temp;");
                    $this->query("DROP TABLE {$tablename}__temp;");
                }
            } else {
                $allqueries[] = $query;
            }
        }
        // Drop all indices that we created, they'll get recreated by indexqueries below.
        // The other option would be to loop through the indices, comparing with indexqueries, and only drop the ones that have changed.
        $indices = DB::get_column("SELECT name FROM sqlite_master WHERE type='index' AND name NOT LIKE 'sqlite_autoindex_%'");
        foreach ($indices as $name) {
            DB::exec('DROP INDEX ' . $name);
        }
        $allqueries = array_merge($allqueries, $indexqueries);
        if ($doinserts) {
            $allqueries = array_merge($allqueries, $iqueries);
        }
        if ($execute) {
            DB::exec('PRAGMA cache_size=4000');
            foreach ($allqueries as $query) {
                if (!$this->query($query)) {
                    $this->get_errors();
                    return false;
                }
            }
        }
        return $allqueries;
    }