1
0
mirror of https://github.com/flarum/core.git synced 2025-08-06 16:36:47 +02:00

feat: add support for SQLite (#3984)

* feat: add support for sqlite

* chore: add warning on install

* fix: ignore constraints before transaction begins

* chore: update workflow

* Apply fixes from StyleCI

* chore: generate sqlite dump and manually add foreign keys

* chore: fix actions

* chore: fix actions

* chore: fix actions

* chore: fix actions

* chore: fix actions

* chore: fix actions

* test: fix

* Apply fixes from StyleCI

* fix: sqlite with db prefix

* Apply fixes from StyleCI

* fix: statistics sqlite
This commit is contained in:
Sami Mazouz
2024-06-21 07:25:11 +01:00
committed by GitHub
parent 5ce1aeab47
commit eb6e599df1
61 changed files with 801 additions and 263 deletions

View File

@@ -34,7 +34,10 @@ return [
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ADD FULLTEXT content (content)');
if ($connection->getDriverName() !== 'sqlite') {
$connection->statement('ALTER TABLE '.$prefix.'posts ADD FULLTEXT content (content)');
}
},
'down' => function (Builder $schema) {

View File

@@ -12,10 +12,12 @@ use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->table('access_tokens', function (Blueprint $table) {
$table->dropColumn('created_at', 'expires_at');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->string('id', 40)->change();
$table->dropColumn('created_at');
$table->dropColumn('expires_at');
$table->integer('last_activity');
$table->integer('lifetime');
});
@@ -24,8 +26,7 @@ return [
'down' => function (Builder $schema) {
$schema->table('access_tokens', function (Blueprint $table) {
$table->string('id', 100)->change();
$table->dropColumn('last_activity');
$table->dropColumn('lifetime');
$table->dropColumn('last_activity', 'lifetime');
$table->timestamp('created_at');
$table->timestamp('expires_at');
});

View File

@@ -14,14 +14,20 @@ return [
'up' => function (Builder $schema) {
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('id', 'token');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('lifetime', 'lifetime_seconds');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('last_activity', 'last_activity_at');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->dateTime('created_at');
$table->integer('user_id')->unsigned()->change();
});
// Use a separate schema instance because this column gets renamed
// in the first one.
// in the previous one.
$schema->table('access_tokens', function (Blueprint $table) {
$table->dateTime('last_activity_at')->change();
});
@@ -31,12 +37,19 @@ return [
$schema->table('access_tokens', function (Blueprint $table) {
$table->integer('last_activity_at')->change();
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('token', 'id');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('lifetime_seconds', 'lifetime');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->renameColumn('last_activity_at', 'last_activity');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->dropColumn('created_at');
});
$schema->table('access_tokens', function (Blueprint $table) {
$table->integer('user_id')->change();
});
}

View File

@@ -12,13 +12,7 @@ use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->table('api_keys', function (Blueprint $table) {
$table->dropPrimary(['id']);
$table->renameColumn('id', 'key');
$table->unique('key');
});
$schema->table('api_keys', function (Blueprint $table) {
$definition = function (Blueprint $table) {
$table->increments('id');
$table->string('allowed_ips')->nullable();
$table->string('scopes')->nullable();
@@ -27,7 +21,23 @@ return [
$table->dateTime('last_activity_at')->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
};
if ($schema->getConnection()->getDriverName() !== 'sqlite') {
$schema->table('api_keys', function (Blueprint $table) {
$table->dropPrimary(['id']);
$table->renameColumn('id', 'key');
$table->unique('key');
});
$schema->table('api_keys', $definition);
} else {
$schema->drop('api_keys');
$schema->create('api_keys', function (Blueprint $table) use ($definition) {
$table->string('key', 100)->unique();
$definition($table);
});
}
},
'down' => function (Builder $schema) {
@@ -36,10 +46,13 @@ return [
$table->dropColumn('id', 'allowed_ips', 'user_id', 'scopes', 'created_at');
});
$schema->table('api_keys', function (Blueprint $table) {
$schema->table('api_keys', function (Blueprint $table) use ($schema) {
$table->dropUnique(['key']);
$table->renameColumn('key', 'id');
$table->primary('id');
if ($schema->getConnection()->getDriverName() !== 'sqlite') {
$table->primary('id');
}
});
}
];

View File

@@ -7,19 +7,19 @@
* LICENSE file that was distributed with this source code.
*/
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}registration_tokens MODIFY created_at DATETIME");
$schema->table('registration_tokens', function (Blueprint $table) {
$table->dateTime('created_at')->change();
});
},
'down' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}registration_tokens MODIFY created_at TIMESTAMP");
$schema->table('registration_tokens', function (Blueprint $table) {
$table->timestamp('created_at')->change();
});
}
];

View File

@@ -12,13 +12,19 @@ use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = InnoDB');
if ($connection->getDriverName() === 'mysql') {
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = InnoDB');
}
},
'down' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = MyISAM');
if ($connection->getDriverName() === 'mysql') {
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = MyISAM');
}
}
];

