Skip to content

Commit

Permalink
feat: add support for PgSQL (#3985)
Browse files Browse the repository at this point in the history
* feat: add support for `PgSQL`
* chore: generate dump
* feat: query exception errors db driver hint
* feat: allow defining supported databases
* chore: review comments
* feat: setting for pgsql preferred search config
  • Loading branch information
SychO9 authored Jun 22, 2024
1 parent d04cda6 commit 379298a
Show file tree
Hide file tree
Showing 76 changed files with 2,099 additions and 263 deletions.
55 changes: 38 additions & 17 deletions .github/workflows/REUSABLE_backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ on:
description: Versions of databases to test with. Should be array of strings encoded as JSON array
type: string
required: false
default: '["mysql:5.7", "mysql:8.0.30", "mysql:8.1.0", "mariadb", "sqlite:3"]'
default: '["mysql:5.7", "mysql:8.0.30", "mysql:8.1.0", "mariadb", "sqlite:3", "postgres:10"]'

php_ini_values:
description: PHP ini values
Expand All @@ -68,6 +68,9 @@ env:
# `inputs.composer_directory` defaults to `inputs.backend_directory`
FLARUM_TEST_TMP_DIR_LOCAL: tests/integration/tmp
COMPOSER_AUTH: ${{ secrets.composer_auth }}
DB_DATABASE: flarum_test
DB_USERNAME: root
DB_PASSWORD: root

jobs:
test:
Expand Down Expand Up @@ -98,6 +101,9 @@ jobs:
- service: 'sqlite:3'
db: SQLite
driver: sqlite
- service: 'postgres:10'
db: PostgreSQL 10
driver: pgsql

# Include Database prefix tests with only one PHP version.
- php: ${{ fromJSON(inputs.php_versions)[0] }}
Expand All @@ -106,30 +112,24 @@ jobs:
driver: mysql
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:8.0.30'
db: MySQL 8.0
driver: mysql
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: mariadb
db: MariaDB
driver: mysql
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:8.1.0'
db: MySQL 8.1
driver: mysql
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'sqlite:3'
db: SQLite
driver: sqlite
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'postgres:10'
db: PostgreSQL 10
driver: pgsql
prefix: flarum_
prefixStr: (prefix)

# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
exclude:
Expand All @@ -147,12 +147,34 @@ jobs:
service: 'sqlite:3'
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'sqlite:3'
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'postgres:10'
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'postgres:10'

services:
mysql:
image: ${{ matrix.service != 'sqlite:3' && matrix.service || '' }}
image: ${{ matrix.driver == 'mysql' && matrix.service || '' }}
env:
MYSQL_DATABASE: ${{ env.DB_DATABASE }}
MYSQL_USER: ${{ env.DB_USERNAME }}
MYSQL_PASSWORD: ${{ env.DB_PASSWORD }}
MYSQL_ROOT_PASSWORD: ${{ env.DB_PASSWORD }}
ports:
- 13306:3306
postgres:
image: ${{ matrix.driver == 'pgsql' && matrix.service || '' }}
env:
POSTGRES_DB: ${{ env.DB_DATABASE }}
POSTGRES_USER: ${{ env.DB_USERNAME }}
POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }}
ports:
- 15432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'

Expand All @@ -173,7 +195,7 @@ jobs:
ini-values: ${{ matrix.php_ini_values }}

- name: Create MySQL Database
if: ${{ matrix.service != 'sqlite:3' }}
if: ${{ matrix.driver == 'mysql' }}
run: |
sudo systemctl start mysql
mysql -uroot -proot -e 'CREATE DATABASE flarum_test;' --port 13306
Expand All @@ -200,8 +222,7 @@ jobs:
fi
working-directory: ${{ inputs.backend_directory }}
env:
DB_PORT: 13306
DB_PASSWORD: root
DB_PORT: ${{ matrix.driver == 'mysql' && 13306 || 15432 }}
DB_PREFIX: ${{ matrix.prefix }}
DB_DRIVER: ${{ matrix.driver }}
COMPOSER_PROCESS_TIMEOUT: 600
Expand Down
20 changes: 12 additions & 8 deletions extensions/approval/tests/integration/api/ApprovePostsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@

use Carbon\Carbon;
use Flarum\Approval\Tests\integration\InteractsWithUnapprovedContent;
use Flarum\Discussion\Discussion;
use Flarum\Group\Group;
use Flarum\Post\Post;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;

