diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8813a1fe94..628903944d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,6 +193,9 @@ jobs: - name: PostgreSQL 13, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:13-3.1 NODE_VERSION: 14.18.1 + - name: PostgreSQL 14, PostGIS 3.1 + POSTGRES_IMAGE: postgis/postgis:14-3.1 + NODE_VERSION: 14.18.1 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 @@ -232,7 +235,9 @@ jobs: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}- - name: Install dependencies run: npm ci - - run: bash scripts/before_script_postgres.sh + - run: | + bash scripts/before_script_postgres_conf.sh + bash scripts/before_script_postgres.sh - run: npm run coverage env: CI: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb444414b4..eaf4b648d0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -145,13 +145,15 @@ If your pull request introduces a change that may affect the storage or retrieva - `it_only_mongodb_version('>=4.4')` // will test with any version of Postgres but only with version >=4.4 of MongoDB; accepts semver notation to specify a version range - `it_exclude_mongodb_version('<4.4')` // will test with any version of Postgres and MongoDB, excluding version <4.4 of MongoDB; accepts semver notation to specify a version range + - `it_only_postgres_version('>=13')` // will test with any version of Mongo but only with version >=13 of Postgres; accepts semver notation to specify a version range + - `it_exclude_postgres_version('<13')` // will test with any version of Postgres and MongoDB, excluding version <13 of Postgres; accepts semver notation to specify a version range #### Postgres with Docker [PostGIS images (select one with v2.2 or higher) on docker dashboard](https://hub.docker.com/r/postgis/postgis) is based off of the official [postgres](https://registry.hub.docker.com/_/postgres/) image and will work out-of-the-box (as long as you create a user with the necessary extensions for each of your Parse databases; see below). To launch the compatible Postgres instance, copy and paste the following line into your shell: ``` -docker run -d --name parse-postgres -p 5432:5432 -e POSTGRES_PASSWORD=password --rm postgis/postgis:11-3.0-alpine && sleep 20 && docker exec -it parse-postgres psql -U postgres -c 'CREATE DATABASE parse_server_postgres_adapter_test_database;' && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION pgcrypto; CREATE EXTENSION postgis;' -d parse_server_postgres_adapter_test_database && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION postgis_topology;' -d parse_server_postgres_adapter_test_database +docker run -d --name parse-postgres -p 5432:5432 -e POSTGRES_PASSWORD=password --rm postgis/postgis:13-3.1-alpine && sleep 20 && docker exec -it parse-postgres psql -U postgres -c 'CREATE DATABASE parse_server_postgres_adapter_test_database;' && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION pgcrypto; CREATE EXTENSION postgis;' -d parse_server_postgres_adapter_test_database && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION postgis_topology;' -d parse_server_postgres_adapter_test_database ``` To stop the Postgres instance: @@ -159,7 +161,7 @@ To stop the Postgres instance: docker stop parse-postgres ``` -You can also use the [postgis/postgis:11-2.5-alpine](https://hub.docker.com/r/postgis/postgis) image in a Dockerfile and copy this [script](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) to the image by adding the following lines: +You can also use the [postgis/postgis:13-3.1-alpine](https://hub.docker.com/r/postgis/postgis) image in a Dockerfile and copy this [script](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) to the image by adding the following lines: ``` #Install additional scripts. These are run in abc order during initial start diff --git a/README.md b/README.md index b46205486f..7e4e0dce8b 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ --- -[![Build Status](https://github.com/parse-community/parse-server/workflows/ci/badge.svg?branch=master)](https://github.com/parse-community/parse-server/actions?query=workflow%3Aci+branch%3Amaster) +[![Build Status](https://github.com/parse-community/parse-server/workflows/ci/badge.svg?branch=alpha)](https://github.com/parse-community/parse-server/actions?query=workflow%3Aci+branch%3Aalpha) [![Snyk Badge](https://snyk.io/test/github/parse-community/parse-server/badge.svg)](https://snyk.io/test/github/parse-community/parse-server) -[![Coverage](https://img.shields.io/codecov/c/github/parse-community/parse-server/master.svg)](https://codecov.io/github/parse-community/parse-server?branch=master) +[![Coverage](https://img.shields.io/codecov/c/github/parse-community/parse-server/alpha.svg)](https://codecov.io/github/parse-community/parse-server?branch=alpha) [![Node Version](https://img.shields.io/badge/nodejs-12,_14,_15-green.svg?logo=node.js&style=flat)](https://nodejs.org) [![MongoDB Version](https://img.shields.io/badge/mongodb-4.0,_4.2,_4.4,_5.0-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) -[![Postgres Version](https://img.shields.io/badge/postgresql-11,_12,_13-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) +[![Postgres Version](https://img.shields.io/badge/postgresql-11,_12,_13,_14-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) [![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) [![npm latest version](https://img.shields.io/npm/v/parse-server/latest.svg)](https://www.npmjs.com/package/parse-server) @@ -121,7 +121,7 @@ Parse Server is continuously tested with the most recent releases of MongoDB to |-------------|----------------|------------------|--------------------| | MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Fully compatible | | MongoDB 4.2 | 4.2.17 | TBD | ✅ Fully compatible | -| MongoDB 4.4 | 4.4.10 | TBD | ✅ Fully compatible | +| MongoDB 4.4 | 4.4.10 | TBD | ✅ Fully compatible | | MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Fully compatible | #### PostgreSQL @@ -132,6 +132,7 @@ Parse Server is continuously tested with the most recent releases of PostgreSQL | Postgres 11 | 3.0, 3.1 | November 2023 | April 2022 | ✅ Fully compatible | | Postgres 12 | 3.1 | November 2024 | April 2023 | ✅ Fully compatible | | Postgres 13 | 3.1 | November 2025 | April 2024 | ✅ Fully compatible | +| Postgres 14 | 3.1 | November 2026 | April 2025 | ✅ Fully compatible | ### Locally ```bash diff --git a/scripts/before_script_postgres_conf.sh b/scripts/before_script_postgres_conf.sh new file mode 100755 index 0000000000..ec471d9c3f --- /dev/null +++ b/scripts/before_script_postgres_conf.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +echo "[SCRIPT] Before Script :: Setup Parse Postgres configuration file" + +# DB Version: 13 +# OS Type: linux +# DB Type: web +# Total Memory (RAM): 6 GB +# CPUs num: 1 +# Data Storage: ssd + +PGPASSWORD=postgres psql -v ON_ERROR_STOP=1 -h localhost -U postgres <<-EOSQL + ALTER SYSTEM SET max_connections TO '200'; + ALTER SYSTEM SET shared_buffers TO '1536MB'; + ALTER SYSTEM SET effective_cache_size TO '4608MB'; + ALTER SYSTEM SET maintenance_work_mem TO '384MB'; + ALTER SYSTEM SET checkpoint_completion_target TO '0.9'; + ALTER SYSTEM SET wal_buffers TO '16MB'; + ALTER SYSTEM SET default_statistics_target TO '100'; + ALTER SYSTEM SET random_page_cost TO '1.1'; + ALTER SYSTEM SET effective_io_concurrency TO '200'; + ALTER SYSTEM SET work_mem TO '3932kB'; + ALTER SYSTEM SET min_wal_size TO '1GB'; + ALTER SYSTEM SET max_wal_size TO '4GB'; + SELECT pg_reload_conf(); +EOSQL + +exec "$@" diff --git a/spec/.eslintrc.json b/spec/.eslintrc.json index e76afb3a66..519da96484 100644 --- a/spec/.eslintrc.json +++ b/spec/.eslintrc.json @@ -17,8 +17,10 @@ "notEqual": true, "it_only_db": true, "it_only_mongodb_version": true, + "it_only_postgres_version": true, "fit_only_mongodb_version": true, "it_exclude_mongodb_version": true, + "it_exclude_postgres_version": true, "fit_exclude_mongodb_version": true, "it_exclude_dbs": true, "describe_only_db": true, diff --git a/spec/ParseQuery.Aggregate.spec.js b/spec/ParseQuery.Aggregate.spec.js index 4d6ab59c40..04fa6068ed 100644 --- a/spec/ParseQuery.Aggregate.spec.js +++ b/spec/ParseQuery.Aggregate.spec.js @@ -223,9 +223,8 @@ describe('Parse.Query Aggregate testing', () => { const obj3 = new TestObject(); const pipeline = [ { - // TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx) - group: { - objectId: { + $group: { + _id: { day: { $dayOfMonth: '$_updated_at' }, month: { $month: '$_created_at' }, year: { $year: '$_created_at' }, @@ -254,9 +253,8 @@ describe('Parse.Query Aggregate testing', () => { const obj3 = new TestObject(); const pipeline = [ { - // TODO: update to new syntax. See [#7339](https://bit.ly/3incnWx) - group: { - objectId: { + $group: { + _id: { day: { $dayOfMonth: '$updatedAt' }, month: { $month: '$createdAt' }, year: { $year: '$createdAt' }, diff --git a/spec/helper.js b/spec/helper.js index 49de5c453f..612c716202 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -446,6 +446,15 @@ global.it_only_mongodb_version = version => { } }; +global.it_only_postgres_version = version => { + const envVersion = process.env.POSTGRES_VERSION; + if (!envVersion || semver.satisfies(envVersion, version)) { + return it; + } else { + return xit; + } +}; + global.fit_only_mongodb_version = version => { const envVersion = process.env.MONGODB_VERSION; if (!envVersion || semver.satisfies(envVersion, version)) { @@ -464,6 +473,15 @@ global.it_exclude_mongodb_version = version => { } }; +global.it_exclude_postgres_version = version => { + const envVersion = process.env.POSTGRES_VERSION; + if (!envVersion || !semver.satisfies(envVersion, version)) { + return it; + } else { + return xit; + } +}; + global.fit_exclude_mongodb_version = version => { const envVersion = process.env.MONGODB_VERSION; if (!envVersion || !semver.satisfies(envVersion, version)) { diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 5d0e211ab4..065d5c93a3 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -1983,10 +1983,10 @@ export class PostgresStorageAdapter implements StorageAdapter { return this._client .one(qs, values, a => { - if (a.approximate_row_count != null) { - return +a.approximate_row_count; + if (a.approximate_row_count == null || a.approximate_row_count == -1) { + return !isNaN(+a.count) ? +a.count : 0; } else { - return +a.count; + return +a.approximate_row_count; } }) .catch(error => { @@ -2111,7 +2111,7 @@ export class PostgresStorageAdapter implements StorageAdapter { columns.push( `EXTRACT(${ mongoAggregateToPostgres[operation] - } FROM $${index}:name AT TIME ZONE 'UTC') AS $${index + 1}:name` + } FROM $${index}:name AT TIME ZONE 'UTC')::integer AS $${index + 1}:name` ); values.push(source, alias); index += 2;