View File

@@ -7,19 +7,19 @@
* LICENSE file that was distributed with this source code.
*/
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}email_tokens MODIFY created_at DATETIME");
$schema->table('email_tokens', function (Blueprint $table) {
$table->dateTime('created_at')->change();
});
},
'down' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}email_tokens MODIFY created_at TIMESTAMP");
$schema->table('email_tokens', function (Blueprint $table) {
$table->timestamp('created_at')->change();
});
}
];

View File

@@ -15,10 +15,14 @@ return [
'up' => function (Builder $schema) {
$schema->table('notifications', function (Blueprint $table) {
$table->dropColumn('subject_type');
});
$schema->table('notifications', function (Blueprint $table) {
$table->renameColumn('time', 'created_at');
});
$schema->table('notifications', function (Blueprint $table) {
$table->renameColumn('sender_id', 'from_user_id');
});
$schema->table('notifications', function (Blueprint $table) {
$table->dateTime('read_at')->nullable();
});
@@ -36,8 +40,11 @@ return [
$table->string('subject_type', 200)->nullable();
$table->renameColumn('created_at', 'time');
});
$schema->table('notifications', function (Blueprint $table) {
$table->renameColumn('from_user_id', 'sender_id');
});
$schema->table('notifications', function (Blueprint $table) {
$table->boolean('is_read');
});

View File

@@ -7,19 +7,19 @@
* LICENSE file that was distributed with this source code.
*/
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}password_tokens MODIFY created_at DATETIME");
$schema->table('password_tokens', function (Blueprint $table) {
$table->dateTime('created_at')->change();
});
},
'down' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE {$prefix}password_tokens MODIFY created_at TIMESTAMP");
$schema->table('password_tokens', function (Blueprint $table) {
$table->timestamp('created_at')->change();
});
}
];

View File