class ApprovePostsTest extends TestCase
{
Expand All @@ -26,23 +30,23 @@ protected function setUp(): void
$this->extension('flarum-approval');

$this->prepareDatabase([
'users' => [
User::class => [
['id' => 1, 'username' => 'Muralf', 'email' => '[email protected]', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'acme', 'email' => '[email protected]', 'is_email_confirmed' => 1],
['id' => 4, 'username' => 'luceos', 'email' => '[email protected]', 'is_email_confirmed' => 1],
],
'discussions' => [
Discussion::class => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 1, 'comment_count' => 1, 'is_approved' => 1],
],
'posts' => [
['id' => 1, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => 0, 'is_approved' => 1, 'number' => 1],
['id' => 2, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => 0, 'is_approved' => 1, 'number' => 2],
['id' => 3, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => 0, 'is_approved' => 0, 'number' => 3],
Post::class => [
['id' => 1, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => null, 'is_approved' => 1, 'number' => 1],
['id' => 2, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => null, 'is_approved' => 1, 'number' => 2],
['id' => 3, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => null, 'is_approved' => 0, 'number' => 3],
['id' => 4, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => Carbon::now(), 'is_approved' => 1, 'number' => 4],
['id' => 5, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => 0, 'is_approved' => 0, 'number' => 5],
['id' => 5, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'hidden_at' => null, 'is_approved' => 0, 'number' => 5],
],
'groups' => [
Group::class => [
['id' => 4, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0],
['id' => 5, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0],
],
Expand Down
12 changes: 8 additions & 4 deletions extensions/approval/tests/integration/api/CreatePostsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@

use Carbon\Carbon;
use Flarum\Approval\Tests\integration\InteractsWithUnapprovedContent;
use Flarum\Discussion\Discussion;
use Flarum\Group\Group;
use Flarum\Post\Post;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;

class CreatePostsTest extends TestCase
{
Expand All @@ -27,18 +30,18 @@ protected function setUp(): void
$this->extension('flarum-flags', 'flarum-approval');

$this->prepareDatabase([
'users' => [
User::class => [
['id' => 1, 'username' => 'Muralf', 'email' => '[email protected]', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'acme', 'email' => '[email protected]', 'is_email_confirmed' => 1],
['id' => 4, 'username' => 'luceos', 'email' => '[email protected]', 'is_email_confirmed' => 1],
],
'discussions' => [
Discussion::class => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 1, 'comment_count' => 1, 'is_approved' => 1],
['id' => 2, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 2, 'comment_count' => 1, 'is_approved' => 0],
['id' => 3, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 3, 'comment_count' => 1, 'is_approved' => 0],
],
'posts' => [
Post::class => [
['id' => 1, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
['id' => 2, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 2],
['id' => 3, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 3],
Expand All @@ -49,7 +52,7 @@ protected function setUp(): void
['id' => 8, 'discussion_id' => 3, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 2],
['id' => 9, 'discussion_id' => 3, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 0, 'number' => 3],
],
'groups' => [
Group::class => [
['id' => 4, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0],
['id' => 5, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0],
],
Expand All @@ -60,6 +63,7 @@ protected function setUp(): void
'group_permission' => [
['group_id' => 4, 'permission' => 'discussion.startWithoutApproval'],
['group_id' => 5, 'permission' => 'discussion.replyWithoutApproval'],
['group_id' => Group::MEMBER_ID, 'permission' => 'postWithoutThrottle'],
]
]);
}
Expand Down
5 changes: 4 additions & 1 deletion extensions/flags/src/Api/Resource/FlagResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ public function model(): string
public function query(Context $context): object
{
if ($context->listing(self::class)) {
$query = Flag::query()->groupBy('post_id');
$query = Flag::query()->whenPgSql(
fn (Builder $query) => $query->distinct('post_id')->orderBy('post_id'),
else: fn (Builder $query) => $query->groupBy('post_id')
);

$this->scope($query, $context);

Expand Down
27 changes: 18 additions & 9 deletions extensions/flags/tests/integration/api/flags/ListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@

namespace Flarum\Flags\Tests\integration\api\flags;

use Carbon\Carbon;
use Flarum\Discussion\Discussion;
use Flarum\Flags\Flag;
use Flarum\Group\Group;
use Flarum\Post\Post;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;
use Illuminate\Database\PostgresConnection;
use Illuminate\Support\Arr;

class ListTest extends TestCase
Expand Down Expand Up @@ -58,12 +60,12 @@ protected function setUp(): void
['id' => 4, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p></p></t>', 'is_private' => true],
],
Flag::class => [
['id' => 1, 'post_id' => 1, 'user_id' => 1],
['id' => 2, 'post_id' => 1, 'user_id' => 2],
['id' => 3, 'post_id' => 1, 'user_id' => 3],
['id' => 4, 'post_id' => 2, 'user_id' => 2],
['id' => 5, 'post_id' => 3, 'user_id' => 1],
['id' => 6, 'post_id' => 4, 'user_id' => 1],
['id' => 1, 'post_id' => 1, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(2)],
['id' => 2, 'post_id' => 1, 'user_id' => 2, 'created_at' => Carbon::now()->addMinutes(3)],
['id' => 3, 'post_id' => 1, 'user_id' => 3, 'created_at' => Carbon::now()->addMinutes(4)],
['id' => 4, 'post_id' => 2, 'user_id' => 2, 'created_at' => Carbon::now()->addMinutes(5)],
['id' => 5, 'post_id' => 3, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(6)],
['id' => 6, 'post_id' => 4, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(7)],
]
]);
}
Expand All @@ -79,12 +81,19 @@ public function admin_can_see_one_flag_per_visible_post()
])
);

$this->assertEquals(200, $response->getStatusCode(), $body = $response->getBody()->getContents());
$body = $response->getBody()->getContents();

$this->assertEquals(200, $response->getStatusCode(), $body);

$data = json_decode($body, true)['data'];

$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['1', '4', '5'], $ids);

if ($this->database() instanceof PostgresConnection) {
$this->assertEqualsCanonicalizing(['3', '4', '5'], $ids);
} else {
$this->assertEqualsCanonicalizing(['1', '4', '5'], $ids);
}
}

/**
Expand Down Expand Up @@ -122,7 +131,7 @@ public function mod_can_see_one_flag_per_visible_post()
$data = json_decode($response->getBody()->getContents(), true)['data'];

$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['1', '4', '5'], $ids);
$this->assertCount(3, $data);
}

/**
Expand Down
31 changes: 18 additions & 13 deletions extensions/flags/tests/integration/api/flags/ListWithTagsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;

class ListWithTagsTest extends TestCase
{
Expand Down Expand Up @@ -86,16 +87,16 @@ protected function setUp(): void
],
Flag::class => [
// From regular ListTest
['id' => 1, 'post_id' => 1, 'user_id' => 1],
['id' => 2, 'post_id' => 1, 'user_id' => 2],
['id' => 3, 'post_id' => 1, 'user_id' => 3],
['id' => 4, 'post_id' => 2, 'user_id' => 2],
['id' => 5, 'post_id' => 3, 'user_id' => 1],
['id' => 1, 'post_id' => 1, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(2)],
['id' => 2, 'post_id' => 1, 'user_id' => 2, 'created_at' => Carbon::now()->addMinutes(3)],
['id' => 3, 'post_id' => 1, 'user_id' => 3, 'created_at' => Carbon::now()->addMinutes(4)],
['id' => 4, 'post_id' => 2, 'user_id' => 2, 'created_at' => Carbon::now()->addMinutes(5)],
['id' => 5, 'post_id' => 3, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(6)],
// In tags
['id' => 6, 'post_id' => 4, 'user_id' => 1],
['id' => 7, 'post_id' => 5, 'user_id' => 1],
['id' => 8, 'post_id' => 6, 'user_id' => 1],
['id' => 9, 'post_id' => 7, 'user_id' => 1],
['id' => 6, 'post_id' => 4, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(7)],
['id' => 7, 'post_id' => 5, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(8)],
['id' => 8, 'post_id' => 6, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(9)],
['id' => 9, 'post_id' => 7, 'user_id' => 1, 'created_at' => Carbon::now()->addMinutes(10)],
]
]);
}
Expand All @@ -111,12 +112,14 @@ public function admin_can_see_one_flag_per_post()
])
);

$this->assertEquals(200, $response->getStatusCode());
$body = $response->getBody()->getContents();

$data = json_decode($response->getBody()->getContents(), true)['data'];
$this->assertEquals(200, $response->getStatusCode(), $body);

$data = json_decode($body, true)['data'];

$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['1', '4', '5', '6', '7', '8', '9'], $ids);
$this->assertCount(7, $data);
}

/**
Expand Down Expand Up @@ -154,7 +157,9 @@ public function mod_can_see_one_flag_per_post()
$data = json_decode($response->getBody()->getContents(), true)['data'];

$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['1', '4', '5', '8', '9'], $ids);
// 7 is included, even though mods can't view discussions.
// This is because the UI doesnt allow discussions.viewFlags without viewDiscussions.
$this->assertCount(5, $data);
}

/**
Expand Down
Loading

0 comments on commit 379298a

Please sign in to comment.