diff --git a/.github/workflows/build-and-publish-ci-image.yml b/.github/workflows/build-and-publish-ci-image.yml index aadc5112..92cd61d0 100644 --- a/.github/workflows/build-and-publish-ci-image.yml +++ b/.github/workflows/build-and-publish-ci-image.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Log in to Docker Hub uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a diff --git a/.github/workflows/build-and-publish-franken-image.yml b/.github/workflows/build-and-publish-franken-image.yml index a9adeaa0..9e8c771b 100644 --- a/.github/workflows/build-and-publish-franken-image.yml +++ b/.github/workflows/build-and-publish-franken-image.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Log in to Docker Hub uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index f4525391..2524d517 100644 --- a/.github/workflows/coding-standards.yml +++ b/.github/workflows/coding-standards.yml @@ -31,7 +31,7 @@ jobs: steps: - name: "Checkout code" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" - name: "Install PHP" uses: "shivammathur/setup-php@v2" diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index ed31434c..e1a8dd96 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -56,7 +56,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" with: fetch-depth: 2 @@ -75,14 +75,6 @@ jobs: - name: "Run PHPUnit" env: - DBAL_DRIVER: "${{ matrix.extension }}" - DBAL_DBNAME: "test_db" - DBAL_HOST: "postgres" - DBAL_PASSWORD: "postgres" - DBAL_PORT: "5432" - DBAL_ROOT_PASSWORD: "postgres" - DBAL_ROOT_USER: "postgres" - DBAL_USER: "postgres" DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/test_db?serverVersion=${{ matrix.postgres-version }}&charset=utf8" run: "vendor/bin/phpunit" @@ -96,7 +88,7 @@ jobs: strategy: matrix: php-version: - - "8.4" + - "8.5" postgres-version: - "10" - "15" @@ -119,7 +111,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" with: fetch-depth: 2 @@ -138,14 +130,6 @@ jobs: - name: "Run PHPUnit" env: - DBAL_DRIVER: "${{ matrix.extension }}" - DBAL_DBNAME: "test_db" - DBAL_HOST: "postgres" - DBAL_PASSWORD: "postgres" - DBAL_PORT: "5432" - DBAL_ROOT_PASSWORD: "postgres" - DBAL_ROOT_USER: "postgres" - DBAL_USER: "postgres" DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/test_db?serverVersion=${{ matrix.postgres-version }}&charset=utf8" run: "vendor/bin/phpunit" @@ -159,7 +143,7 @@ jobs: strategy: matrix: php-version: - - "8.4" + - "8.5" mariadb-version: - "10.11.6" # LTS (Feb 2028) - "11.4.5" # LTS (May 2029) @@ -167,7 +151,7 @@ jobs: extension: - "mysqli" include: - - php-version: "8.4" + - php-version: "8.5" mariadb-version: "11.4.5" extension: "pdo_mysql" @@ -186,7 +170,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" with: fetch-depth: 2 @@ -204,14 +188,6 @@ jobs: - name: "Run PHPUnit" env: - DBAL_DRIVER: "${{ matrix.extension }}" - DBAL_DBNAME: "test_db" - DBAL_HOST: "mariadb" - DBAL_PASSWORD: "password" - DBAL_PORT: "3306" - DBAL_ROOT_PASSWORD: "password" - DBAL_ROOT_USER: "root" - DBAL_USER: "root" DATABASE_URL: "mysql://root:password@mariadb:3306/test_db?serverVersion=mariadb-${{ matrix.mariadb-version }}" run: "vendor/bin/phpunit" @@ -225,12 +201,12 @@ jobs: strategy: matrix: php-version: - - "8.4" + - "8.5" mysql-version: - - "5.7" - "8.0" - "8.2" - "8.3" + - "8.4" extension: - "mysqli" - "pdo_mysql" @@ -249,7 +225,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" with: fetch-depth: 2 @@ -267,14 +243,6 @@ jobs: - name: "Run PHPUnit" env: - DBAL_DRIVER: "${{ matrix.extension }}" - DBAL_DBNAME: "test_db" - DBAL_HOST: "mysql" - DBAL_PASSWORD: "password" - DBAL_PORT: "3306" - DBAL_ROOT_PASSWORD: "password" - DBAL_ROOT_USER: "root" - DBAL_USER: "root" DATABASE_URL: "mysql://root:password@mysql:3306/test_db" run: "vendor/bin/phpunit" @@ -290,7 +258,7 @@ jobs: # strategy: # matrix: # php-version: - # - "8.4" + # - "8.5" # mssql-version: # - "2019" # - "2022" @@ -313,7 +281,7 @@ jobs: # steps: # - name: "Checkout" - # uses: "actions/checkout@v4" + # uses: "actions/checkout@v6" # with: # fetch-depth: 2 @@ -331,14 +299,7 @@ jobs: # - name: "Run PHPUnit" # env: - # DBAL_DRIVER: "${{ matrix.extension }}" - # DBAL_DBNAME: "test_db" - # DBAL_HOST: "mssql" - # DBAL_PASSWORD: "P@ssword123" - # DBAL_PORT: "1433" - # DBAL_ROOT_PASSWORD: "P@ssword123" - # DBAL_ROOT_USER: "sa" - # DBAL_USER: "sa" + # DATABASE_DRIVER: "${{ matrix.extension }}" # DATABASE_URL: "mssql://sa:P%40ssword123@mssql:1433/test_db?serverVersion=2019&driverOptions[TrustServerCertificate]=true" # run: "vendor/bin/phpunit" @@ -355,14 +316,14 @@ jobs: os: - "ubuntu-22.04" php-version: - - "8.4" + - "8.5" extension: - "pdo_sqlite" - "sqlite3" steps: - name: "Checkout" - uses: "actions/checkout@v4" + uses: "actions/checkout@v6" with: fetch-depth: 2 @@ -380,9 +341,5 @@ jobs: - name: "Run PHPUnit" env: - DBAL_DRIVER: "${{ matrix.extension }}" - DBAL_DBNAME: "test_db" - DBAL_HOST: "127.0.0.1" - DBAL_PATH: "test_db.sqlite" DATABASE_URL: "sqlite:///test_db.sqlite" run: "vendor/bin/phpunit" diff --git a/CHANGELOG.md b/CHANGELOG.md index 87385157..42b217bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ## Next * [feature] 🌟 String pattern anonymizer, build complex strings by fetching values from other anonymizers. +* [bc] Officially drop support for MySQL 5.7 - code is still there and working but automated unit testing has been disabled. +* [internal] Add automated testing for MariaDB 12. +* [internal] Rewrote `dev.sh` local unit testing script to be simpler, reorganized the local unit testing Docker stack. ## 2.0.3 diff --git a/composer.json b/composer.json index 43bd14a9..6f297ccc 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "prefer-stable": true, "require": { "php": ">=8.1", - "makinacorpus/query-builder": "^1.6.2", + "makinacorpus/query-builder": "^1.7.1", "psr/log": "^3.0", "symfony/config": "^6.0|^7.0", "symfony/console": "^6.0|^7.0", diff --git a/dev.sh b/dev.sh index 592b3887..645539f7 100755 --- a/dev.sh +++ b/dev.sh @@ -13,7 +13,7 @@ EXTRA_DOCKER_ENV="" while getopts ":xp:l" opt; do case "${opt}" in x) - EXTRA_DOCKER_ENV="${EXTRA_DOCKER_ENV} -e XDEBUG_TRIGGER=1" + EXTRA_DOCKER_ENV="${EXTRA_DOCKER_ENV} -e XDEBUG_MODE=debug -e XDEBUG_TRIGGER=1" ;; l) LOWEST=1 @@ -115,101 +115,68 @@ do_ps() { do_docker_compose ps } -do_test_mysql57() { - section_title "Running tests with MySQL 5.7" - do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_mysql \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=mysql57 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=3306 \ - -e DBAL_ROOT_PASSWORD=password \ - -e DBAL_ROOT_USER="root" \ - -e DBAL_USER=root \ - -e DATABASE_URL=mysql://root:password@mysql57:3306/test_db?serverVersion=5.7 \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" -} - do_test_mysql80() { section_title "Running tests with MySQL 8.0" + # --skip-ssl for MariaDB client, --ssl-mode=disabled for MySQL client do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=mysqli \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=mysql80 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=3306 \ - -e DBAL_ROOT_PASSWORD=password \ - -e DBAL_ROOT_USER=root \ - -e DBAL_USER=root \ - -e DATABASE_URL=mysql://root:password@mysql80:3306/test_db?serverVersion=8 \ + -e DBTOOLS_BACKUP_OPTIONS="--no-tablespaces --skip-ssl" \ + -e DBTOOLS_RESTORE_OPTIONS="--skip-ssl" \ + -e DATABASE_URL=mysql://root:password@mysql80:3306/test_db?serverVersion=8.0 \ "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } -do_test_mysql83() { - section_title "Running tests with MySQL 8.3" +do_test_mysql84() { + section_title "Running tests with MySQL 8.4" + # --skip-ssl for MariaDB client, --ssl-mode=disabled for MySQL client do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_mysql \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=mysql83 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=3306 \ - -e DBAL_ROOT_PASSWORD=password \ - -e DBAL_ROOT_USER=root \ - -e DBAL_USER=root \ - -e DATABASE_URL=mysql://root:password@mysql83:3306/test_db?serverVersion=8 \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + -e DBTOOLS_BACKUP_OPTIONS="--no-tablespaces --skip-ssl" \ + -e DBTOOLS_RESTORE_OPTIONS="--skip-ssl" \ + -e DATABASE_URL=mysql://root:password@mysql84:3306/test_db?serverVersion=8.4 \ + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" +} + +do_test_mysql() { + do_test_mysql80 "$@" + do_test_mysql84 "$@" } do_test_mariadb11() { section_title "Running tests with MariaDB 11" + # --skip-ssl for MariaDB client, --ssl-mode=disabled for MySQL client do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_mysql \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=mariadb11 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=3306 \ - -e DBAL_ROOT_PASSWORD="password" \ - -e DBAL_ROOT_USER="root" \ - -e DBAL_USER=root \ + -e DBTOOLS_BACKUP_OPTIONS="--no-tablespaces --skip-ssl" \ + -e DBTOOLS_RESTORE_OPTIONS="--skip-ssl" \ -e DATABASE_URL=mysql://root:password@mariadb11:3306/test_db?serverVersion=mariadb-11.1.3 \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } -do_test_mysql() { - do_test_mysql57 "$@" - do_test_mysql80 "$@" - do_test_mysql83 "$@" +do_test_mariadb12() { + section_title "Running tests with MariaDB 12" + # --skip-ssl for MariaDB client, --ssl-mode=disabled for MySQL client + do_docker_compose exec $EXTRA_DOCKER_ENV \ + -e DBTOOLS_BACKUP_OPTIONS="--no-tablespaces --skip-ssl" \ + -e DBTOOLS_RESTORE_OPTIONS="--skip-ssl" \ + -e DATABASE_URL=mysql://root:password@mariadb12:3306/test_db?serverVersion=mariadb-12.1.2 \ + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" +} + +do_test_mariadb() { do_test_mariadb11 "$@" + do_test_mariadb12 "$@" } do_test_postgresql10() { section_title "Running tests with PostgreSQL 10" do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_pgsql \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=postgresql10 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=5432 \ - -e DBAL_ROOT_PASSWORD=password \ - -e DBAL_ROOT_USER=postgres \ - -e DBAL_USER=postgres \ -e DATABASE_URL="postgresql://postgres:password@postgresql10:5432/test_db?serverVersion=10&charset=utf8" \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } do_test_postgresql16() { section_title "Running tests with PostgreSQL 16" do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_pgsql \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=postgresql16 \ - -e DBAL_PASSWORD=password \ - -e DBAL_PORT=5432 \ - -e DBAL_ROOT_PASSWORD=password \ - -e DBAL_ROOT_USER=postgres \ - -e DBAL_USER=postgres \ -e DATABASE_URL="postgresql://postgres:password@postgresql16:5432/test_db?serverVersion=16&charset=utf8" \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } do_test_postgresql() { @@ -220,31 +187,15 @@ do_test_postgresql() { do_test_sqlsrv2019() { section_title "Running tests with SQL Server 2019" do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_sqlsrv \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=sqlsrv2019 \ - -e DBAL_PASSWORD=P@ssword123 \ - -e DBAL_PORT=1433 \ - -e DBAL_ROOT_PASSWORD=P@ssword123 \ - -e DBAL_ROOT_USER=sa \ - -e DBAL_USER=sa \ - -e DATABASE_URL="pdo-sqlsrv://sa:P%40ssword123@sqlsrv2019:1433/test_db?serverVersion=2019&charset=utf8&driverOptions[TrustServerCertificate]=true" \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + -e DATABASE_URL="sqlsrv://sa:P%40ssword123@sqlsrv2019:1433/test_db?serverVersion=2019&charset=utf8&driverOptions[TrustServerCertificate]=true" \ + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } do_test_sqlsrv2022() { section_title "Running tests with SQL Server 2022" do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_sqlsrv \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=sqlsrv2022 \ - -e DBAL_PASSWORD=P@ssword123 \ - -e DBAL_PORT=1433 \ - -e DBAL_ROOT_PASSWORD=P@ssword123 \ - -e DBAL_ROOT_USER=sa \ - -e DBAL_USER=sa \ - -e DATABASE_URL="pdo-sqlsrv://sa:P%40ssword123@sqlsrv2022:1433/test_db?serverVersion=2022&charset=utf8&driverOptions[TrustServerCertificate]=true" \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + -e DATABASE_URL="sqlsrv://sa:P%40ssword123@sqlsrv2022:1433/test_db?serverVersion=2022&charset=utf8&driverOptions[TrustServerCertificate]=true" \ + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } do_test_sqlsrv() { @@ -257,24 +208,21 @@ do_test_sqlsrv() { do_test_sqlite() { section_title "Running tests with SQLite" do_docker_compose exec $EXTRA_DOCKER_ENV \ - -e DBAL_DRIVER=pdo_sqlite \ - -e DBAL_DBNAME=test_db \ - -e DBAL_HOST=127.0.0.1 \ - -e DBAL_PATH="test_db.sqlite" \ - -e DATABASE_URL="pdo-sqlite:///test_db.sqlite" \ - $PHPUNIT_CONTAINER vendor/bin/phpunit "$@" + -e DATABASE_URL="sqlite:///test_db.sqlite" \ + "$PHPUNIT_CONTAINER" vendor/bin/phpunit "$@" } # Run PHPunit tests for all database vendors do_test_all() { do_composer_update - do_test_mysql57 "$@" do_test_mysql80 "$@" - do_test_mysql83 "$@" + do_test_mysql84 "$@" do_test_mariadb11 "$@" + do_test_mariadb12 "$@" do_test_postgresql10 "$@" do_test_postgresql16 "$@" + do_test_postgresql18 "$@" do_test_sqlsrv2019 "$@" do_test_sqlsrv2022 "$@" do_test_sqlite "$@" @@ -286,15 +234,16 @@ do_test_notice() { printf "\n" printf "\nLaunch this action with one of these available options:" printf "\n" - printf "\n - ${GREEN}mysql${NC}: Launch test for MySQL 5.7, 8.0, 8.3 & MariaDB 11" - printf "\n - ${GREEN}mysql57${NC}: Launch test for MySQL 5.7" + printf "\n - ${GREEN}mysql${NC}: Launch test for all MySQL versions" printf "\n - ${GREEN}mysql80${NC}: Launch test for MySQL 8.0" - printf "\n - ${GREEN}mysql83${NC}: Launch test for MySQL 8.3" + printf "\n - ${GREEN}mysql84${NC}: Launch test for MySQL 8.4" + printf "\n - ${GREEN}mariadb${NC}: Launch test for all MariaDB versions" printf "\n - ${GREEN}mariadb11${NC}: Launch test for MariaDB 11" - printf "\n - ${GREEN}postgresql${NC}: Launch test for PostgreSQL 10 & 16" + printf "\n - ${GREEN}mariadb12${NC}: Launch test for MariaDB 12" + printf "\n - ${GREEN}postgresql${NC}: Launch test for all PostgreSQL versions" printf "\n - ${GREEN}postgresql10${NC}: Launch test for PostgreSQL 10" printf "\n - ${GREEN}postgresql16${NC}: Launch test for PostgreSQL 16" - printf "\n - ${GREEN}sqlsrv${NC}: Launch test for SQL Server 2019 & 2022" + printf "\n - ${GREEN}sqlsrv${NC}: Launch test for all SQL Server versions" printf "\n - ${GREEN}sqlsrv2019${NC}: Launch test for SQL Server 2019" printf "\n - ${GREEN}sqlsrv2022${NC}: Launch test for SQL Server 2022" printf "\n - ${GREEN}sqlite${NC}: Launch test for SQLite" @@ -309,7 +258,7 @@ do_test() { if [[ -n $@ ]];then shift;fi case $suit in - mysql57|mysql80|mysql83|mariadb11|mysql|postgresql10|postgresql16|postgresql|sqlsrv2019|sqlsrv2022|sqlsrv|sqlite) do_composer_update && do_test_$suit "$@";; + mysql80|mysql84|mysql|mariadb11|mariadb12|mariadb|postgresql10|postgresql16|postgresql|sqlsrv2019|sqlsrv2022|sqlsrv|sqlite) do_composer_update && do_test_$suit "$@";; *) do_test_notice;; esac } @@ -346,7 +295,7 @@ do_notice() { printf "\nAvailable options:" printf "\n ${GREEN}-l${NC}: run ${GREEN}composer update${NC} with ${GREEN}--prefer-lowest${NC} option" printf "\n ${GREEN}-x${NC}: trigger ${GREEN}xdebug${NC} when running test suites (ignored otherwise)" - printf "\n ${GREEN}-p 8.3${NC}: choose PHP version to run, ${GREEN}8.2${NC} or ${GREEN}8.4${NC}" + printf "\n ${GREEN}-p 8.3${NC}: choose PHP version to run from ${GREEN}8.1${NC} to ${GREEN}8.5${NC}" printf "\n" printf "\n\n" } diff --git a/docker-compose.yaml b/docker-compose.yaml index 23b0dc50..0d3ba8cd 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,123 +1,88 @@ services: phpunit-8-1: - build: ./docker/php-8.1 - networks: - - db-tools-test + env_file: ./docker/php-dev/docker.env + build: + dockerfile: ./docker/php-dev/Dockerfile + args: + - PHP_VERSION=8.1 volumes: - ./:/var/www - environment: - PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=dbtoolsbundle} - XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9000 log=/tmp/xdebug/xdebug.log output_dir=/tmp/xdebug start_with_request=trigger" - XDEBUG_MODE: "${XDEBUG_MODE:-debug}" extra_hosts: - "host.docker.internal:host-gateway" phpunit-8-2: - build: ./docker/php-8.2 - networks: - - db-tools-test + env_file: ./docker/php-dev/docker.env + build: + dockerfile: ./docker/php-dev/Dockerfile + args: + - PHP_VERSION=8.2 volumes: - ./:/var/www - environment: - PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=dbtoolsbundle} - XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9000 log=/tmp/xdebug/xdebug.log output_dir=/tmp/xdebug start_with_request=trigger" - XDEBUG_MODE: "${XDEBUG_MODE:-debug}" extra_hosts: - "host.docker.internal:host-gateway" phpunit-8-3: - build: ./docker/php-8.3 - networks: - - db-tools-test + env_file: ./docker/php-dev/docker.env + build: + dockerfile: ./docker/php-dev/Dockerfile + args: + - PHP_VERSION=8.3 volumes: - ./:/var/www - environment: - PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=dbtoolsbundle} - XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9000 log=/tmp/xdebug/xdebug.log output_dir=/tmp/xdebug start_with_request=trigger" - XDEBUG_MODE: "${XDEBUG_MODE:-debug}" extra_hosts: - "host.docker.internal:host-gateway" phpunit-8-4: - build: ./docker/php-8.4 - networks: - - db-tools-test + env_file: ./docker/php-dev/docker.env + build: + dockerfile: ./docker/php-dev/Dockerfile + args: + - PHP_VERSION=8.4 volumes: - ./:/var/www - environment: - PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=dbtoolsbundle} - XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9000 log=/tmp/xdebug/xdebug.log output_dir=/tmp/xdebug start_with_request=trigger" - XDEBUG_MODE: "${XDEBUG_MODE:-debug}" extra_hosts: - "host.docker.internal:host-gateway" phpunit-8-5: - build: ./docker/php-8.5 - networks: - - db-tools-test + env_file: ./docker/php-dev/docker.env + build: + dockerfile: ./docker/php-dev/Dockerfile + args: + - PHP_VERSION=8.5 volumes: - ./:/var/www - environment: - PHP_IDE_CONFIG: ${PHP_IDE_CONFIG:-serverName=dbtoolsbundle} - XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9000 log=/tmp/xdebug/xdebug.log output_dir=/tmp/xdebug start_with_request=trigger" - XDEBUG_MODE: "${XDEBUG_MODE:-debug}" extra_hosts: - "host.docker.internal:host-gateway" - mysql57: - image: mysql:5.7 - restart: 'no' - environment: - MYSQL_DATABASE: test_db - MYSQL_ROOT_USER: root - MYSQL_ROOT_PASSWORD: password - ports: - - 9501:3306 - networks: - - db-tools-test mysql80: image: mysql:8.0 restart: 'no' environment: MYSQL_DATABASE: test_db MYSQL_ROOT_PASSWORD: password - ports: - - 9502:3306 - networks: - - db-tools-test - mysql83: - image: mysql:8.3 + mysql84: + image: mysql:8.4 restart: 'no' environment: MYSQL_DATABASE: test_db MYSQL_ROOT_PASSWORD: password - ports: - - 9508:3306 - networks: - - db-tools-test mariadb11: image: mariadb:11.4.5 restart: 'no' environment: MYSQL_DATABASE: test_db MARIADB_ROOT_PASSWORD: password - ports: - - 9503:3306 - networks: - - db-tools-test + mariadb12: + image: mariadb:12.1 + restart: 'no' + environment: + MYSQL_DATABASE: test_db + MARIADB_ROOT_PASSWORD: password postgresql10: image: postgres:10 restart: 'no' environment: POSTGRES_PASSWORD: password - ports: - - 9504:5432 - networks: - - db-tools-test postgresql16: image: postgres:16 restart: 'no' environment: POSTGRES_PASSWORD: password - ports: - - 9505:5432 - networks: - - db-tools-test sqlsrv2019: image: mcr.microsoft.com/mssql/server:2019-latest restart: unless-stopped @@ -126,10 +91,6 @@ services: MSSQL_PID: Developer MSSQL_SA_PASSWORD: P@ssword123 SA_PASSWORD: P@ssword123 - ports: - - 9506:1433 - networks: - - db-tools-test sqlsrv2022: image: mcr.microsoft.com/mssql/server:2022-latest restart: unless-stopped @@ -138,10 +99,3 @@ services: MSSQL_PID: Developer MSSQL_SA_PASSWORD: P@ssword123 SA_PASSWORD: P@ssword123 - ports: - - 9507:1433 - networks: - - db-tools-test - -networks: - db-tools-test: diff --git a/docker/php-8.1/Dockerfile b/docker/php-8.1/Dockerfile deleted file mode 100644 index 182b3743..00000000 --- a/docker/php-8.1/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM php:8.1-fpm-bookworm - -# Basic requirements -RUN apt-get update -RUN apt-get install -yqq --no-install-recommends default-mysql-client acl iproute2 zip zlib1g-dev libzip-dev \ - libxml2-dev libpng-dev libghc-curl-dev libldb-dev libldap2-dev gnupg2 libpq-dev sqlite3 - -# Instaling postgresql-client-16 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg && \ - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ - apt-get update && apt-get install -y postgresql-16 - -# PHP required extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath -RUN docker-php-ext-enable pdo_pgsql pdo_mysql sodium - -# SQL Server support -ENV ACCEPT_EULA=Y -RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list -RUN apt-get update -RUN apt-get -y --no-install-recommends install msodbcsql18 unixodbc-dev -RUN pecl install sqlsrv -RUN pecl install pdo_sqlsrv -RUN docker-php-ext-enable sqlsrv pdo_sqlsrv - -# Install Xdebug -RUN pecl install xdebug-3.3.2 && docker-php-ext-enable xdebug - -# Cleanup. -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -COPY --from=composer /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www diff --git a/docker/php-8.2/Dockerfile b/docker/php-8.2/Dockerfile deleted file mode 100644 index fa38fe1e..00000000 --- a/docker/php-8.2/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM php:8.2-fpm-bookworm - -# Basic requirements -RUN apt-get update -RUN apt-get install -yqq --no-install-recommends default-mysql-client acl iproute2 zip zlib1g-dev libzip-dev \ - libxml2-dev libpng-dev libghc-curl-dev libldb-dev libldap2-dev gnupg2 libpq-dev sqlite3 - -# Instaling postgresql-client-16 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg && \ - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ - apt-get update && apt-get install -y postgresql-16 - -# PHP required extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath -RUN docker-php-ext-enable pdo_pgsql pdo_mysql sodium - -# SQL Server support -ENV ACCEPT_EULA=Y -RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list -RUN apt-get update -RUN apt-get -y --no-install-recommends install msodbcsql18 unixodbc-dev -RUN pecl install sqlsrv -RUN pecl install pdo_sqlsrv -RUN docker-php-ext-enable sqlsrv pdo_sqlsrv - -# Install Xdebug -RUN pecl install xdebug-3.3.2 && docker-php-ext-enable xdebug - -# Cleanup. -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -COPY --from=composer /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www diff --git a/docker/php-8.3/Dockerfile b/docker/php-8.3/Dockerfile deleted file mode 100644 index 2e55cf9c..00000000 --- a/docker/php-8.3/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM php:8.3-fpm-bookworm - -# Basic requirements -RUN apt-get update -RUN apt-get install -yqq --no-install-recommends default-mysql-client acl iproute2 zip zlib1g-dev libzip-dev \ - libxml2-dev libpng-dev libghc-curl-dev libldb-dev libldap2-dev gnupg2 libpq-dev sqlite3 - -# Instaling postgresql-client-16 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg && \ - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ - apt-get update && apt-get install -y postgresql-16 - -# PHP required extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath -RUN docker-php-ext-enable pdo_pgsql pdo_mysql sodium - -# SQL Server support -ENV ACCEPT_EULA=Y -RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list -RUN apt-get update -RUN apt-get -y --no-install-recommends install msodbcsql18 unixodbc-dev -RUN pecl install sqlsrv -RUN pecl install pdo_sqlsrv -RUN docker-php-ext-enable sqlsrv pdo_sqlsrv - -# Install Xdebug -RUN pecl install xdebug-3.3.2 && docker-php-ext-enable xdebug - -# Cleanup. -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -COPY --from=composer /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www diff --git a/docker/php-8.4/Dockerfile b/docker/php-8.4/Dockerfile deleted file mode 100644 index 2dba6ffc..00000000 --- a/docker/php-8.4/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM php:8.4-fpm-bookworm - -# Basic requirements -RUN apt-get update -RUN apt-get install -yqq --no-install-recommends default-mysql-client acl iproute2 zip zlib1g-dev libzip-dev \ - libxml2-dev libpng-dev libghc-curl-dev libldb-dev libldap2-dev gnupg2 libpq-dev sqlite3 - -# Instaling postgresql-client-16 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg && \ - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ - apt-get update && apt-get install -y postgresql-16 - -# PHP required extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath -RUN docker-php-ext-enable pdo_pgsql pdo_mysql sodium - -# SQL Server support -ENV ACCEPT_EULA=Y -RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list -RUN apt-get update -RUN apt-get -y --no-install-recommends install msodbcsql18 unixodbc-dev -RUN pecl install sqlsrv -RUN pecl install pdo_sqlsrv -RUN docker-php-ext-enable sqlsrv pdo_sqlsrv - -# Install Xdebug -RUN pecl install xdebug-3.4.0beta1 && docker-php-ext-enable xdebug - -# Cleanup. -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -COPY --from=composer /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www diff --git a/docker/php-8.5/Dockerfile b/docker/php-8.5/Dockerfile deleted file mode 100644 index 81c8b9d1..00000000 --- a/docker/php-8.5/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM php:8.5-fpm-bookworm - -# Basic requirements -RUN apt-get update -RUN apt-get install -yqq --no-install-recommends default-mysql-client acl iproute2 zip zlib1g-dev libzip-dev \ - libxml2-dev libpng-dev libghc-curl-dev libldb-dev libldap2-dev gnupg2 libpq-dev sqlite3 - -# Instaling postgresql-client-16 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg && \ - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ - apt-get update && apt-get install -y postgresql-16 - -# PHP required extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath -RUN docker-php-ext-enable pdo_pgsql pdo_mysql sodium - -# SQL Server support -# Waiting pdo_sqlsrv to be compatible with PHP-8.5 -# @see https://github.com/microsoft/msphpsql/issues/1546 -# ENV ACCEPT_EULA=Y -# RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - -# RUN curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list -# RUN apt-get update -# RUN apt-get -y --no-install-recommends install msodbcsql18 unixodbc-dev -# RUN pecl install sqlsrv -# RUN pecl install pdo_sqlsrv -# RUN docker-php-ext-enable sqlsrv pdo_sqlsrv - -# Install Xdebug -RUN pecl install xdebug-3.5.0 && docker-php-ext-enable xdebug - -# Cleanup. -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -COPY --from=composer /usr/bin/composer /usr/bin/composer - -WORKDIR /var/www diff --git a/docker/php-dev/Dockerfile b/docker/php-dev/Dockerfile new file mode 100644 index 00000000..ee6897c4 --- /dev/null +++ b/docker/php-dev/Dockerfile @@ -0,0 +1,96 @@ +# Dockerfile for PHP 8.1 and greater. +ARG COMPOSER_VERSION=latest +ARG PHP_VERSION=8.1 + +FROM composer:${COMPOSER_VERSION} AS composer-builder + +FROM php:${PHP_VERSION}-fpm-trixie + +# Basic requirements +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + <<'EOT' + rm -f /etc/apt/apt.conf.d/docker-clean || true + echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/docker-keep-cache + echo 'APT::Install-Recommends "false";' >/etc/apt/apt.conf.d/docker-no-install-recommends + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y --no-install-recommends \ + -o Dpkg::Options::='--force-confdef' \ + -o Dpkg::Options::='--force-confold' \ + acl \ + default-mysql-client \ + gnupg2 \ + iproute2 \ + libghc-curl-dev \ + libldap2-dev \ + libldb-dev \ + libpng-dev \ + libpq-dev \ + libxml2-dev \ + libzip-dev \ + sqlite3 \ + zip \ + zlib1g-dev + apt-get clean + apt autoclean -y + apt autoremove -y + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +EOT + +# For now, we keep the v16 version, because 18 will add a "transaction_timeout" +# in all its dump, which will make very unhappy v10 and v16. Since we test all +# versions using the same client library, we have no other choice than keep +# the lowest common denominator, for now, until we fix this in a reasonable +# way. +# Postgresql-client-16 +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + <<'EOT' + export DEBIAN_FRONTEND=noninteractive + curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg + sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt trixie-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + apt-get update + apt-get install -y --no-install-recommends \ + -o Dpkg::Options::='--force-confdef' \ + -o Dpkg::Options::='--force-confold' \ + postgresql-16 + apt-get clean + apt autoclean -y + apt autoremove -y + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +EOT + +# PHP extensions and Xdebug +RUN <<'EOT' + docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql + docker-php-ext-install -j$(nproc) pgsql pdo_pgsql pdo mysqli pdo_mysql zip xml gd curl bcmath + docker-php-ext-enable pdo_pgsql pdo_mysql sodium + pecl install xdebug && docker-php-ext-enable xdebug +EOT + +# SQL Server support +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + <<'EOT' + export DEBIAN_FRONTEND=noninteractive + export ACCEPT_EULA=Y + curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg + curl https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list + apt-get update + apt-get install -y --no-install-recommends \ + -o Dpkg::Options::='--force-confdef' \ + -o Dpkg::Options::='--force-confold' \ + msodbcsql18 \ + unixodbc-dev + pecl install sqlsrv + pecl install pdo_sqlsrv + docker-php-ext-enable sqlsrv pdo_sqlsrv + apt-get clean + apt autoclean -y + apt autoremove -y +EOT + +COPY --from=composer-builder /usr/bin/composer /usr/local/bin/composer + +WORKDIR /var/www diff --git a/docker/php-dev/docker.env b/docker/php-dev/docker.env new file mode 100644 index 00000000..6f5fc2e4 --- /dev/null +++ b/docker/php-dev/docker.env @@ -0,0 +1,4 @@ +PHP_IDE_CONFIG="serverName=docker" +XDEBUG_CONFIG="client_host=host.docker.internal client_port=9000 log=/tmp/xdebug.log output_dir=/tmp start_with_request=trigger" +#XDEBUG_MODE="debug" +XDEBUG_MODE="" diff --git a/docs/content/getting-started/database-vendors.md b/docs/content/getting-started/database-vendors.md index a5fcc051..c43975df 100644 --- a/docs/content/getting-started/database-vendors.md +++ b/docs/content/getting-started/database-vendors.md @@ -5,7 +5,7 @@ Fully supported database vendors are: - PostgreSQL 10 and above
(previous versions from 9.5 are untested but should work) - MariaDB 10.11 and above -- MySQL 5.7, 8.0 and above +- MySQL 8.0 and above Partially supported database vendors are: diff --git a/docs/content/getting-started/installation.md b/docs/content/getting-started/installation.md index ad6358f9..c792b1e1 100644 --- a/docs/content/getting-started/installation.md +++ b/docs/content/getting-started/installation.md @@ -28,7 +28,7 @@ Currently supported database vendors: - PostgreSQL 10 and above
(previous versions from 9.5 are untested but should work) - MariaDB 10.11 and above -- MySQL 5.7, 8.0 and above +- MySQL 8.0 and above - SQLite 3.0 and above ::: info diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c67ba70f..34b0396e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,11 +2,8 @@ - - - - - + + diff --git a/src/Bridge/Standalone/Bootstrap.php b/src/Bridge/Standalone/Bootstrap.php index 32b16932..f2e058b8 100644 --- a/src/Bridge/Standalone/Bootstrap.php +++ b/src/Bridge/Standalone/Bootstrap.php @@ -423,7 +423,7 @@ private static function configParseFile(string $filename): array /** * Get config variables from environment variables. */ - private static function configGetEnv(array $config): array + public static function configGetEnv(array $config): array { if (!isset($config['connections'])) { $config['connections'] = ['default' => self::getEnv('DBTOOLS_CONNECTION')]; diff --git a/src/Test/FunctionalTestCase.php b/src/Test/FunctionalTestCase.php index 0091f33b..88d162d2 100644 --- a/src/Test/FunctionalTestCase.php +++ b/src/Test/FunctionalTestCase.php @@ -4,14 +4,7 @@ namespace MakinaCorpus\DbToolsBundle\Test; -use Doctrine\DBAL\Configuration; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\AbstractSQLiteDriver\Middleware\EnableForeignKeys; -use Doctrine\DBAL\Driver\OCI8\Middleware\InitializeSession; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Logging\Middleware; use Doctrine\DBAL\Schema\Column; -use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; use Doctrine\Persistence\ManagerRegistry; use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizator; use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AnonymizerRegistry; @@ -19,22 +12,17 @@ use MakinaCorpus\DbToolsBundle\Anonymization\Config\AnonymizerConfig; use MakinaCorpus\DbToolsBundle\Bridge\Symfony\DoctrineDatabaseSessionRegistry; use MakinaCorpus\DbToolsBundle\Database\DatabaseSessionRegistry; -use MakinaCorpus\QueryBuilder\Bridge\Doctrine\DoctrineQueryBuilder; -use MakinaCorpus\QueryBuilder\DatabaseSession; +use MakinaCorpus\QueryBuilder\Bridge\Bridge; +use MakinaCorpus\QueryBuilder\Bridge\Doctrine\DoctrineBridge; +use MakinaCorpus\QueryBuilder\BridgeFactory; +use MakinaCorpus\QueryBuilder\Dsn; use MakinaCorpus\QueryBuilder\Error\Server\DatabaseObjectDoesNotExistError; -use Psr\Log\AbstractLogger; abstract class FunctionalTestCase extends UnitTestCase { - private bool $initialized = false; - /** - * @deprecated - * Remove when hard dependency on doctrine/dbal will be gone. - */ - private ?Connection $connection = null; - /** - * @var string[] - */ + private ?Bridge $connection = null; + private ?Bridge $privConnection = null; + /** @var string[] */ private array $createdTables = []; /** @after */ @@ -48,53 +36,48 @@ protected function disconnect(): void $this->createdTables = []; } - if ($this->connection) { - while ($this->connection->isTransactionActive()) { - $this->connection->rollBack(); - } - unset($this->connection); + if (null !== $this->connection) { + $this->connection->close(); + $this->connection = null; + } + + if (null !== $this->privConnection) { + $this->privConnection->close(); + $this->privConnection = null; } } /** * Initialize database. */ - protected function initializeDatabase(): void + protected function initializeDatabase(string $dbName): void { - $privConnection = $this->createPrivConnection(); + $privConnection = $this->getDatabaseSessionWithPrivileges(); try { - $privConnection->createSchemaManager()->createDatabase('test_db'); - } catch (\Exception $e) { - - } finally { - $privConnection->close(); + $privConnection->executeStatement("CREATE DATABASE ?::id", [$dbName]); + } catch (\Throwable $e) { + // Check database already exists or not. + if (!\str_contains($e->getMessage(), 'exist')) { + throw $e; + } } } /** - * Get testing connection object. - * - * @deprecated - * Remove when hard dependency on doctrine/dbal will is gone. + * Create query builder. */ - protected function getDoctrineConnection(): Connection + #[\Override] + protected function getDatabaseSession(): Bridge { - if (!$this->initialized) { - $this->initializeDatabase(); - - $this->initialized = true; - } - - return $this->connection ??= $this->createDoctrineConnection(); + return $this->connection ??= $this->createBridge(); } /** - * Get database session. + * Create priviledged query builder. */ - #[\Override] - protected function getDatabaseSession(): DatabaseSession + protected function getDatabaseSessionWithPrivileges(): Bridge { - return new DoctrineQueryBuilder($this->getDoctrineConnection()); + return $this->privConnection ??= $this->createPriviledgeBridge(); } /** @@ -102,7 +85,13 @@ protected function getDatabaseSession(): DatabaseSession */ protected function getDatabaseSessionRegistry(): DatabaseSessionRegistry { - $doctrineConnection = $this->getDoctrineConnection(); + $bridge = $this->getDatabaseSession(); + + if (!$bridge instanceof DoctrineBridge) { + throw new \Exception("Connection is not a Doctrine bridge."); + } + + $doctrineConnection = $bridge->getConnection(); $doctrineRegistry = $this->createMock(ManagerRegistry::class); $doctrineRegistry @@ -258,114 +247,91 @@ protected function createAnonymizatorWithConfig(AnonymizerConfig ...$anonymizerC } /** - * Create database connection. - * - * Default will use a mock object. - * - * @deprecated - * Remove when hard dependency on doctrine/dbal will be gone. + * Create connection. */ - private function createDoctrineConnection(): Connection + private function createBridge(): Bridge { $params = $this->getConnectionParameters(); - return DriverManager::getConnection( - $params, - self::createConfiguration($params['driver']), - ); + if (!\str_contains($params['driver'], 'sqlite')) { + if ($params['dbname']) { + $this->initializeDatabase($params['dbname']); + } + } + + return BridgeFactory::createDoctrine($params); } /** - * Get connection parameters from environment. + * Create priviledged query builder. */ - private function getConnectionParameters(): array + private function createPriviledgeBridge(): Bridge { - if (!$driver = \getenv('DBAL_DRIVER')) { - self::markTestSkipped("Missing 'DBAL_DRIVER' environment variable."); + return BridgeFactory::createDoctrine($this->getPriviledgedConnectionParameters()); + } + + /** + * Get connection parameters for user with privileges connection. + * + * This connection serves the purpose of initializing database. + */ + private function getPriviledgedConnectionParameters(): array + { + if (!$dsnString = \getenv('DATABASE_URL')) { + self::markTestSkipped("Missing 'DATABASE_URL' environment variable."); + } + $dsn = Dsn::fromString($dsnString); + + $driver = \getenv('DATABASE_DRIVER') ?: $dsn->getDriver(); + if ($driver === Dsn::DRIVER_ANY) { + $driver = BridgeFactory::guessDoctrineDriver($dsn->getVendor(), $driver); } $driverOptions = []; if (\str_contains($driver, 'sqlsrv')) { // https://stackoverflow.com/questions/71688125/odbc-driver-18-for-sql-serverssl-provider-error1416f086 $driverOptions['TrustServerCertificate'] = "true"; + $driverOptions['MultipleActiveResultSets'] = "false"; } - $params = \array_filter([ - 'dbname' => \getenv('DBAL_DBNAME'), + return \array_filter([ 'driver' => $driver, - 'driverOptions' => $driverOptions, - 'host' => \getenv('DBAL_HOST'), - 'password' => \getenv('DBAL_PASSWORD'), - 'port' => ($port = \getenv('DBAL_PORT')) ? ((int) $port) : null, - 'user' => \getenv('DBAL_USER'), - 'path' => \getenv('DBAL_PATH'), - ]); - - return $params; + 'host' => $dsn->getHost(), + 'password' => \getenv('DATABASE_ROOT_PASSWORD') ?: $dsn->getPassword(), + 'port' => $dsn->getPort(), + 'user' => \getenv('DATABASE_ROOT_USER') ?: $dsn->getUser(), + ]) + $driverOptions; } /** - * Connexion with administration rights, for database setup. + * Get connection parameters for test user. */ - private function createPrivConnection(): Connection + private function getConnectionParameters(): array { - $params = $this->getConnectionParameters(); - - if ($value = \getenv('DBAL_ROOT_USER')) { - $params['user'] = $value; - } - if ($value = \getenv('DBAL_ROOT_PASSWORD')) { - $params['password'] = $value; + if (!$dsnString = \getenv('DATABASE_URL')) { + self::markTestSkipped("Missing 'DATABASE_URL' environment variable."); } - // Avoid error upon connection when database does not exit. - unset($params['dbname']); + $dsn = Dsn::fromString($dsnString); - return DriverManager::getConnection( - $params, - self::createConfiguration($params['driver']), - ); - } - - /** - * Code copied and adapted from doctrine/dbal package. - * - * @see \Doctrine\DBAL\Tests\FunctionalTestCase - */ - private static function createConfiguration(string $driver): Configuration - { - $configuration = new Configuration(); - $middlewares = []; - - // @todo Option - /* @phpstan-ignore-next-line */ - if (false) { - $middlewares[] = new Middleware( - new class () extends AbstractLogger { - #[\Override] - public function log($level, string|\Stringable $message, array $context = []): void - { - if (\str_contains($message, 'Executing statement')) { - echo $message, \print_r($context, true), "\n"; - } - } - }, - ); + $driver = \getenv('DATABASE_DRIVER') ?: $dsn->getDriver(); + if (Dsn::DRIVER_ANY === $driver) { + $driver = BridgeFactory::guessDoctrineDriver($dsn->getVendor(), $driver); } - switch ($driver) { - case 'pdo_oci': - case 'oci8': - $middlewares[] = new InitializeSession(); - break; - case 'pdo_sqlite': - case 'sqlite3': - $middlewares[] = new EnableForeignKeys(); - break; + $driverOptions = []; + if (\str_contains($driver, 'sqlsrv')) { + // https://stackoverflow.com/questions/71688125/odbc-driver-18-for-sql-serverssl-provider-error1416f086 + $driverOptions['TrustServerCertificate'] = "true"; + $driverOptions['MultipleActiveResultSets'] = "false"; } - $configuration->setMiddlewares($middlewares); - $configuration->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - - return $configuration; + return \array_filter([ + 'dbname' => 'test_db', + 'driver' => $driver, + 'host' => $dsn->getHost(), + 'password' => $dsn->getPassword(), + 'port' => $dsn->getPort(), + 'user' => $dsn->getUser(), + ] + $driverOptions); } } diff --git a/tests/Functional/BackupperRestorer/BackupperRestorerTest.php b/tests/Functional/BackupperRestorer/BackupperRestorerTest.php index 05206699..5874557f 100644 --- a/tests/Functional/BackupperRestorer/BackupperRestorerTest.php +++ b/tests/Functional/BackupperRestorer/BackupperRestorerTest.php @@ -5,6 +5,7 @@ namespace MakinaCorpus\DbToolsBundle\Tests\Functional\BackupperRestorer; use MakinaCorpus\DbToolsBundle\Backupper\BackupperFactory; +use MakinaCorpus\DbToolsBundle\Bridge\Standalone\Bootstrap; use MakinaCorpus\DbToolsBundle\Configuration\Configuration; use MakinaCorpus\DbToolsBundle\Configuration\ConfigurationRegistry; use MakinaCorpus\DbToolsBundle\Error\NotImplementedException; @@ -71,14 +72,35 @@ protected function createTestData(): void ); } + private function createConfigurationRegistry(): ConfigurationRegistry + { + // We require ENV vars to be read, so we need this. + $config = Bootstrap::configGetEnv([]); + + $default = new Configuration( + backupBinary: $config['backup_binary'] ?? null, + backupExcludedTables: $config['backup_excluded_tables'] ?? null, + backupExpirationAge: $config['backup_expiration_age'] ?? null, + backupOptions: $config['backup_options'] ?? null, + backupTimeout: $config['backup_timeout'] ?? null, + restoreBinary: $config['restore_binary'] ?? null, + restoreOptions: $config['restore_options'] ?? null, + restoreTimeout: $config['restore_timeout'] ?? null, + storageDirectory: $config['storage_directory'] ?? null, + storageFilenameStrategy: $config['storage_filename_strategy'] ?? null, + ); + + return new ConfigurationRegistry($default); + } + private function getBackupperFactory(): BackupperFactory { - return new BackupperFactory($this->getDatabaseSessionRegistry(), new ConfigurationRegistry()); + return new BackupperFactory($this->getDatabaseSessionRegistry(), $this->createConfigurationRegistry()); } private function getRestorerFactory(): RestorerFactory { - return new RestorerFactory($this->getDatabaseSessionRegistry(), new ConfigurationRegistry()); + return new RestorerFactory($this->getDatabaseSessionRegistry(), $this->createConfigurationRegistry()); } public function testBackupper(): void @@ -167,9 +189,10 @@ public function testBackupperWithExtraOptions(): void $backupper ->setDestination($backupFilename) ->setExtraOptions( + // --skip-ssl is added due to local docker testing environment. Do NOT remove this option. match ($this->getDatabaseSession()->getVendorName()) { - Vendor::MARIADB => '-v --no-tablespaces --add-drop-table --skip-quote-names', - Vendor::MYSQL => '-v --no-tablespaces --add-drop-table --skip-quote-names', + Vendor::MARIADB => '-v --no-tablespaces --skip-ssl --add-drop-table --skip-quote-names', + Vendor::MYSQL => '-v --no-tablespaces --skip-ssl --add-drop-table --skip-quote-names', Vendor::POSTGRESQL => '-v --no-owner -Z 5 --lock-wait-timeout=120', Vendor::SQLITE => '-bail -readonly', // No interesting options for SQLite. default => $this->markTestSkipped('Driver unsupported: ' . \getenv('DBAL_DRIVER')), @@ -215,9 +238,10 @@ public function testRestorerWithExtraOptions(): void $restorer ->setBackupFilename($this->prepareBackupFilename($restorer->getExtension())) ->setExtraOptions( + // --skip-ssl is added due to local docker testing environment. Do NOT remove this option. match ($databaseSession->getVendorName()) { - Vendor::MARIADB => '-v --no-auto-rehash --skip-progress-reports', - Vendor::MYSQL => '-v --no-auto-rehash', + Vendor::MARIADB => '-v --skip-ssl --no-auto-rehash --skip-progress-reports', + Vendor::MYSQL => '-v --skip-ssl --no-auto-rehash', Vendor::POSTGRESQL => '-v -j 2 --disable-triggers --clean --if-exists', Vendor::SQLITE => '-bail', // No interesting options for SQLite. default => $this->markTestSkipped('Driver unsupported: ' . \getenv('DBAL_DRIVER')), @@ -246,7 +270,7 @@ public function testCreateBackupper(): void { $this->skipIfDatabase(Vendor::SQLSERVER); - $backupperFactory = new BackupperFactory($this->getDatabaseSessionRegistry(), new ConfigurationRegistry()); + $backupperFactory = new BackupperFactory($this->getDatabaseSessionRegistry(), $this->createConfigurationRegistry()); $backupper = $backupperFactory->create();