@@ -13,7 +13,10 @@ return [
'up' => function (Builder $schema) {
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'discussions ADD FULLTEXT title (title)');
if ($connection->getDriverName() !== 'sqlite') {
$connection->statement('ALTER TABLE '.$prefix.'discussions ADD FULLTEXT title (title)');
}
},
'down' => function (Builder $schema) {

View File

@@ -12,24 +12,42 @@ use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->table('access_tokens', function (Blueprint $table) {
// Replace primary key with unique index so we can create a new primary
$table->dropPrimary('token');
$table->unique('token');
});
if ($schema->getConnection()->getDriverName() !== 'sqlite') {
$schema->table('access_tokens', function (Blueprint $table) {
// Replace primary key with unique index so we can create a new primary
$table->dropPrimary('token');
$table->unique('token');
});
// This needs to be done in a second statement because of the order Laravel runs operations in
$schema->table('access_tokens', function (Blueprint $table) {
// Introduce new increment-based ID
$table->increments('id')->first();
});
// This needs to be done in a second statement because of the order Laravel runs operations in
$schema->table('access_tokens', function (Blueprint $table) {
// Introduce new increment-based ID
$table->increments('id')->first();
});
} else {
$schema->drop('access_tokens');
$schema->create('access_tokens', function (Blueprint $table) {
$table->increments('id');
$table->string('token', 100)->unique();
$table->integer('user_id')->unsigned();
$table->dateTime('last_activity_at')->nullable();
$table->dateTime('created_at');
$table->string('type', 100)->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->index('type');
});
}
},
'down' => function (Builder $schema) {
$schema->table('access_tokens', function (Blueprint $table) {
$schema->table('access_tokens', function (Blueprint $table) use ($schema) {
$table->dropColumn('id');
$table->dropIndex('token');
$table->primary('token');
if ($schema->getConnection()->getDriverName() !== 'sqlite') {
$table->primary('token');
}
});
}
];

View File

@@ -17,17 +17,15 @@ return [
$table->timestamp('updated_at')->nullable();
});
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE `${prefix}groups` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
$connection->statement("ALTER TABLE `${prefix}groups` MODIFY updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
$schema->table('groups', function (Blueprint $table) {
$table->timestamp('created_at')->nullable()->useCurrent()->change();
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate()->change();
});
},
'down' => function (Builder $schema) {
$schema->table('groups', function (Blueprint $table) {
$table->dropColumn('created_at');
$table->dropColumn('updated_at');
$table->dropColumn('created_at', 'updated_at');
});
}
];

View File

@@ -16,10 +16,9 @@ return [
$table->timestamp('created_at')->nullable();
});
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE `${prefix}group_user` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
$schema->table('group_user', function (Blueprint $table) {
$table->timestamp('created_at')->nullable()->useCurrent()->change();
});
},
'down' => function (Builder $schema) {

View File

@@ -16,10 +16,9 @@ return [
$table->timestamp('created_at')->nullable();
});
// do this manually because dbal doesn't recognize timestamp columns
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement("ALTER TABLE `${prefix}group_permission` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
$schema->table('group_permission', function (Blueprint $table) {
$table->timestamp('created_at')->nullable()->useCurrent()->change();
});
},
'down' => function (Builder $schema) {

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
if ($schema->getConnection()->getDriverName() === 'sqlite') {
$schema->getConnection()->statement('PRAGMA foreign_keys = OFF');
$schema->getConnection()->statement('PRAGMA writable_schema = ON');
$prefix = $schema->getConnection()->getTablePrefix();
$foreignKeysSqlite = [
'discussions' => <<<SQL
foreign key("user_id") references "{$prefix}users"("id") on delete set null,
foreign key("last_posted_user_id") references "{$prefix}users"("id") on delete set null,
foreign key("hidden_user_id") references "{$prefix}users"("id") on delete set null,
foreign key("first_post_id") references "{$prefix}posts"("id") on delete set null,
foreign key("last_post_id") references "{$prefix}posts"("id") on delete set null
SQL,
'posts' => <<<SQL
foreign key("discussion_id") references "{$prefix}discussions"("id") on delete cascade,
foreign key("user_id") references "{$prefix}users"("id") on delete set null,
foreign key("edited_user_id") references "{$prefix}users"("id") on delete set null,
foreign key("hidden_user_id") references "{$prefix}users"("id") on delete set null
SQL,
];
foreach (['discussions', 'posts'] as $table) {
$tableDefinition = $schema->getConnection()->select('SELECT sql FROM sqlite_master WHERE type = "table" AND name = "'.$prefix.$table.'"')[0]->sql;
$modifiedTableDefinition = str($tableDefinition)->beforeLast(')')->append(', '.$foreignKeysSqlite[$table].')')->toString();
$modifiedTableDefinitionWithEscapedQuotes = str($modifiedTableDefinition)->replace('"', '""')->toString();
$schema->getConnection()->statement('UPDATE sqlite_master SET sql = "'.$modifiedTableDefinitionWithEscapedQuotes.'" WHERE type = "table" AND name = "'.$prefix.$table.'"');
}
$schema->getConnection()->statement('PRAGMA writable_schema = OFF');
$schema->getConnection()->statement('PRAGMA foreign_keys = ON');
}
},
];

