-
Notifications
You must be signed in to change notification settings - Fork 43
docs: Document PostgreSQL database support for Mautic 7.x #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 7.1
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -363,4 +363,145 @@ | |
| :param array $columns: Array of columns to included in the index. | ||
|
|
||
| :return: ``INDEX {tableName} ($columns...)`` statement | ||
| :returntype: string | ||
| :returntype: string | ||
|
|
||
| Database compatibility | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Database compatibility section based on PR #15926. Key implementation files: Source: mautic/mautic#15926 |
||
| ********************** | ||
|
|
||
| Mautic 7.x supports MySQL, MariaDB, and PostgreSQL. Follow these patterns to ensure your queries work across all platforms. | ||
|
|
||
| Supported databases | ||
| =================== | ||
|
|
||
| .. list-table:: | ||
| :widths: 30 30 40 | ||
| :header-rows: 1 | ||
|
|
||
| * - Database | ||
| - Minimum version | ||
| - PHP extension | ||
| * - MySQL | ||
| - 8.0 | ||
| - ``pdo_mysql`` | ||
| * - MariaDB | ||
| - 10.6 | ||
| - ``pdo_mysql`` | ||
| * - PostgreSQL | ||
| - 16 | ||
| - ``pdo_pgsql`` | ||
|
|
||
| .. vale off | ||
|
|
||
| Case-insensitive string matching | ||
| ================================ | ||
|
|
||
| .. vale on | ||
|
|
||
| MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreSQL's ``LIKE`` is case-sensitive. Mautic provides helper methods in ``CommonRepository`` to handle this. | ||
|
|
||
| **Using the helper methods:** | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| // In a repository extending CommonRepository | ||
| $qb = $this->getEntityManager()->getConnection()->createQueryBuilder(); | ||
|
|
||
| // Case-insensitive LIKE - uses ILIKE on PostgreSQL, LIKE on MySQL/MariaDB | ||
| $qb->andWhere( | ||
| $this->getILikeExpression($qb, 'l.email', ':search') | ||
| ); | ||
|
|
||
| // Or wrap the column with LOWER() for case-insensitive comparison | ||
| $qb->andWhere( | ||
| $this->getLowerLikeExpression($qb, 'l.firstname', ':search') | ||
| ); | ||
|
|
||
| **Available methods in CommonRepository:** | ||
|
|
||
| - ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Returns platform-appropriate case-insensitive ``LIKE`` expression | ||
|
Check warning on line 421 in docs/plugins/database.rst
|
||
| - ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Wraps the column with ``LOWER()`` for case-insensitive comparison | ||
|
Check warning on line 422 in docs/plugins/database.rst
|
||
| - ``isPostgreSql()``: Returns ``TRUE`` if connected to a PostgreSQL database | ||
|
|
||
| .. vale off | ||
|
|
||
| Column and alias quoting | ||
| ======================== | ||
|
|
||
| .. vale on | ||
|
|
||
| PostgreSQL lowercases unquoted identifiers automatically. This causes issues with Mautic's ``camelCase`` column aliases. Always quote identifiers in raw SQL queries that use mixed-case names. | ||
|
|
||
| **Use quoted identifiers for camelCase aliases:** | ||
|
Check failure on line 434 in docs/plugins/database.rst
|
||
|
|
||
| .. code-block:: php | ||
|
|
||
| // Correct - aliases are quoted | ||
| $qb->select('l.id, l.first_name AS "firstName", l.date_added AS "dateAdded"'); | ||
|
|
||
| // Incorrect - PostgreSQL converts to lowercase | ||
| $qb->select('l.id, l.first_name AS firstName'); | ||
|
|
||
| Doctrine's QueryBuilder handles quoting automatically when you use proper field mappings. You only need manual quoting for raw SQL or custom column aliases. | ||
|
|
||
| .. vale off | ||
|
|
||
| GROUP BY requirements | ||
| ===================== | ||
|
|
||
| .. vale on | ||
|
|
||
| PostgreSQL enforces strict ``GROUP BY`` rules, and MySQL 8+ does the same when ``ONLY_FULL_GROUP_BY`` SQL mode is enabled - the default in strict mode. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. | ||
|
|
||
| Writing compliant ``GROUP BY`` clauses ensures compatibility across all supported databases and SQL modes. | ||
|
|
||
| Mautic's Report Builder corrects ``GROUP BY`` clauses automatically. If you're building custom Reports or queries with aggregates, include all non-aggregated columns in the ``GROUP BY`` clause. | ||
|
|
||
| **Correct pattern:** | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| $qb->select('l.id, l.email, COUNT(e.id) as emailCount') | ||
| ->from('leads', 'l') | ||
| ->leftJoin('l', 'emails', 'e', 'e.lead_id = l.id') | ||
| ->groupBy('l.id, l.email'); // All non-aggregate columns included | ||
|
|
||
| **Incorrect pattern:** | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| // This fails on PostgreSQL - l.email not in GROUP BY | ||
| $qb->select('l.id, l.email, COUNT(e.id) as emailCount') | ||
| ->from('leads', 'l') | ||
| ->leftJoin('l', 'emails', 'e', 'e.lead_id = l.id') | ||
| ->groupBy('l.id'); | ||
|
|
||
| Detecting the database platform | ||
| =============================== | ||
|
|
||
| When you need platform-specific query logic, detect the database type using the connection's platform: | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| use Doctrine\DBAL\Platforms\PostgreSQLPlatform; | ||
|
|
||
| $connection = $this->getEntityManager()->getConnection(); | ||
| $platform = $connection->getDatabasePlatform(); | ||
|
|
||
| if ($platform instanceof PostgreSQLPlatform) { | ||
| // PostgreSQL-specific logic | ||
| } else { | ||
| // MySQL/MariaDB logic | ||
| } | ||
|
|
||
| Repositories extending ``CommonRepository`` can use the ``isPostgreSql()`` helper method. | ||
|
|
||
| Best practices | ||
| ============== | ||
|
|
||
| 1. **Use Doctrine's ORM and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. | ||
|
|
||
| 2. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. | ||
|
|
||
| 3. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. | ||
|
|
||
| 4. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -233,6 +233,64 @@ | |
|
|
||
| ``Password: secret`` | ||
|
|
||
| Testing on multiple databases | ||
| ***************************** | ||
|
|
||
| Mautic supports MySQL, MariaDB, and PostgreSQL. The CI pipeline runs tests against all supported databases. Make sure your code works across all databases when developing features or writing tests. | ||
|
|
||
| Supported database versions | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Multi-database testing section based on PR #15926. CI tests run on PostgreSQL 16/18, MariaDB 10.11/11.4, MySQL 8.4/9.4. Source: mautic/mautic#15926 |
||
| =========================== | ||
|
|
||
| .. list-table:: | ||
| :header-rows: 1 | ||
|
|
||
| * - Database | ||
| - Tested versions | ||
| * - PostgreSQL | ||
| - 16, 18 | ||
| * - MariaDB | ||
| - 10.11, 11.4 | ||
| * - MySQL | ||
| - 8.4, 9.4 | ||
|
|
||
| Configuring your test environment for PostgreSQL | ||
| ================================================ | ||
|
|
||
| To run tests locally against PostgreSQL: | ||
|
|
||
| 1. Update your ``.env.test.local`` with PostgreSQL credentials: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| # .env.test.local | ||
| DB_DRIVER=pdo_pgsql | ||
| DB_HOST=localhost | ||
| DB_PORT=5432 | ||
| DB_USER=postgres | ||
| DB_PASSWD=your_password | ||
| DB_NAME=mautic_test | ||
|
|
||
| 2. Ensure the ``pdo_pgsql`` PHP extension is installed and enabled. | ||
|
Check warning on line 273 in docs/testing/e2e_test_suite.rst
|
||
|
|
||
| 3. Run the test suite as normal: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| bin/phpunit | ||
|
|
||
| Database-specific test considerations | ||
| ===================================== | ||
|
|
||
| Keep these database differences in mind when writing tests: | ||
|
|
||
| - **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. | ||
|
Check warning on line 286 in docs/testing/e2e_test_suite.rst
|
||
|
|
||
| - **GROUP BY strictness**: PostgreSQL and MySQL 8+ strict mode require all non-aggregated ``SELECT`` columns in ``GROUP BY``. | ||
|
Check warning on line 288 in docs/testing/e2e_test_suite.rst
|
||
|
|
||
| - **Identifier quoting**: PostgreSQL lowercases unquoted identifiers. Quote ``camelCase`` aliases in raw SQL. | ||
|
Check warning on line 290 in docs/testing/e2e_test_suite.rst
|
||
|
|
||
| For detailed guidance on writing database-agnostic code, refer to the :doc:`/plugins/database` documentation. | ||
|
Check failure on line 292 in docs/testing/e2e_test_suite.rst
|
||
|
|
||
| Contributing | ||
| ************ | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PostgreSQL configuration example from PR #15926. Uses
pdo_pgsqldriver on port 5432, requires PostgreSQL 16+.Source: mautic/mautic#15926