-
Notifications
You must be signed in to change notification settings - Fork 48
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.2
Are you sure you want to change the base?
Changes from all commits
6a2dec2
3b09a5d
28cf334
f9784a8
23e5a1b
abb7fda
488ee72
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 |
|---|---|---|
|
|
@@ -107,6 +107,7 @@ noindex | |
| OAuth | ||
| OAuth1a | ||
| OAuth2 | ||
| ORM | ||
| Packagist | ||
| patch | ||
| PATCH | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -363,4 +363,159 @@ Define migrations in the Plugin's ``Migrations`` directory. The file and class n | |
| :param array $columns: Array of columns to included in the index. | ||
|
|
||
| :return: ``INDEX {tableName} ($columns...)`` statement | ||
| :returntype: string | ||
| :returntype: string | ||
|
|
||
| Database compatibility | ||
|
Contributor
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 centralizes all platform-specific helpers in ``Mautic\CoreBundle\Doctrine\DatabasePlatform``. | ||
|
|
||
| **Using the helper methods:** | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| use Mautic\CoreBundle\Doctrine\DatabasePlatform; | ||
|
|
||
| $connection = $this->getEntityManager()->getConnection(); | ||
| $platform = $connection->getDatabasePlatform(); | ||
| $qb = $connection->createQueryBuilder(); | ||
|
|
||
| // Case-insensitive LIKE - uses ILIKE on PostgreSQL, LIKE on MySQL/MariaDB | ||
| $qb->andWhere( | ||
| DatabasePlatform::getCaseInsensitiveLike($platform, 'l.email', ':search') | ||
| ); | ||
|
|
||
| // Apply LOWER() to the column for case-insensitive comparison | ||
| $qb->andWhere( | ||
| DatabasePlatform::getCaseInsensitiveLike( | ||
| $platform, | ||
| 'l.firstname', | ||
| ':search', | ||
| DatabasePlatform::FLAG_LOWER_COLUMN | ||
| ) | ||
| ); | ||
|
|
||
| .. vale off | ||
|
|
||
| **Available methods in DatabasePlatform:** | ||
|
|
||
| .. vale on | ||
|
|
||
| * ``getCaseInsensitiveLike($platform, $column, $valueOrParameter, $flags)``: returns platform-appropriate case-insensitive ``LIKE`` expression. Supports flags for ``LOWER()`` handling and negation. | ||
| * ``getRegexpExpression($platform, $column, $pattern, $negative)``: handles ``REGEXP`` differences between MySQL and PostgreSQL. | ||
| * ``isPostgreSQL($platform)``: returns ``TRUE`` if the platform is PostgreSQL. | ||
| * ``isMySQL($platform)``: returns ``TRUE`` if the platform is MySQL or MariaDB. | ||
|
|
||
| .. 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. | ||
|
|
||
| .. vale off | ||
|
|
||
| **Use quoted identifiers for camelCase aliases:** | ||
|
adiati98 marked this conversation as resolved.
|
||
|
|
||
| .. vale on | ||
|
|
||
| .. 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 active - 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, use the static helpers in ``DatabasePlatform``: | ||
|
|
||
| .. code-block:: php | ||
|
|
||
| use Mautic\CoreBundle\Doctrine\DatabasePlatform; | ||
|
|
||
| $connection = $this->getEntityManager()->getConnection(); | ||
| $platform = $connection->getDatabasePlatform(); | ||
|
|
||
| if (DatabasePlatform::isPostgreSQL($platform)) { | ||
| // PostgreSQL-specific logic | ||
| } else { | ||
| // MySQL/MariaDB logic | ||
| } | ||
|
|
||
| ``DatabasePlatform`` is the single source of truth for platform differences. Use its helpers instead of writing platform checks manually to avoid drift as the codebase evolves. | ||
|
|
||
| Best practices | ||
| ============== | ||
|
|
||
| #. **Use Doctrine's Object Relational Mapper - ORM - and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. | ||
| #. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. | ||
| #. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. | ||
| #. **Use DatabasePlatform helpers** - ``Mautic\CoreBundle\Doctrine\DatabasePlatform`` provides cross-platform helpers for case-insensitive searches, regular expressions, date handling, and platform detection. Consult its source for the full list of available methods. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -233,6 +233,70 @@ You can watch your tests run in an automated browser by visiting the following U | |
|
|
||
| ``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 | ||
|
Contributor
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: | ||
|
|
||
| #. 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 | ||
|
|
||
| #. Install and enable the ``pdo_pgsql`` PHP extension. | ||
|
|
||
| #. Run the test suite as normal: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| bin/phpunit | ||
|
|
||
| Database-specific test considerations | ||
| ===================================== | ||
|
|
||
| Keep these database differences in mind when writing tests: | ||
|
|
||
| .. vale off | ||
|
|
||
| * **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. | ||
| - **GROUP BY strictness**: PostgreSQL and MySQL 8+ strict mode require all non-aggregated ``SELECT`` columns in ``GROUP BY``. | ||
| - **Identifier quoting**: PostgreSQL lowercases unquoted identifiers. Quote ``camelCase`` aliases in raw SQL. | ||
|
|
||
| .. vale on | ||
|
|
||
| .. vale off | ||
|
|
||
| For detailed guidance on writing database-agnostic code, refer to the :doc:`/plugins/database` documentation. | ||
|
adiati98 marked this conversation as resolved.
|
||
|
|
||
| .. vale on | ||
|
|
||
| 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