View File

@@ -0,0 +1,132 @@
CREATE TABLE IF NOT EXISTS "db_prefix_migrations" ("id" integer primary key autoincrement not null, "migration" varchar not null, "extension" varchar);
CREATE TABLE IF NOT EXISTS "db_prefix_groups" ("id" integer primary key autoincrement not null, "name_singular" varchar not null, "name_plural" varchar not null, "color" varchar, "icon" varchar, "is_hidden" tinyint(1) not null default '0', "created_at" datetime, "updated_at" datetime);
CREATE TABLE IF NOT EXISTS "db_prefix_group_permission" ("group_id" integer not null, "permission" varchar not null, "created_at" datetime, primary key ("group_id", "permission"));
CREATE TABLE IF NOT EXISTS "db_prefix_group_user" ("user_id" integer not null, "group_id" integer not null, "created_at" datetime, primary key ("user_id", "group_id"));
CREATE TABLE db_prefix_settings ("key" VARCHAR(255) NOT NULL, value CLOB DEFAULT NULL, PRIMARY KEY("key"));
CREATE TABLE IF NOT EXISTS "db_prefix_api_keys" ("key" varchar not null, "id" integer primary key autoincrement not null, "allowed_ips" varchar, "scopes" varchar, "user_id" integer, "created_at" datetime not null, "last_activity_at" datetime, foreign key("user_id") references "db_prefix_users"("id") on delete cascade);
CREATE UNIQUE INDEX "db_prefix_api_keys_key_unique" on "db_prefix_api_keys" ("key");
CREATE TABLE db_prefix_discussion_user (user_id INTEGER NOT NULL, discussion_id INTEGER NOT NULL, last_read_at DATETIME DEFAULT NULL, last_read_post_number INTEGER DEFAULT NULL, PRIMARY KEY(user_id, discussion_id));
CREATE TABLE db_prefix_email_tokens (token VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL COLLATE "BINARY", user_id INTEGER NOT NULL, created_at DATETIME NOT NULL, PRIMARY KEY(token));
CREATE TABLE db_prefix_notifications (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, from_user_id INTEGER DEFAULT NULL, type VARCHAR(255) NOT NULL COLLATE "BINARY", subject_id INTEGER DEFAULT NULL, data BLOB DEFAULT NULL, created_at DATETIME NOT NULL, is_deleted BOOLEAN DEFAULT 0 NOT NULL, read_at DATETIME DEFAULT NULL);
CREATE TABLE db_prefix_password_tokens (token VARCHAR(255) NOT NULL, user_id INTEGER NOT NULL, created_at DATETIME NOT NULL, PRIMARY KEY(token));
CREATE TABLE IF NOT EXISTS "db_prefix_post_user" ("post_id" integer not null, "user_id" integer not null, foreign key("post_id") references "db_prefix_posts"("id") on delete cascade, foreign key("user_id") references "db_prefix_users"("id") on delete cascade, primary key ("post_id", "user_id"));
CREATE TABLE db_prefix_users (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(255) NOT NULL COLLATE "BINARY", email VARCHAR(255) NOT NULL COLLATE "BINARY", is_email_confirmed BOOLEAN DEFAULT 0 NOT NULL, password VARCHAR(255) NOT NULL COLLATE "BINARY", avatar_url VARCHAR(255) DEFAULT NULL, preferences BLOB DEFAULT NULL, joined_at DATETIME DEFAULT NULL, last_seen_at DATETIME DEFAULT NULL, marked_all_as_read_at DATETIME DEFAULT NULL, read_notifications_at DATETIME DEFAULT NULL, discussion_count INTEGER DEFAULT 0 NOT NULL, comment_count INTEGER DEFAULT 0 NOT NULL);
CREATE UNIQUE INDEX db_prefix_users_email_unique ON db_prefix_users (email);
CREATE UNIQUE INDEX db_prefix_users_username_unique ON db_prefix_users (username);
CREATE INDEX "db_prefix_users_joined_at_index" on "db_prefix_users" ("joined_at");
CREATE INDEX "db_prefix_users_last_seen_at_index" on "db_prefix_users" ("last_seen_at");
CREATE INDEX "db_prefix_users_discussion_count_index" on "db_prefix_users" ("discussion_count");
CREATE INDEX "db_prefix_users_comment_count_index" on "db_prefix_users" ("comment_count");
CREATE INDEX "db_prefix_notifications_user_id_index" on "db_prefix_notifications" ("user_id");
CREATE TABLE db_prefix_registration_tokens (token VARCHAR(255) NOT NULL, payload CLOB DEFAULT NULL, created_at DATETIME NOT NULL, "provider" varchar not null, "identifier" varchar not null, "user_attributes" text, PRIMARY KEY(token));
CREATE TABLE IF NOT EXISTS "db_prefix_login_providers" ("id" integer primary key autoincrement not null, "user_id" integer not null, "provider" varchar not null, "identifier" varchar not null, "created_at" datetime, "last_login_at" datetime, foreign key("user_id") references "db_prefix_users"("id") on delete cascade);
CREATE UNIQUE INDEX "db_prefix_login_providers_provider_identifier_unique" on "db_prefix_login_providers" ("provider", "identifier");
CREATE TABLE IF NOT EXISTS "db_prefix_access_tokens" ("id" integer primary key autoincrement not null, "token" varchar not null, "user_id" integer not null, "last_activity_at" datetime, "created_at" datetime not null, "type" varchar, "title" varchar, "last_ip_address" varchar, "last_user_agent" varchar, foreign key("user_id") references "db_prefix_users"("id") on delete cascade);
CREATE INDEX "db_prefix_access_tokens_type_index" on "db_prefix_access_tokens" ("type");
CREATE UNIQUE INDEX "db_prefix_access_tokens_token_unique" on "db_prefix_access_tokens" ("token");
CREATE TABLE db_prefix_posts (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, discussion_id INTEGER NOT NULL, number INTEGER DEFAULT NULL, created_at DATETIME NOT NULL, user_id INTEGER DEFAULT NULL, type VARCHAR(255) DEFAULT NULL, content CLOB DEFAULT NULL --
, edited_at DATETIME DEFAULT NULL, edited_user_id INTEGER DEFAULT NULL, hidden_at DATETIME DEFAULT NULL, hidden_user_id INTEGER DEFAULT NULL, ip_address VARCHAR(255) DEFAULT NULL, is_private BOOLEAN DEFAULT 0 NOT NULL, foreign key("discussion_id") references "db_prefix_discussions"("id") on delete cascade,
foreign key("user_id") references "db_prefix_users"("id") on delete set null,
foreign key("edited_user_id") references "db_prefix_users"("id") on delete set null,
foreign key("hidden_user_id") references "db_prefix_users"("id") on delete set null);
CREATE INDEX db_prefix_posts_user_id_created_at_index ON db_prefix_posts (user_id, created_at);
CREATE INDEX db_prefix_posts_discussion_id_created_at_index ON db_prefix_posts (discussion_id, created_at);
CREATE INDEX db_prefix_posts_discussion_id_number_index ON db_prefix_posts (discussion_id, number);
CREATE UNIQUE INDEX db_prefix_posts_discussion_id_number_unique ON db_prefix_posts (discussion_id, number);
CREATE INDEX "db_prefix_posts_type_index" on "db_prefix_posts" ("type");
CREATE INDEX "db_prefix_posts_type_created_at_index" on "db_prefix_posts" ("type", "created_at");
CREATE TABLE IF NOT EXISTS "db_prefix_unsubscribe_tokens" ("id" integer primary key autoincrement not null, "user_id" integer not null, "email_type" varchar not null, "token" varchar not null, "unsubscribed_at" datetime, "created_at" datetime, "updated_at" datetime, foreign key("user_id") references "db_prefix_users"("id") on delete cascade);
CREATE INDEX "db_prefix_unsubscribe_tokens_user_id_index" on "db_prefix_unsubscribe_tokens" ("user_id");
CREATE INDEX "db_prefix_unsubscribe_tokens_email_type_index" on "db_prefix_unsubscribe_tokens" ("email_type");
CREATE INDEX "db_prefix_unsubscribe_tokens_token_index" on "db_prefix_unsubscribe_tokens" ("token");
CREATE INDEX "db_prefix_unsubscribe_tokens_user_id_email_type_index" on "db_prefix_unsubscribe_tokens" ("user_id", "email_type");
CREATE UNIQUE INDEX "db_prefix_unsubscribe_tokens_token_unique" on "db_prefix_unsubscribe_tokens" ("token");
CREATE TABLE db_prefix_discussions (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title VARCHAR(255) NOT NULL COLLATE "BINARY", comment_count INTEGER DEFAULT 1 NOT NULL, participant_count INTEGER DEFAULT 0 NOT NULL, created_at DATETIME NOT NULL, user_id INTEGER DEFAULT NULL, first_post_id INTEGER DEFAULT NULL, last_posted_at DATETIME DEFAULT NULL, last_posted_user_id INTEGER DEFAULT NULL, last_post_id INTEGER DEFAULT NULL, last_post_number INTEGER DEFAULT NULL, hidden_at DATETIME DEFAULT NULL, hidden_user_id INTEGER DEFAULT NULL, slug VARCHAR(255) NOT NULL COLLATE "BINARY", is_private BOOLEAN DEFAULT 0 NOT NULL, foreign key("user_id") references "db_prefix_users"("id") on delete set null,
foreign key("last_posted_user_id") references "db_prefix_users"("id") on delete set null,
foreign key("hidden_user_id") references "db_prefix_users"("id") on delete set null,
foreign key("first_post_id") references "db_prefix_posts"("id") on delete set null,
foreign key("last_post_id") references "db_prefix_posts"("id") on delete set null);
CREATE INDEX db_prefix_discussions_last_posted_at_index ON db_prefix_discussions (last_posted_at);
CREATE INDEX db_prefix_discussions_last_posted_user_id_index ON db_prefix_discussions (last_posted_user_id);
CREATE INDEX db_prefix_discussions_created_at_index ON db_prefix_discussions (created_at);
CREATE INDEX db_prefix_discussions_user_id_index ON db_prefix_discussions (user_id);
CREATE INDEX db_prefix_discussions_comment_count_index ON db_prefix_discussions (comment_count);
CREATE INDEX db_prefix_discussions_participant_count_index ON db_prefix_discussions (participant_count);
CREATE INDEX db_prefix_discussions_hidden_at_index ON db_prefix_discussions (hidden_at);
INSERT INTO db_prefix_migrations VALUES(1,'2015_02_24_000000_create_access_tokens_table',NULL);
INSERT INTO db_prefix_migrations VALUES(2,'2015_02_24_000000_create_api_keys_table',NULL);
INSERT INTO db_prefix_migrations VALUES(3,'2015_02_24_000000_create_config_table',NULL);
INSERT INTO db_prefix_migrations VALUES(4,'2015_02_24_000000_create_discussions_table',NULL);
INSERT INTO db_prefix_migrations VALUES(5,'2015_02_24_000000_create_email_tokens_table',NULL);
INSERT INTO db_prefix_migrations VALUES(6,'2015_02_24_000000_create_groups_table',NULL);
INSERT INTO db_prefix_migrations VALUES(7,'2015_02_24_000000_create_notifications_table',NULL);
INSERT INTO db_prefix_migrations VALUES(8,'2015_02_24_000000_create_password_tokens_table',NULL);
INSERT INTO db_prefix_migrations VALUES(9,'2015_02_24_000000_create_permissions_table',NULL);
INSERT INTO db_prefix_migrations VALUES(10,'2015_02_24_000000_create_posts_table',NULL);
INSERT INTO db_prefix_migrations VALUES(11,'2015_02_24_000000_create_users_discussions_table',NULL);
INSERT INTO db_prefix_migrations VALUES(12,'2015_02_24_000000_create_users_groups_table',NULL);
INSERT INTO db_prefix_migrations VALUES(13,'2015_02_24_000000_create_users_table',NULL);
INSERT INTO db_prefix_migrations VALUES(14,'2015_09_15_000000_create_auth_tokens_table',NULL);
INSERT INTO db_prefix_migrations VALUES(15,'2015_09_20_224327_add_hide_to_discussions',NULL);
INSERT INTO db_prefix_migrations VALUES(16,'2015_09_22_030432_rename_notification_read_time',NULL);
INSERT INTO db_prefix_migrations VALUES(17,'2015_10_07_130531_rename_config_to_settings',NULL);
INSERT INTO db_prefix_migrations VALUES(18,'2015_10_24_194000_add_ip_address_to_posts',NULL);
INSERT INTO db_prefix_migrations VALUES(19,'2015_12_05_042721_change_access_tokens_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(20,'2015_12_17_194247_change_settings_value_column_to_text',NULL);
INSERT INTO db_prefix_migrations VALUES(21,'2016_02_04_095452_add_slug_to_discussions',NULL);
INSERT INTO db_prefix_migrations VALUES(22,'2017_04_07_114138_add_is_private_to_discussions',NULL);
INSERT INTO db_prefix_migrations VALUES(23,'2017_04_07_114138_add_is_private_to_posts',NULL);
INSERT INTO db_prefix_migrations VALUES(24,'2018_01_11_093900_change_access_tokens_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(25,'2018_01_11_094000_change_access_tokens_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(26,'2018_01_11_095000_change_api_keys_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(27,'2018_01_11_101800_rename_auth_tokens_to_registration_tokens',NULL);
INSERT INTO db_prefix_migrations VALUES(28,'2018_01_11_102000_change_registration_tokens_rename_id_to_token',NULL);
INSERT INTO db_prefix_migrations VALUES(29,'2018_01_11_102100_change_registration_tokens_created_at_to_datetime',NULL);
INSERT INTO db_prefix_migrations VALUES(30,'2018_01_11_120604_change_posts_table_to_innodb',NULL);
INSERT INTO db_prefix_migrations VALUES(31,'2018_01_11_155200_change_discussions_rename_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(32,'2018_01_11_155300_change_discussions_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(33,'2018_01_15_071700_rename_users_discussions_to_discussion_user',NULL);
INSERT INTO db_prefix_migrations VALUES(34,'2018_01_15_071800_change_discussion_user_rename_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(35,'2018_01_15_071900_change_discussion_user_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(36,'2018_01_15_072600_change_email_tokens_rename_id_to_token',NULL);
INSERT INTO db_prefix_migrations VALUES(37,'2018_01_15_072700_change_email_tokens_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(38,'2018_01_15_072800_change_email_tokens_created_at_to_datetime',NULL);
INSERT INTO db_prefix_migrations VALUES(39,'2018_01_18_130400_rename_permissions_to_group_permission',NULL);
INSERT INTO db_prefix_migrations VALUES(40,'2018_01_18_130500_change_group_permission_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(41,'2018_01_18_130600_rename_users_groups_to_group_user',NULL);
INSERT INTO db_prefix_migrations VALUES(42,'2018_01_18_130700_change_group_user_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(43,'2018_01_18_133000_change_notifications_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(44,'2018_01_18_133100_change_notifications_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(45,'2018_01_18_134400_change_password_tokens_rename_id_to_token',NULL);
INSERT INTO db_prefix_migrations VALUES(46,'2018_01_18_134500_change_password_tokens_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(47,'2018_01_18_134600_change_password_tokens_created_at_to_datetime',NULL);
INSERT INTO db_prefix_migrations VALUES(48,'2018_01_18_135000_change_posts_rename_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(49,'2018_01_18_135100_change_posts_add_foreign_keys',NULL);
INSERT INTO db_prefix_migrations VALUES(50,'2018_01_30_112238_add_fulltext_index_to_discussions_title',NULL);
INSERT INTO db_prefix_migrations VALUES(51,'2018_01_30_220100_create_post_user_table',NULL);
INSERT INTO db_prefix_migrations VALUES(52,'2018_01_30_222900_change_users_rename_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(55,'2018_09_15_041340_add_users_indicies',NULL);
INSERT INTO db_prefix_migrations VALUES(56,'2018_09_15_041828_add_discussions_indicies',NULL);
INSERT INTO db_prefix_migrations VALUES(57,'2018_09_15_043337_add_notifications_indices',NULL);
INSERT INTO db_prefix_migrations VALUES(58,'2018_09_15_043621_add_posts_indices',NULL);
INSERT INTO db_prefix_migrations VALUES(59,'2018_09_22_004100_change_registration_tokens_columns',NULL);
INSERT INTO db_prefix_migrations VALUES(60,'2018_09_22_004200_create_login_providers_table',NULL);
INSERT INTO db_prefix_migrations VALUES(61,'2018_10_08_144700_add_shim_prefix_to_group_icons',NULL);
INSERT INTO db_prefix_migrations VALUES(62,'2019_10_12_195349_change_posts_add_discussion_foreign_key',NULL);
INSERT INTO db_prefix_migrations VALUES(63,'2020_03_19_134512_change_discussions_default_comment_count',NULL);
INSERT INTO db_prefix_migrations VALUES(64,'2020_04_21_130500_change_permission_groups_add_is_hidden',NULL);
INSERT INTO db_prefix_migrations VALUES(65,'2021_03_02_040000_change_access_tokens_add_type',NULL);
INSERT INTO db_prefix_migrations VALUES(66,'2021_03_02_040500_change_access_tokens_add_id',NULL);
INSERT INTO db_prefix_migrations VALUES(67,'2021_03_02_041000_change_access_tokens_add_title_ip_agent',NULL);
INSERT INTO db_prefix_migrations VALUES(68,'2021_04_18_040500_change_migrations_add_id_primary_key',NULL);
INSERT INTO db_prefix_migrations VALUES(69,'2021_04_18_145100_change_posts_content_column_to_mediumtext',NULL);
INSERT INTO db_prefix_migrations VALUES(70,'2021_05_10_000000_rename_permissions',NULL);
INSERT INTO db_prefix_migrations VALUES(71,'2022_05_20_000000_add_timestamps_to_groups_table',NULL);
INSERT INTO db_prefix_migrations VALUES(72,'2022_05_20_000001_add_created_at_to_group_user_table',NULL);
INSERT INTO db_prefix_migrations VALUES(73,'2022_05_20_000002_add_created_at_to_group_permission_table',NULL);
INSERT INTO db_prefix_migrations VALUES(74,'2022_07_14_000000_add_type_index_to_posts',NULL);
INSERT INTO db_prefix_migrations VALUES(75,'2022_07_14_000001_add_type_created_at_composite_index_to_posts',NULL);
INSERT INTO db_prefix_migrations VALUES(76,'2022_08_06_000000_change_access_tokens_last_activity_at_to_nullable',NULL);
INSERT INTO db_prefix_migrations VALUES(77,'2023_08_19_000000_create_unsubscribe_tokens_table',NULL);
INSERT INTO db_prefix_migrations VALUES(78,'2023_10_23_000000_drop_post_number_index_column_from_discussions_table',NULL);
INSERT INTO db_prefix_migrations VALUES(79,'2024_05_05_000000_add_sqlite_keys',NULL);