diff --git a/.dockerignore b/.dockerignore index 14aa2027..07018df1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,15 @@ +# Exclude files and directories to minimize +# the Docker build context size. +# This practice limits the scope of COPY commands in the Dockerfile. +# When not using multi-layer builds, it can effectively reduce the final image size. + +# The first part of this file is should be the same as the .gitignore file +# The second part is the extra not needed content for .dockerignore + +######################################################## +# first part: .gitignore contents +######################################################## + # Global excludes across all subdirectories **/*.o **/*.obj @@ -32,9 +44,6 @@ **/lib*dll.def **/lib*.pc -# documnetation files -doc/ - # Local excludes in root directory t/__pycache__/ log/ @@ -46,4 +55,26 @@ output_iso/ include/utils/stopevents_defs.h include/utils/stopevents_data.h orioledb.typedefs -!**/ci/antithesis/libvoidstar.so \ No newline at end of file +ci/antithesis + + + +####################################################### +# second part: extra .dockerignore contents +####################################################### + +# Exclude version control and continuous integration (CI) directories +.git +.github + +# Exclude Dockerfiles +Dockerfile +Dockerfile.ubuntu + +# Exclude OrioleDB Docker test definitions and code +# as they are not needed inside the Docker image. +test/ +ci/local_docker_matrix.sh + +# Documentation files, which are not needed inside the Docker image. +doc/ diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index bebbd44c..7f44aecf 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -19,7 +19,7 @@ jobs: compiler: [clang] distr: [alpine, ubuntu] include: - - distr-version: 3.18 + - distr-version: 3.19 distr: alpine - distr-version: focal distr: ubuntu @@ -28,17 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v3 - - - name: Set DOCKER_PG_LLVM_DEPS - run: | - if [[ "${{ matrix.distr }}" == "alpine" ]] && ([[ "${{ matrix.distr-version }}" == "3.18" ]] || [[ "${{ matrix.distr-version }}" == "edge" ]]); \ - then echo "DOCKER_PG_LLVM_DEPS=llvm15-dev clang15" >> $GITHUB_ENV; \ - else echo "DOCKER_PG_LLVM_DEPS=llvm-dev clang" >> $GITHUB_ENV; \ - fi - - - name: Echo DOCKER_PG_LLVM_DEP - run: echo "DOCKER_PG_LLVM_DEP = ${{ env.DOCKER_PG_LLVM_DEPS }} " + uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -54,7 +44,7 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v4 with: images: orioledb/orioledb tags: ${{ github.event.inputs.tags }} @@ -64,7 +54,7 @@ jobs: suffix=${{ contains(github.ref, 's3') && '-s3' || '' }}-pg${{ matrix.postgres }}${{ matrix.distr == 'ubuntu' && '-ubuntu' || '' }},onlatest=true - name: Build and push Docker image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . file: ${{ matrix.distr == 'ubuntu' && 'Dockerfile.ubuntu' || 'Dockerfile' }} @@ -77,4 +67,4 @@ jobs: UBUNTU_VERSION=${{ matrix.distr == 'ubuntu' && matrix.distr-version || '' }} PG_MAJOR=${{ matrix.postgres }} BUILD_CC_COMPILER=${{ matrix.compiler }} - DOCKER_PG_LLVM_DEPS=${{ env.DOCKER_PG_LLVM_DEPS }} + DOCKER_PG_LLVM_DEPS=llvm-dev clang diff --git a/.github/workflows/dockertest.yml b/.github/workflows/dockertest.yml index 48bf4fc1..c4d5c1fa 100644 --- a/.github/workflows/dockertest.yml +++ b/.github/workflows/dockertest.yml @@ -17,7 +17,7 @@ jobs: compiler: [clang] distr: [alpine, ubuntu] include: - - distr-version: 3.18 + - distr-version: 3.19 distr: alpine - distr-version: focal distr: ubuntu @@ -27,21 +27,12 @@ jobs: continue-on-error: ${{ matrix.alpine == 'edge' }} steps: - - name: Set DOCKER_PG_LLVM_DEPS - run: | - if [[ "${{ matrix.distr }}" == "alpine" ]] && ([[ "${{ matrix.distr-version }}" == "3.18" ]] || [[ "${{ matrix.distr-version }}" == "edge" ]]); \ - then echo "DOCKER_PG_LLVM_DEPS=llvm15-dev clang15" >> $GITHUB_ENV; \ - else echo "DOCKER_PG_LLVM_DEPS=llvm-dev clang" >> $GITHUB_ENV; \ - fi - - - name: Echo DOCKER_PG_LLVM_DEP - run: echo "DOCKER_PG_LLVM_DEP = ${{ env.DOCKER_PG_LLVM_DEPS }} " - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: docker build orioletest:${{ matrix.postgres }}-${{ matrix.compiler }}-${{ matrix.distr }}-${{ matrix.distr-version }} - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ${{ matrix.distr == 'ubuntu' && 'Dockerfile.ubuntu' || 'Dockerfile' }} @@ -54,4 +45,4 @@ jobs: UBUNTU_VERSION=${{ matrix.distr == 'ubuntu' && matrix.distr-version || '' }} PG_MAJOR=${{ matrix.postgres }} BUILD_CC_COMPILER=${{ matrix.compiler }} - DOCKER_PG_LLVM_DEPS=${{ env.DOCKER_PG_LLVM_DEPS }} + DOCKER_PG_LLVM_DEPS=llvm-dev clang diff --git a/.gitignore b/.gitignore index b8502f67..1148c3ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# When adding new definitions here, +# please also include them in the first part of the .dockerignore file. + # Global excludes across all subdirectories *.o *.obj diff --git a/Dockerfile b/Dockerfile index 0076d6d4..dde4110e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ # This is slightly adjusted Dockerfile from # https://github.com/docker-library/postgres -# set ALPINE_VERSION= [ edge 3.18 3.17 3.16 3.15 3.14 3.13 ] -ARG ALPINE_VERSION=3.17 +# set ALPINE_VERSION= [ edge 3.19 3.18 3.17 3.16 3.15 3.14 3.13 ] +ARG ALPINE_VERSION=3.19 FROM alpine:${ALPINE_VERSION} ARG ALPINE_VERSION # Set PG_MAJOR = [16 15] -ARG PG_MAJOR=15 +ARG PG_MAJOR=16 ENV PG_MAJOR ${PG_MAJOR} # set compiler: [ clang gcc ] @@ -53,7 +53,7 @@ RUN set -eux; \ # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split # https://github.com/docker-library/postgres/issues/327#issuecomment-1201582069 case "$ALPINE_VERSION" in 3.13 | 3.14 | 3.15 ) EXTRA_ICU_PACKAGES='' ;; \ - 3.16 | 3.17 | 3.18 | 3.19* ) EXTRA_ICU_PACKAGES=icu-data-full ;; \ + 3.16 | 3.17 | 3.18 | 3.19 | 3.20* ) EXTRA_ICU_PACKAGES=icu-data-full ;; \ *) : ;; \ esac ; \ \ @@ -78,22 +78,6 @@ RUN set -eux; \ fi ; \ fi ; \ \ -# temporary not allowing LLVM 16 to be used -# reason: we can't overwrite and fix the DOCKER_PG_LLVM_DEPS -# and the future downstream extensions like PostGIS need a correct build information (DOCKER_PG_LLVM_DEPS) - if \ - # if the custom llvm version is set ( via DOCKER_PG_LLVM_DEPS ), and it is 16, then halt operation - ( [ ! -z "${CUSTOM_LLVM_VERSION}" ] && [ "$CUSTOM_LLVM_VERSION" == "16" ] ) \ - # or - if the custom llvm version is not set, and the Alpine version is >=3.18, then halt operation - || ( [ -z "${CUSTOM_LLVM_VERSION}" ] && ( [ "$ALPINE_VERSION" == "3.18" ] || [ "$ALPINE_VERSION" == "3.19" ]) ) \ - ; then \ - set +x ; \ - echo "------------------------------" ; \ - echo "Error: The LLVM 16 is not compatible with the current PostgreSQL! Halting operation." ; \ - echo "Suggested workarounds: use --build-arg DOCKER_PG_LLVM_DEPS='llvm15-dev clang15' " ; \ - exit 1; \ - fi ; \ - \ apk add --no-cache --virtual .build-deps \ ${DOCKER_PG_LLVM_DEPS} \ bison \ diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu index 29b5560d..a301227d 100644 --- a/Dockerfile.ubuntu +++ b/Dockerfile.ubuntu @@ -1,11 +1,15 @@ # This is modified Dockerfile from 16/bookworm in # https://github.com/docker-library/postgres +# Set UBUNTU_VERSION = [ devel 23.10 22.04 20.04 ] +# or [ devel mantic jammy focal ] ARG UBUNTU_VERSION=focal FROM ubuntu:${UBUNTU_VERSION} -# Set PG_MAJOR = [16 15 14 13 ] -ARG PG_MAJOR=14 +ARG UBUNTU_VERSION + +# Set PG_MAJOR = [16 15] +ARG PG_MAJOR=16 ENV PG_MAJOR ${PG_MAJOR} # set compiler: [ clang gcc ] @@ -28,16 +32,33 @@ RUN set -eux; \ mkdir -p /var/lib/postgresql; \ chown -R postgres:postgres /var/lib/postgresql -RUN set -ex; \ +RUN set -eux; \ apt-get update; \ - apt-get install -y --no-install-recommends \ + DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y; \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ca-certificates \ gnupg \ - ; \ - rm -rf /var/lib/apt/lists/* + locales \ + tzdata \ + \ + # Ensures compatibility with the official PostgreSQL Docker image + libnss-wrapper \ + xz-utils \ + zstd \ + ; \ + echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ + locale-gen; \ + locale -a | grep 'en_US.utf8' ; \ + \ + rm -rf /var/lib/apt/lists/* ; \ + apt-get clean + +# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default +ENV LANG en_US.utf8 # grab gosu for easy step-down from root # https://github.com/tianon/gosu/releases -ENV GOSU_VERSION 1.16 +ENV GOSU_VERSION 1.17 RUN set -eux; \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ @@ -58,20 +79,6 @@ RUN set -eux; \ gosu --version; \ gosu nobody true -RUN set -eux; \ - apt-get update; \ - DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y; \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - locales \ - tzdata \ - curl \ - ca-certificates \ - ; \ - localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8; - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -ENV LANG en_US.utf8 - RUN mkdir -p /usr/src/postgresql/contrib/orioledb COPY . /usr/src/postgresql/contrib/orioledb @@ -92,11 +99,16 @@ RUN set -eux; \ echo "ORIOLEDB_BUILDTIME=$ORIOLEDB_BUILDTIME" ; \ echo "DOCKER_PG_LLVM_DEPS=$DOCKER_PG_LLVM_DEPS" ; \ \ + LLVM_RUNTIME_DEPS=$(echo "$DOCKER_PG_LLVM_DEPS" | grep -o 'llvm[0-9]*') ; \ + echo "LLVM_RUNTIME_DEPS=$LLVM_RUNTIME_DEPS" ; \ + \ apt-get update; \ DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \ build-essential \ + ${LLVM_RUNTIME_DEPS} \ ${DOCKER_PG_LLVM_DEPS} \ bison \ + curl \ flex \ gdb \ git \ @@ -113,7 +125,8 @@ RUN set -eux; \ libuuid1 \ libxml2 \ libxml2-dev \ - libxslt-dev \ + libxslt1.1 \ + libxslt1-dev \ libzstd1 \ libzstd-dev \ make \ @@ -179,7 +192,7 @@ RUN set -eux; \ --with-llvm \ --with-lz4 \ --with-zstd \ - --with-extra-version=" ${ORIOLEDB_VERSION} PGTAG=${PGTAG} ubuntu:focal+${BUILD_CC_COMPILER} build:${ORIOLEDB_BUILDTIME}" \ + --with-extra-version=" ${ORIOLEDB_VERSION} PGTAG=${PGTAG} ubuntu:${UBUNTU_VERSION}+${BUILD_CC_COMPILER} build:${ORIOLEDB_BUILDTIME}" \ || cat config.log ); \ echo "ORIOLEDB_PATCHSET_VERSION = `echo $PGTAG | cut -d'_' -f2`" >> src/Makefile.global; \ make -j "$(nproc)"; \ @@ -190,11 +203,26 @@ RUN set -eux; \ make -C contrib/orioledb install; \ \ apt-get -y remove \ - build-essential flex bison pkg-config \ - libreadline-dev libipc-run-perl \ - libicu-dev python3-dev python3-pip \ - libzstd-dev \ - curl wget liblz4-dev uuid-dev \ + ${DOCKER_PG_LLVM_DEPS} \ + bison \ + build-essential \ + curl \ + flex \ + gdb \ + git \ + libicu-dev \ + libipc-run-perl \ + liblz4-dev \ + libreadline-dev \ + libxml2-dev \ + libxslt1-dev \ + libzstd-dev \ + make \ + pkg-config \ + python3-dev \ + python3-pip \ + uuid-dev \ + wget \ ; \ apt-get -y autoremove; \ rm -rf /var/cache/apt/archives /var/lib/apt/lists/*; \ @@ -220,6 +248,7 @@ COPY --chown=postgres:postgres postgresql.docker.conf /etc/postgresql/postgresql ENV PG_CONF=/etc/postgresql/postgresql.conf COPY docker-entrypoint.sh /usr/local/bin/ +RUN sed -i -e 's/su-exec/gosu/g' "/usr/local/bin/docker-entrypoint.sh" ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/ci/local_docker_matrix.sh b/ci/local_docker_matrix.sh index 0e2331dd..0ccb3ab8 100755 --- a/ci/local_docker_matrix.sh +++ b/ci/local_docker_matrix.sh @@ -3,43 +3,92 @@ set -Eeo pipefail # Testing all possible docker builds on a local machine # run from project root: ./ci/local_docker_matrix.sh -# and check the logs in ./log_docker_build/*.log +# and check the logs in ./log_docker_build/*.*.log + +# Full matrix of test builds 2x2x12 = 48 builds +pg_major_list=( 16 15) +compiler_list=( clang gcc ) +base_list=( + # alpine versions + alpine:3.19 + alpine:3.18 + alpine:3.17 + alpine:3.16 + alpine:3.15 + alpine:3.14 + alpine:3.13 + + # ubuntu versions + ubuntu:23.10 + ubuntu:22.04 + ubuntu:20.04 + + # developer versions + alpine:edge + ubuntu:devel + ) + + # set and prepare $logpath for build logs -logpath=./log_docker_build +mkdir -p ./log_docker_build +logpath=./log_docker_build/"$(date +%Y-%m-%d-%H%M%S)-pid-$$" mkdir -p $logpath rm -f ${logpath}/*.log -# simple local build matxix - for build all images -for alpine in edge 3.18 3.17 3.16 3.15 3.14 3.13 ; do - # Refresh alpine images! - docker pull alpine:$alpine - for pg_major in 16 15 14 13; do - for compiler in clang gcc; do - # LLVM 16 hack for setting the correct DOCKER_PG_LLVM_DEPS - case "$alpine" in 3.18 | edge ) pg_llvm_deps='llvm15-dev clang15' ;; \ - * ) pg_llvm_deps='llvm-dev clang' ;; \ - esac ; \ +# Using official postgres docker test code +# from https://github.com/docker-library/postgres/blob/master/test +OFFIMG_LOCAL_CLONE=./log_docker_build/official-images +OFFIMG_REPO_URL=https://github.com/docker-library/official-images.git +# Check if the directory exists and contains a git repository +mkdir -p "$OFFIMG_LOCAL_CLONE" +if [ -d "$OFFIMG_LOCAL_CLONE/.git" ]; then + echo "::Updating official-images : $OFFIMG_LOCAL_CLONE" + pushd "$OFFIMG_LOCAL_CLONE" && git pull origin master && popd +else + echo "::Cloning official-images into $OFFIMG_LOCAL_CLONE" + git clone "$OFFIMG_REPO_URL" "$OFFIMG_LOCAL_CLONE" +fi + +for pg_major in "${pg_major_list[@]}" ; do + for compiler in "${compiler_list[@]}" ; do + for base in "${base_list[@]}" ; do - docker_tag="${pg_major}-${compiler}-alpine${alpine}" + base_os="${base%%:*}" + base_tag="${base##*:}" + base_os_upper="${base_os^^}" + + # Determine the Dockerfile based on base OS + if [ "$base_os" = "alpine" ]; then + dockerfile="Dockerfile" + elif [ "$base_os" = "ubuntu" ]; then + dockerfile="Dockerfile.ubuntu" + fi + + docker_tag="${pg_major}-${compiler}-${base_os}-${base_tag}" echo "------------ $docker_tag ------------------" - echo "params: ALPINE_VERSION=$alpine" - echo "params: BUILD_CC_COMPILER=$compiler" - echo "params: PG_MAJOR=$pg_major" - echo "params: DOCKER_PG_LLVM_DEPS=$pg_llvm_deps" - echo "----------------------------------------" - - rm -f ${logpath}/${docker_tag}.log - time docker build --network=host --progress=plain \ - --build-arg ALPINE_VERSION="$alpine" \ + + rm -f ${logpath}/"${docker_tag}".*.log + + time docker build --pull --network=host --progress=plain \ + -f $dockerfile \ + --build-arg "${base_os_upper}_VERSION=$base_tag" \ --build-arg BUILD_CC_COMPILER="$compiler" \ --build-arg PG_MAJOR="$pg_major" \ - --build-arg DOCKER_PG_LLVM_DEPS="$pg_llvm_deps" \ - -t orioletest:${docker_tag} . 2>&1 | tee ${logpath}/${docker_tag}.log + -t orioletest:"${docker_tag}" . 2>&1 | tee ${logpath}/"${docker_tag}".build.log + + # Run docker test : oriole + postgres official test scripts + "${OFFIMG_LOCAL_CLONE}/test/run.sh" \ + -c "${OFFIMG_LOCAL_CLONE}/test/config.sh" \ + -c "test/orioledb-config.sh" \ + "orioletest:${docker_tag}" 2>&1 | tee ${logpath}/"${docker_tag}".test.log done done done docker images orioletest:* | sort + +# You can check the build logs with: +# grep -i -C 1 warning: ./log_docker_build/*/*.build.log \ No newline at end of file diff --git a/test/docker_test.md b/test/docker_test.md new file mode 100644 index 00000000..17dcad5f --- /dev/null +++ b/test/docker_test.md @@ -0,0 +1,52 @@ + +# Official Postgres Docker Image test + +Running the Docker Official Image tests against orioledb images, +see: "Docker Official Images Test Suite": +* https://github.com/docker-library/official-images/tree/master/test + + +used by: +* `./ci/local_docker_matrix.sh` +* todo: add to Github CI + + +## Running docker test suite + +```bash +# clone official-images test suite +OFFIMG_LOCAL_CLONE=./log_docker_build/official-images +OFFIMG_REPO_URL=https://github.com/docker-library/official-images.git +mkdir -p "$OFFIMG_LOCAL_CLONE" +git clone "$OFFIMG_REPO_URL" "$OFFIMG_LOCAL_CLONE" + +"${OFFIMG_LOCAL_CLONE}/test/run.sh" \ + -c "${OFFIMG_LOCAL_CLONE}/test/config.sh" \ + -c "test/orioledb-config.sh" \ + "orioletest:16-gcc-ubuntu-22.04" +``` + +If the test is ok, you can see: + +```bash +testing orioletest:16-gcc-ubuntu-22.04 + 'utc' [1/6]...passed + 'no-hard-coded-passwords' [2/6]...passed + 'override-cmd' [3/6]...passed + 'postgres-basics' [4/6]....passed + 'postgres-initdb' [5/6]....passed + 'orioledb-basics' [6/6]...passed +``` + +## test: postgres-basics + +https://github.com/docker-library/official-images/blob/master/test/tests/postgres-basics/run.sh + +## test: postgres-initdb + +https://github.com/docker-library/official-images/blob/master/test/tests/postgres-initdb/run.sh +https://github.com/docker-library/official-images/blob/master/test/tests/postgres-initdb/initdb.sql + +## test: orioledb-basics + +* `./tests/orioledb-basics/run.sh` diff --git a/test/orioledb-config.sh b/test/orioledb-config.sh new file mode 100644 index 00000000..57bc0b7f --- /dev/null +++ b/test/orioledb-config.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034,SC2154 + +testAlias[orioletest]=postgres + +imageTests[orioletest]=' + orioledb-basics +' diff --git a/test/tests/orioledb-basics/run.sh b/test/tests/orioledb-basics/run.sh new file mode 100755 index 00000000..223a59d2 --- /dev/null +++ b/test/tests/orioledb-basics/run.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# shellcheck disable=SC2119,SC2120 +set -eo pipefail + +image="$1" + +export POSTGRES_USER='my cool orioledb user' +export POSTGRES_PASSWORD='my cool orioledb password' +export POSTGRES_DB='my cool orioledb database' + +cname="orioletest-container-$RANDOM-$RANDOM" +cid="$(docker run -d -e POSTGRES_USER -e POSTGRES_PASSWORD -e POSTGRES_DB --name "$cname" "$image")" +trap 'docker rm -vf "$cid" > /dev/null' EXIT + +psql() { + docker run --rm -i \ + --link "$cname":orioletest \ + --entrypoint psql \ + -e PGPASSWORD="$POSTGRES_PASSWORD" \ + "$image" \ + --host orioletest \ + --username "$POSTGRES_USER" \ + --dbname "$POSTGRES_DB" \ + --quiet --no-align --tuples-only \ + "$@" +} + +# Set default values for POSTGRES_TEST_TRIES and POSTGRES_TEST_SLEEP if they are not set. +# You can change the default value of POSTGRES_TEST_TRIES and the POSTGRES_TEST_SLEEP in the CI build settings. +# For special cases like Buildx/qemu tests, you may need to set POSTGRES_TEST_TRIES to 42. +: "${POSTGRES_TEST_TRIES:=15}" +: "${POSTGRES_TEST_SLEEP:=2}" +tries="$POSTGRES_TEST_TRIES" +while ! echo 'SELECT 1' | psql &>/dev/null; do + ((tries--)) + if [ $tries -le 0 ]; then + echo >&2 'postgres failed to accept connections in a reasonable amount of time!' + echo 'SELECT 1' | psql # to hopefully get a useful error message + false + fi + sleep "$POSTGRES_TEST_SLEEP" +done + + +# minimal OrioleDB test +psql <<'EOSQL' + + CREATE EXTENSION IF NOT EXISTS orioledb; + SELECT orioledb_commit_hash(); + CREATE TABLE o_test_generated ( + a int, + b int GENERATED ALWAYS AS (a * 2) STORED + ) USING orioledb; + INSERT INTO o_test_generated VALUES (1), (2); + SELECT * FROM o_test_generated; + +EOSQL + +echo "SELECT version();" | psql +echo "\dx" | psql