diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index e37e39b8..162de41d 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -10,26 +10,27 @@ jobs: build: runs-on: ubuntu-latest + env: + ORACLE_HOME: /opt/oracle/instantclient_23_26 + LD_LIBRARY_PATH: /opt/oracle/instantclient_23_26 steps: - - uses: actions/checkout@v4 - - name: Set up Ruby 3.1 + - uses: actions/checkout@v6 + - name: Set up Ruby 4.0 uses: ruby/setup-ruby@v1 with: - ruby-version: "3.1" - - name: Install required package + ruby-version: "4.0" + - name: Create symbolic link for libaio library compatibility run: | - sudo apt-get install alien + sudo ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1 - name: Download Oracle instant client run: | - wget -q https://download.oracle.com/otn_software/linux/instantclient/216000/oracle-instantclient-basic-21.6.0.0.0-1.x86_64.rpm - wget -q https://download.oracle.com/otn_software/linux/instantclient/216000/oracle-instantclient-sqlplus-21.6.0.0.0-1.x86_64.rpm - wget -q https://download.oracle.com/otn_software/linux/instantclient/216000/oracle-instantclient-devel-21.6.0.0.0-1.x86_64.rpm + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-basic-linux.x64-23.26.1.0.0.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-sdk-linux.x64-23.26.1.0.0.zip - name: Install Oracle instant client run: | - sudo alien -i oracle-instantclient-basic-21.6.0.0.0-1.x86_64.rpm - sudo alien -i oracle-instantclient-sqlplus-21.6.0.0.0-1.x86_64.rpm - sudo alien -i oracle-instantclient-devel-21.6.0.0.0-1.x86_64.rpm + sudo unzip -q instantclient-basic-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + sudo unzip -qo instantclient-sdk-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ - name: Build and run RuboCop run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0c1b393d..98e1e553 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,35 +7,32 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest continue-on-error: true strategy: matrix: ruby: [ + '4.0', + '3.4', + '3.3', '3.2', - '3.1', - '3.0', - '2.7', - '2.6', - '2.5', ruby-head, ruby-debug, truffleruby, truffleruby-head ] env: - ORACLE_HOME: /usr/lib/oracle/21/client64 - LD_LIBRARY_PATH: /usr/lib/oracle/21/client64/lib + ORACLE_HOME: /opt/oracle/instantclient_23_26 + LD_LIBRARY_PATH: /opt/oracle/instantclient_23_26 NLS_LANG: AMERICAN_AMERICA.AL32UTF8 TNS_ADMIN: ./ci/network/admin - DATABASE_NAME: XEPDB1 + DATABASE_NAME: FREEPDB1 TZ: Europe/Riga DATABASE_SYS_PASSWORD: Oracle18 - DATABASE_VERSION: 21.3.0.0 services: oracle: - image: gvenzl/oracle-xe:latest + image: gvenzl/oracle-free:latest ports: - 1521:1521 env: @@ -48,27 +45,28 @@ jobs: --health-retries 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - - name: Install required package + - name: Create symbolic link for libaio library compatibility run: | - sudo apt-get install alien - - name: Download Oracle client + sudo ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1 + - name: Download Oracle instant client run: | - wget -q https://download.oracle.com/otn_software/linux/instantclient/2110000/oracle-instantclient-basic-21.10.0.0.0-1.x86_64.rpm - wget -q https://download.oracle.com/otn_software/linux/instantclient/2110000/oracle-instantclient-sqlplus-21.10.0.0.0-1.x86_64.rpm - wget -q https://download.oracle.com/otn_software/linux/instantclient/2110000/oracle-instantclient-devel-21.10.0.0.0-1.x86_64.rpm - - name: Install Oracle client + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-basic-linux.x64-23.26.1.0.0.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-sdk-linux.x64-23.26.1.0.0.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-sqlplus-linux.x64-23.26.1.0.0.zip + - name: Install Oracle instant client run: | - sudo alien -i oracle-instantclient-basic-21.10.0.0.0-1.x86_64.rpm - sudo alien -i oracle-instantclient-sqlplus-21.10.0.0.0-1.x86_64.rpm - sudo alien -i oracle-instantclient-devel-21.10.0.0.0-1.x86_64.rpm + sudo unzip -q instantclient-basic-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + sudo unzip -qo instantclient-sdk-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + sudo unzip -qo instantclient-sqlplus-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + echo "/opt/oracle/instantclient_23_26" >> $GITHUB_PATH - name: Install JDBC Driver run: | - wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/211/ojdbc11.jar -O ./lib/ojdbc11.jar + wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar -O ./lib/ojdbc11.jar - name: Create database user run: | ./ci/setup_accounts.sh @@ -81,4 +79,4 @@ jobs: bundle install --jobs 4 --retry 3 - name: Run RSpec run: | - bundle exec rspec + RUBYOPT=-w bundle exec rspec diff --git a/.github/workflows/test_11g.yml b/.github/workflows/test_11g.yml new file mode 100644 index 00000000..21002e86 --- /dev/null +++ b/.github/workflows/test_11g.yml @@ -0,0 +1,96 @@ +name: test_11g + +on: + push: + pull_request: + +jobs: + build: + + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + ruby: [ + '4.0', + '3.4', + '3.3', + '3.2', + ruby-head, + ruby-debug, + truffleruby, + truffleruby-head + ] + env: + ORACLE_HOME: /opt/oracle/instantclient_21_15 + LD_LIBRARY_PATH: /opt/oracle/instantclient_21_15 + NLS_LANG: AMERICAN_AMERICA.AL32UTF8 + TNS_ADMIN: ./ci/network/admin + DATABASE_NAME: XE + TZ: Europe/Riga + DATABASE_SYS_PASSWORD: Oracle18 + + services: + oracle: + image: gvenzl/oracle-xe:11 + ports: + - 1521:1521 + env: + TZ: Europe/Riga + ORACLE_PASSWORD: Oracle18 + options: >- + --health-cmd healthcheck.sh + --health-interval 10s + --health-timeout 5s + --health-retries 10 + + steps: + - uses: actions/checkout@v6 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - name: Create symbolic link for libaio library compatibility + run: | + sudo ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1 + - name: Download Oracle instant client + run: | + wget -q https://download.oracle.com/otn_software/linux/instantclient/2115000/instantclient-basic-linux.x64-21.15.0.0.0dbru.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2115000/instantclient-sqlplus-linux.x64-21.15.0.0.0dbru.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2115000/instantclient-sdk-linux.x64-21.15.0.0.0dbru.zip + - name: Install Oracle instant client + run: | + sudo mkdir -p /opt/oracle/ + sudo unzip -q instantclient-basic-linux.x64-21.15.0.0.0dbru.zip -d /opt/oracle + sudo unzip -qo instantclient-sqlplus-linux.x64-21.15.0.0.0dbru.zip -d /opt/oracle + sudo unzip -qo instantclient-sdk-linux.x64-21.15.0.0.0dbru.zip -d /opt/oracle + echo "/opt/oracle/instantclient_21_15" >> $GITHUB_PATH + - name: Install JDBC Driver + run: | + wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar -O ./lib/ojdbc11.jar + - name: Configure ORA_TZFILE to match Oracle 11g server + run: | + # Oracle 11g XE uses timezone file v14; Instant Client 21.15 embeds v35. + # This mismatch causes ORA-01805 when ruby-oci8 fetches DATE/TIMESTAMP + # values. Copy the v14 files from the 11g container and point the + # Instant Client at them via ORA_TZFILE. + ORACLE_CONTAINER=$(docker ps --filter "ancestor=gvenzl/oracle-xe:11" -q) + sudo mkdir -p /opt/oracle/instantclient_21_15/oracore/zoneinfo + docker cp "$ORACLE_CONTAINER":/u01/app/oracle/product/11.2.0/xe/oracore/zoneinfo/timezlrg_14.dat /tmp/timezlrg_14.dat + docker cp "$ORACLE_CONTAINER":/u01/app/oracle/product/11.2.0/xe/oracore/zoneinfo/timezone_14.dat /tmp/timezone_14.dat + sudo mv /tmp/timezlrg_14.dat /opt/oracle/instantclient_21_15/oracore/zoneinfo/ + sudo mv /tmp/timezone_14.dat /opt/oracle/instantclient_21_15/oracore/zoneinfo/ + echo "ORA_TZFILE=timezlrg_14.dat" >> $GITHUB_ENV + - name: Create database user + run: | + ./ci/setup_accounts.sh + - name: Disable ActiveRecord for TruffleRuby + run: | + echo "NO_ACTIVERECORD=true" >> $GITHUB_ENV + if: "contains(matrix.ruby, 'truffleruby')" + - name: Bundle install + run: | + bundle install --jobs 4 --retry 3 + - name: Run RSpec + run: | + RUBYOPT=-w bundle exec rspec diff --git a/.github/workflows/test_gemfiles.yml b/.github/workflows/test_gemfiles.yml new file mode 100644 index 00000000..b37b575e --- /dev/null +++ b/.github/workflows/test_gemfiles.yml @@ -0,0 +1,92 @@ +name: test_gemfiles + +on: + push: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - gemfile: gemfiles/Gemfile.activerecord-5.0 + ruby: '2.4' + - gemfile: gemfiles/Gemfile.activerecord-5.1 + ruby: '2.4' + - gemfile: gemfiles/Gemfile.activerecord-5.2 + ruby: '2.4' + - gemfile: gemfiles/Gemfile.activerecord-6.0 + ruby: '2.5' + - gemfile: gemfiles/Gemfile.activerecord-6.1 + ruby: '2.5' + - gemfile: gemfiles/Gemfile.activerecord-7.0 + ruby: '2.7' + - gemfile: gemfiles/Gemfile.activerecord-7.1 + ruby: '2.7' + - gemfile: gemfiles/Gemfile.activerecord-7.2 + ruby: '3.1' + - gemfile: gemfiles/Gemfile.activerecord-8.0 + ruby: '3.2' + env: + BUNDLE_GEMFILE: ${{ matrix.gemfile }} + ORACLE_HOME: /opt/oracle/instantclient_23_26 + LD_LIBRARY_PATH: /opt/oracle/instantclient_23_26 + NLS_LANG: AMERICAN_AMERICA.AL32UTF8 + TNS_ADMIN: ./ci/network/admin + DATABASE_NAME: FREEPDB1 + TZ: Europe/Riga + DATABASE_SYS_PASSWORD: Oracle18 + + services: + oracle: + image: gvenzl/oracle-free:latest + ports: + - 1521:1521 + env: + TZ: Europe/Riga + ORACLE_PASSWORD: Oracle18 + options: >- + --health-cmd healthcheck.sh + --health-interval 10s + --health-timeout 5s + --health-retries 10 + + steps: + - uses: actions/checkout@v6 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - name: Create symbolic link for libaio library compatibility + run: | + sudo ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/x86_64-linux-gnu/libaio.so.1 + - name: Download Oracle instant client + run: | + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-basic-linux.x64-23.26.1.0.0.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-sdk-linux.x64-23.26.1.0.0.zip + wget -q https://download.oracle.com/otn_software/linux/instantclient/2326100/instantclient-sqlplus-linux.x64-23.26.1.0.0.zip + - name: Install Oracle instant client + run: | + sudo unzip -q instantclient-basic-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + sudo unzip -qo instantclient-sdk-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + sudo unzip -qo instantclient-sqlplus-linux.x64-23.26.1.0.0.zip -d /opt/oracle/ + echo "/opt/oracle/instantclient_23_26" >> $GITHUB_PATH + - name: Install JDBC Driver + run: | + wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar -O ./lib/ojdbc11.jar + - name: Create database user + run: | + ./ci/setup_accounts.sh + - name: Bundle install + run: | + bundle install --jobs 4 --retry 3 + - name: Run RSpec + run: | + RUBYOPT=-w bundle exec rspec diff --git a/.rubocop.yml b/.rubocop.yml index 03fed3f7..547fb3d1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,9 @@ -# rubocop 0.51.0 requires Ruby 2.1 -# We should not use cops only available for Ruby 2.1 or later -# since ruby-plsql itself supports Ruby 1.9.3 AllCops: - TargetRubyVersion: 2.3 + # Match the minimum Ruby exercised by the per-Rails matrix in + # .github/workflows/test_gemfiles.yml (AR 5.0-5.2 jobs run on Ruby 2.4) + # so RuboCop does not permit syntax/stdlib usage that would break + # those supported runtimes. + TargetRubyVersion: 2.4 DisabledByDefault: true # Prefer &&/|| over and/or. @@ -112,7 +113,7 @@ Style/StringLiterals: EnforcedStyle: double_quotes # Detect hard tabs, no hard tabs. -Layout/Tab: +Layout/IndentationStyle: Enabled: true # Blank lines should not have any spaces. @@ -132,7 +133,6 @@ Style/RedundantPercentQ: Layout/EndAlignment: Enabled: true EnforcedStyleAlignWith: variable - AutoCorrect: true # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg. Lint/RequireParentheses: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0a9a9583..00000000 --- a/.travis.yml +++ /dev/null @@ -1,105 +0,0 @@ -dist: focal -sudo: required - -jdk: - - openjdk8 -env: - global: - - ORACLE_COOKIE=sqldev - - ORACLE_FILE=oracle11g/xe/oracle-xe-11.2.0-1.0.x86_64.rpm.zip - - ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe - - NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - - ORACLE_BASE=/u01/app/oracle - - LD_LIBRARY_PATH=$ORACLE_HOME/lib - - PATH=$PATH:$ORACLE_HOME/jdbc/lib - - DATABASE_VERSION=11.2.0.2 - - ORACLE_SID=XE - - DATABASE_NAME=XE - - ORA_SDTZ='Europe/London' #Needed as a client parameter - - TZ='Europe/London' #Needed as a DB Server parameter - -before_install: - - chmod +x .travis/oracle/download.sh - - chmod +x .travis/oracle/install.sh - - chmod +x .travis/setup_accounts.sh - - 'gem install bundler || gem install bundler -v 1.17.3' - -install: - - .travis/oracle/download.sh - - .travis/oracle/install.sh - - .travis/setup_accounts.sh - - bundle install --without=development - -language: ruby -rvm: - - 3.2.2 - - 3.1.4 - - 3.0.6 - - 2.7.7 - - 2.6.10 - - 2.5.9 - - 2.4.10 - - 2.3.8 - - jruby-9.2.17.0 - - ruby-head - - jruby-head - -gemfile: - - Gemfile - - gemfiles/Gemfile.activerecord-5.0 - - gemfiles/Gemfile.activerecord-5.1 - - gemfiles/Gemfile.activerecord-5.2 - - gemfiles/Gemfile.activerecord-6.0 - - gemfiles/Gemfile.activerecord-6.1 - - gemfiles/Gemfile.activerecord-7.0 - - gemfiles/Gemfile.activerecord-main - -matrix: - exclude: - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: jruby-head - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: jruby-9.2.17.0 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.6.9 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.5.9 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.4.10 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.3.8 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.2.10 - - gemfile: gemfiles/Gemfile.activerecord-6.0 - rvm: 2.4.10 - - gemfile: gemfiles/Gemfile.activerecord-6.0 - rvm: 2.3.8 - - gemfile: gemfiles/Gemfile.activerecord-6.0 - rvm: 2.2.10 - - gemfile: gemfiles/Gemfile.activerecord-6.1 - rvm: 2.4.10 - - gemfile: gemfiles/Gemfile.activerecord-6.1 - rvm: 2.3.8 - - gemfile: gemfiles/Gemfile.activerecord-6.1 - rvm: 2.2.10 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: jruby-head - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: jruby-9.2.17.0 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: 2.6.9 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: 2.5.9 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: 2.4.10 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: 2.3.8 - - gemfile: gemfiles/Gemfile.activerecord-7.0 - rvm: 2.2.10 - allow_failures: - - rvm: ruby-head - - rvm: jruby-head - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 3.0.3 - - gemfile: gemfiles/Gemfile.activerecord-main - rvm: 2.7.5 diff --git a/.travis/oracle/download.sh b/.travis/oracle/download.sh deleted file mode 100755 index c7927005..00000000 --- a/.travis/oracle/download.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -cd "$(dirname "$(readlink -f "$0")")" - -deb_file=oracle-xe_11.2.0-1.0_amd64.deb - -git clone https://github.com/wnameless/docker-oracle-xe-11g.git - -cd docker-oracle-xe-11g/assets && - cat "${deb_file}aa" "${deb_file}ab" "${deb_file}ac" > "${deb_file}" - -pwd - -ls -lAh "${deb_file}" - diff --git a/.travis/oracle/install.sh b/.travis/oracle/install.sh deleted file mode 100755 index b4c7fef8..00000000 --- a/.travis/oracle/install.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -[ -n "$ORACLE_FILE" ] || { echo "Missing ORACLE_FILE environment variable!"; exit 1; } -[ -n "$ORACLE_HOME" ] || { echo "Missing ORACLE_HOME environment variable!"; exit 1; } - -cd "$(dirname "$(readlink -f "$0")")" - -ORACLE_DEB=docker-oracle-xe-11g/assets/oracle-xe_11.2.0-1.0_amd64.deb - -sudo apt-get -qq update -sudo apt-get --no-install-recommends -qq install bc libaio1 - -df -B1 /dev/shm | awk 'END { if ($1 != "shmfs" && $1 != "tmpfs" || $2 < 2147483648) exit 1 }' || - ( sudo rm -r /dev/shm && sudo mkdir /dev/shm && sudo mount -t tmpfs shmfs -o size=2G /dev/shm ) - -test -f /sbin/chkconfig || - ( echo '#!/bin/sh' | sudo tee /sbin/chkconfig > /dev/null && sudo chmod u+x /sbin/chkconfig ) - -test -d /var/lock/subsys || sudo mkdir /var/lock/subsys - -sudo dpkg -i "${ORACLE_DEB}" - -echo 'OS_AUTHENT_PREFIX=""' | sudo tee -a "$ORACLE_HOME/config/scripts/init.ora" > /dev/null -echo 'disk_asynch_io=false' | sudo tee -a "$ORACLE_HOME/config/scripts/init.ora" > /dev/null -sudo usermod -aG dba $USER - -( echo ; echo ; echo travis ; echo travis ; echo n ) | sudo AWK='/usr/bin/awk' /etc/init.d/oracle-xe configure - -"$ORACLE_HOME/bin/sqlplus" -L -S / AS SYSDBA < 2.0" gem "rspec_junit_formatter" - gem "rubocop", "0.81", require: false + gem "rubocop", require: false gem "rubocop-performance", require: false gem "rubocop-rails", require: false end @@ -13,12 +13,12 @@ group :test, :development do gem "rspec", "~> 3.1" unless ENV["NO_ACTIVERECORD"] - gem "activerecord", "~> 5.0" - gem "activerecord-oracle_enhanced-adapter", "~> 1.7" + gem "activerecord", "~> 8.0" + gem "activerecord-oracle_enhanced-adapter", "~> 8.0" gem "simplecov", ">= 0" end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem "ruby-oci8", "~> 2.1" end end diff --git a/ci/network/admin/tnsnames.ora b/ci/network/admin/tnsnames.ora index 91cd300e..d1ba8183 100644 --- a/ci/network/admin/tnsnames.ora +++ b/ci/network/admin/tnsnames.ora @@ -1,7 +1,15 @@ -XEPDB1 = +FREEPDB1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)) (CONNECT_DATA = - (SERVICE_NAME = XEPDB1) + (SERVICE_NAME = FREEPDB1) + ) + ) + +XE = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)) + (CONNECT_DATA = + (SERVICE_NAME = XE) ) ) diff --git a/ci/setup_accounts.sh b/ci/setup_accounts.sh index 9af72166..17f03159 100755 --- a/ci/setup_accounts.sh +++ b/ci/setup_accounts.sh @@ -2,7 +2,7 @@ set -ev -${ORACLE_HOME}/bin/sqlplus system/${DATABASE_SYS_PASSWORD}@${DATABASE_NAME} <= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-5.1 b/gemfiles/Gemfile.activerecord-5.1 index 64f6e464..640f2495 100644 --- a/gemfiles/Gemfile.activerecord-5.1 +++ b/gemfiles/Gemfile.activerecord-5.1 @@ -15,7 +15,7 @@ group :test, :development do gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-5.2 b/gemfiles/Gemfile.activerecord-5.2 index 346834bb..cc6e686a 100644 --- a/gemfiles/Gemfile.activerecord-5.2 +++ b/gemfiles/Gemfile.activerecord-5.2 @@ -10,12 +10,12 @@ group :test, :development do gem 'rspec', '~> 3.1' unless ENV['NO_ACTIVERECORD'] - gem 'activerecord', '~> 5.2.0.beta' - gem 'activerecord-oracle_enhanced-adapter', '~> 5.2.0.beta' + gem 'activerecord', '~> 5.2.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 5.2.0' gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-6.0 b/gemfiles/Gemfile.activerecord-6.0 index 67a6c88f..6e42d181 100644 --- a/gemfiles/Gemfile.activerecord-6.0 +++ b/gemfiles/Gemfile.activerecord-6.0 @@ -10,12 +10,12 @@ group :test, :development do gem 'rspec', '~> 3.1' unless ENV['NO_ACTIVERECORD'] - gem 'activerecord', '~> 6.0.0.rc1' - gem 'activerecord-oracle_enhanced-adapter', '~>6.0.0.rc1' + gem 'activerecord', '~> 6.0.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 6.0.0' gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-6.1 b/gemfiles/Gemfile.activerecord-6.1 index 4565f578..5370bfc4 100644 --- a/gemfiles/Gemfile.activerecord-6.1 +++ b/gemfiles/Gemfile.activerecord-6.1 @@ -11,11 +11,11 @@ group :test, :development do unless ENV['NO_ACTIVERECORD'] gem 'activerecord', '~> 6.1.0' - gem 'activerecord-oracle_enhanced-adapter', '~>6.1.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 6.1.0' gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-7.0 b/gemfiles/Gemfile.activerecord-7.0 index 0879987c..e954e527 100644 --- a/gemfiles/Gemfile.activerecord-7.0 +++ b/gemfiles/Gemfile.activerecord-7.0 @@ -15,7 +15,7 @@ group :test, :development do gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/gemfiles/Gemfile.activerecord-7.1 b/gemfiles/Gemfile.activerecord-7.1 new file mode 100644 index 00000000..26a1aab8 --- /dev/null +++ b/gemfiles/Gemfile.activerecord-7.1 @@ -0,0 +1,21 @@ +source 'http://rubygems.org' + +group :development do + gem 'juwelier', '~> 2.0' + gem 'rspec_junit_formatter' +end + +group :test, :development do + gem 'rake', '>= 10.0' + gem 'rspec', '~> 3.1' + + unless ENV['NO_ACTIVERECORD'] + gem 'activerecord', '~> 7.1.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 7.1.0' + gem 'simplecov', '>= 0' + end + + platforms :ruby, :windows do + gem 'ruby-oci8', '~> 2.1' + end +end diff --git a/gemfiles/Gemfile.activerecord-7.2 b/gemfiles/Gemfile.activerecord-7.2 new file mode 100644 index 00000000..12925d42 --- /dev/null +++ b/gemfiles/Gemfile.activerecord-7.2 @@ -0,0 +1,21 @@ +source 'http://rubygems.org' + +group :development do + gem 'juwelier', '~> 2.0' + gem 'rspec_junit_formatter' +end + +group :test, :development do + gem 'rake', '>= 10.0' + gem 'rspec', '~> 3.1' + + unless ENV['NO_ACTIVERECORD'] + gem 'activerecord', '~> 7.2.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 7.2.0' + gem 'simplecov', '>= 0' + end + + platforms :ruby, :windows do + gem 'ruby-oci8', '~> 2.1' + end +end diff --git a/gemfiles/Gemfile.activerecord-8.0 b/gemfiles/Gemfile.activerecord-8.0 new file mode 100644 index 00000000..87745340 --- /dev/null +++ b/gemfiles/Gemfile.activerecord-8.0 @@ -0,0 +1,21 @@ +source 'http://rubygems.org' + +group :development do + gem 'juwelier', '~> 2.0' + gem 'rspec_junit_formatter' +end + +group :test, :development do + gem 'rake', '>= 10.0' + gem 'rspec', '~> 3.1' + + unless ENV['NO_ACTIVERECORD'] + gem 'activerecord', '~> 8.0.0' + gem 'activerecord-oracle_enhanced-adapter', '~> 8.0.0' + gem 'simplecov', '>= 0' + end + + platforms :ruby, :windows do + gem 'ruby-oci8', '~> 2.1' + end +end diff --git a/gemfiles/Gemfile.activerecord-main b/gemfiles/Gemfile.activerecord-main index 086b3fc5..1fcbb691 100644 --- a/gemfiles/Gemfile.activerecord-main +++ b/gemfiles/Gemfile.activerecord-main @@ -15,7 +15,7 @@ group :test, :development do gem 'simplecov', '>= 0' end - platforms :ruby, :mswin, :mingw do + platforms :ruby, :windows do gem 'ruby-oci8', '~> 2.1' end end diff --git a/lib/plsql/connection.rb b/lib/plsql/connection.rb index 39ec3507..2f41190e 100644 --- a/lib/plsql/connection.rb +++ b/lib/plsql/connection.rb @@ -3,13 +3,13 @@ class Connection attr_reader :raw_driver attr_reader :activerecord_class - def initialize(raw_conn, ar_class = nil) #:nodoc: + def initialize(raw_conn, ar_class = nil) # :nodoc: @raw_driver = self.class.driver_type @raw_connection = raw_conn @activerecord_class = ar_class end - def self.create(raw_conn, ar_class = nil) #:nodoc: + def self.create(raw_conn, ar_class = nil) # :nodoc: if ar_class && !(defined?(::ActiveRecord) && ar_class.ancestors.include?(::ActiveRecord::Base)) raise ArgumentError, "Wrong ActiveRecord class" end @@ -23,7 +23,7 @@ def self.create(raw_conn, ar_class = nil) #:nodoc: end end - def self.create_new(params) #:nodoc: + def self.create_new(params) # :nodoc: conn = case driver_type when :oci OCIConnection.create_raw(params) @@ -36,7 +36,7 @@ def self.create_new(params) #:nodoc: conn end - def self.driver_type #:nodoc: + def self.driver_type # :nodoc: # MRI 1.8.6 or YARV 1.9.1 or TruffleRuby @driver_type ||= if (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby") && defined?(OCI8) :oci @@ -67,18 +67,18 @@ def jdbc? @raw_driver == :jdbc end - def logoff #:nodoc: + def logoff # :nodoc: # Rollback any uncommited transactions rollback # Common cleanup activities before logoff, should be called from particular driver method drop_session_ruby_temporary_tables end - def commit #:nodoc: + def commit # :nodoc: raise NoMethodError, "Not implemented for this raw driver" end - def rollback #:nodoc: + def rollback # :nodoc: raise NoMethodError, "Not implemented for this raw driver" end @@ -98,21 +98,21 @@ def prefetch_rows=(value) raise NoMethodError, "Not implemented for this raw driver" end - def select_first(sql, *bindvars) #:nodoc: + def select_first(sql, *bindvars) # :nodoc: cursor = cursor_from_query(sql, bindvars, prefetch_rows: 1) cursor.fetch ensure cursor.close rescue nil end - def select_hash_first(sql, *bindvars) #:nodoc: + def select_hash_first(sql, *bindvars) # :nodoc: cursor = cursor_from_query(sql, bindvars, prefetch_rows: 1) cursor.fetch_hash ensure cursor.close rescue nil end - def select_all(sql, *bindvars, &block) #:nodoc: + def select_all(sql, *bindvars, &block) # :nodoc: cursor = cursor_from_query(sql, bindvars) results = [] row_count = 0 @@ -129,7 +129,7 @@ def select_all(sql, *bindvars, &block) #:nodoc: cursor.close rescue nil end - def select_hash_all(sql, *bindvars, &block) #:nodoc: + def select_hash_all(sql, *bindvars, &block) # :nodoc: cursor = cursor_from_query(sql, bindvars) results = [] row_count = 0 @@ -146,11 +146,11 @@ def select_hash_all(sql, *bindvars, &block) #:nodoc: cursor.close rescue nil end - def exec(sql, *bindvars) #:nodoc: + def exec(sql, *bindvars) # :nodoc: raise NoMethodError, "Not implemented for this raw driver" end - def parse(sql) #:nodoc: + def parse(sql) # :nodoc: raise NoMethodError, "Not implemented for this raw driver" end @@ -181,7 +181,7 @@ def fetch_hash # all_synonyms view is quite slow therefore # this implementation is overriden in OCI connection with faster native OCI method - def describe_synonym(schema_name, synonym_name) #:nodoc: + def describe_synonym(schema_name, synonym_name) # :nodoc: select_first( "SELECT table_owner, table_name FROM all_synonyms WHERE owner = :owner AND synonym_name = :synonym_name", schema_name.to_s.upcase, synonym_name.to_s.upcase) diff --git a/lib/plsql/helpers.rb b/lib/plsql/helpers.rb index b144585d..86c83c83 100644 --- a/lib/plsql/helpers.rb +++ b/lib/plsql/helpers.rb @@ -1,6 +1,6 @@ -module PLSQL #:nodoc: - module ArrayHelpers #:nodoc: - def self.to_hash(keys, values) #:nodoc: +module PLSQL # :nodoc: + module ArrayHelpers # :nodoc: + def self.to_hash(keys, values) # :nodoc: (0...keys.size).inject({}) { |hash, i| hash[keys[i]] = values[i]; hash } end end diff --git a/lib/plsql/jdbc_connection.rb b/lib/plsql/jdbc_connection.rb index 3b9e1278..9f479a80 100644 --- a/lib/plsql/jdbc_connection.rb +++ b/lib/plsql/jdbc_connection.rb @@ -46,7 +46,7 @@ end module PLSQL - class JDBCConnection < Connection #:nodoc: + class JDBCConnection < Connection # :nodoc: def self.create_raw(params) database = params[:database] url = if ENV["TNS_ADMIN"] && database && !params[:host] && !params[:url] @@ -98,7 +98,7 @@ def exec(sql, *bindvars) cs.close rescue nil end - class CallableStatement #:nodoc: + class CallableStatement # :nodoc: def initialize(conn, sql) @sql = sql @connection = conn @@ -145,7 +145,7 @@ def bind_param_index(key) end end - class Cursor #:nodoc: + class Cursor # :nodoc: include Connection::CursorCommon attr_reader :result_set diff --git a/lib/plsql/oci_connection.rb b/lib/plsql/oci_connection.rb index caf783e6..ca5e9bee 100644 --- a/lib/plsql/oci_connection.rb +++ b/lib/plsql/oci_connection.rb @@ -24,7 +24,7 @@ end module PLSQL - class OCIConnection < Connection #:nodoc: + class OCIConnection < Connection # :nodoc: def self.create_raw(params) connection_string = if params[:host] "//#{params[:host]}:#{params[:port] || 1521}/#{params[:database]}" @@ -64,7 +64,7 @@ def exec(sql, *bindvars) true end - class Cursor #:nodoc: + class Cursor # :nodoc: include Connection::CursorCommon attr_reader :raw_cursor @@ -157,7 +157,7 @@ def plsql_to_ruby_data_type(metadata) [DateTime, nil] when "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE" [Time, nil] - when "TABLE", "VARRAY", "OBJECT", "XMLTYPE" + when "TABLE", "VARRAY", "OBJECT", "XMLTYPE", "OPAQUE/XMLTYPE" # create Ruby class for collection klass = OCI8::Object::Base.get_class_by_typename(metadata[:sql_type_name]) unless klass diff --git a/lib/plsql/package.rb b/lib/plsql/package.rb index 1cdd0f3f..406f6451 100644 --- a/lib/plsql/package.rb +++ b/lib/plsql/package.rb @@ -1,5 +1,5 @@ module PLSQL - module PackageClassMethods #:nodoc: + module PackageClassMethods # :nodoc: def find(schema, package) package_name = package.to_s.upcase find_in_schema(schema, package_name) || find_by_synonym(schema, package_name) @@ -32,7 +32,7 @@ def find_by_synonym(schema, package_name) end end - class Package #:nodoc: + class Package # :nodoc: extend PackageClassMethods def initialize(schema, package, override_schema_name = nil) @@ -56,7 +56,7 @@ def [](object_name) private def method_missing(method, *args, &block) - method = method.to_s + method = +method.to_s method.chop! if (assignment = method[/=$/]) case (object = self[method]) diff --git a/lib/plsql/procedure.rb b/lib/plsql/procedure.rb index 885ea0bc..a56fb8ab 100644 --- a/lib/plsql/procedure.rb +++ b/lib/plsql/procedure.rb @@ -1,5 +1,5 @@ module PLSQL - module ProcedureClassMethods #:nodoc: + module ProcedureClassMethods # :nodoc: def find(schema, procedure, package = nil, override_schema_name = nil) if package.nil? if (row = schema.select_first( @@ -53,12 +53,12 @@ def procedure_object_id_src(schema) end end - module ProcedureCommon #:nodoc: + module ProcedureCommon # :nodoc: attr_reader :arguments, :argument_list, :out_list, :return attr_reader :schema, :schema_name, :package, :procedure # return type string from metadata that can be used in DECLARE block or table definition - def self.type_to_sql(metadata) #:nodoc: + def self.type_to_sql(metadata) # :nodoc: case metadata[:data_type] when "NUMBER" precision, scale = metadata[:data_precision], metadata[:data_scale] @@ -82,7 +82,7 @@ def self.type_to_sql(metadata) #:nodoc: end # get procedure argument metadata from data dictionary - def get_argument_metadata #:nodoc: + def get_argument_metadata # :nodoc: if (@schema.connection.database_version <=> [18, 0, 0, 0]) >= 0 get_argument_metadata_from_18c else @@ -90,7 +90,7 @@ def get_argument_metadata #:nodoc: end end - def get_argument_metadata_below_18c #:nodoc: + def get_argument_metadata_below_18c # :nodoc: @arguments = {} @argument_list = {} @out_list = {} @@ -126,6 +126,9 @@ def get_argument_metadata_below_18c #:nodoc: data_type, in_out, data_length, data_precision, data_scale, char_used, char_length, type_owner, type_name, type_subname, defaulted = r + # Oracle 23c reports BOOLEAN as "BOOLEAN" instead of "PL/SQL BOOLEAN" + data_type = "PL/SQL BOOLEAN" if data_type == "BOOLEAN" + @overloaded ||= !overload.nil? # if not overloaded then store arguments at key 0 overload ||= 0 @@ -206,7 +209,7 @@ def get_argument_metadata_below_18c #:nodoc: end # get procedure argument metadata from data dictionary - def get_argument_metadata_from_18c #:nodoc: + def get_argument_metadata_from_18c # :nodoc: @arguments = {} @argument_list = {} @out_list = {} @@ -235,6 +238,9 @@ def get_argument_metadata_from_18c #:nodoc: data_type, in_out, data_length, data_precision, data_scale, char_used, char_length, type_owner, type_name, type_package, type_object_type, defaulted = r + # Oracle 23c reports BOOLEAN as "BOOLEAN" instead of "PL/SQL BOOLEAN" + data_type = "PL/SQL BOOLEAN" if data_type == "BOOLEAN" + @overloaded ||= !overload.nil? # if not overloaded then store arguments at key 0 overload ||= 0 @@ -298,7 +304,7 @@ def get_argument_metadata_from_18c #:nodoc: construct_argument_list_for_overloads end - def construct_argument_list_for_overloads #:nodoc: + def construct_argument_list_for_overloads # :nodoc: @overloads = @arguments.keys.sort @overloads.each do |overload| @argument_list[overload] = @arguments[overload].keys.sort { |k1, k2| @arguments[overload][k1][:position] <=> @arguments[overload][k2][:position] } @@ -306,10 +312,10 @@ def construct_argument_list_for_overloads #:nodoc: end end - def ensure_tmp_tables_created(overload) #:nodoc: + def ensure_tmp_tables_created(overload) # :nodoc: return if @tmp_tables_created.nil? || @tmp_tables_created[overload] @tmp_table_names[overload] && @tmp_table_names[overload].each do |table_name, argument_metadata| - sql = "CREATE GLOBAL TEMPORARY TABLE #{table_name} (\n" + sql = +"CREATE GLOBAL TEMPORARY TABLE #{table_name} (\n" element_metadata = argument_metadata[:element] case element_metadata[:data_type] when "PL/SQL RECORD" @@ -330,7 +336,7 @@ def ensure_tmp_tables_created(overload) #:nodoc: @tmp_tables_created[overload] = true end - def build_sql_type_name(type_owner, type_package, type_name) #:nodoc: + def build_sql_type_name(type_owner, type_package, type_name) # :nodoc: if type_owner == nil || type_owner == "PUBLIC" type_owner_res = "" else @@ -345,7 +351,7 @@ def build_sql_type_name(type_owner, type_package, type_name) #:nodoc: type_name_res && "#{type_owner_res}#{type_name_res}" end - def get_field_definitions(argument_metadata) #:nodoc: + def get_field_definitions(argument_metadata) # :nodoc: fields = {} case argument_metadata[:type_object_type] when "PACKAGE" @@ -359,6 +365,9 @@ def get_field_definitions(argument_metadata) #:nodoc: attr_no, attr_name, attr_type_owner, attr_type_name, attr_type_package, attr_length, attr_precision, attr_scale, attr_char_used = r + # Oracle 23c reports BOOLEAN as "BOOLEAN" instead of "PL/SQL BOOLEAN" + attr_type_name = "PL/SQL BOOLEAN" if attr_type_name == "BOOLEAN" + fields[attr_name.downcase.to_sym] = { position: attr_no.to_i, data_type: attr_type_owner == nil ? attr_type_name : get_composite_type(attr_type_owner, attr_type_name, attr_type_package), @@ -408,7 +417,7 @@ def get_field_definitions(argument_metadata) #:nodoc: fields end - def get_element_definition(argument_metadata) #:nodoc: + def get_element_definition(argument_metadata) # :nodoc: element_metadata = {} if collection_type?(argument_metadata[:data_type]) case argument_metadata[:type_object_type] @@ -421,6 +430,9 @@ def get_element_definition(argument_metadata) #:nodoc: elem_type_owner, elem_type_name, elem_type_package, elem_length, elem_precision, elem_scale, elem_char_used, index_by = r + # Oracle 23c reports BOOLEAN as "BOOLEAN" instead of "PL/SQL BOOLEAN" + elem_type_name = "PL/SQL BOOLEAN" if elem_type_name == "BOOLEAN" + if index_by == "VARCHAR2" raise ArgumentError, "Index-by Varchar-Table (associative array) #{argument_metadata[:type_name]} is not supported" end @@ -458,6 +470,9 @@ def get_element_definition(argument_metadata) #:nodoc: ) elem_type_owner, elem_type_name, elem_length, elem_precision, elem_scale, elem_char_used = r + # Oracle 23c reports BOOLEAN as "BOOLEAN" instead of "PL/SQL BOOLEAN" + elem_type_name = "PL/SQL BOOLEAN" if elem_type_name == "BOOLEAN" + element_metadata = { position: 1, data_type: elem_type_owner == nil ? elem_type_name : "OBJECT", @@ -510,21 +525,21 @@ def get_composite_type(type_owner, type_name, type_package) end PLSQL_COMPOSITE_TYPES = ["PL/SQL RECORD", "PL/SQL TABLE", "TABLE", "VARRAY", "REF CURSOR"].freeze - def composite_type?(data_type) #:nodoc: + def composite_type?(data_type) # :nodoc: PLSQL_COMPOSITE_TYPES.include? data_type end PLSQL_COLLECTION_TYPES = ["PL/SQL TABLE", "TABLE", "VARRAY"].freeze - def collection_type?(data_type) #:nodoc: + def collection_type?(data_type) # :nodoc: PLSQL_COLLECTION_TYPES.include? data_type end - def overloaded? #:nodoc: + def overloaded? # :nodoc: @overloaded end end - class Procedure #:nodoc: + class Procedure # :nodoc: extend ProcedureClassMethods include ProcedureCommon diff --git a/lib/plsql/procedure_call.rb b/lib/plsql/procedure_call.rb index 014138df..8ff30641 100644 --- a/lib/plsql/procedure_call.rb +++ b/lib/plsql/procedure_call.rb @@ -1,5 +1,5 @@ module PLSQL - class ProcedureCall #:nodoc: + class ProcedureCall # :nodoc: def initialize(procedure, args = [], options = {}) @procedure = procedure @schema = @procedure.schema @@ -115,7 +115,7 @@ def get_overload_from_arguments_list(args) MATCHING_TYPES = { integer: ["NUMBER", "NATURAL", "NATURALN", "POSITIVE", "POSITIVEN", "SIGNTYPE", "SIMPLE_INTEGER", "PLS_INTEGER", "BINARY_INTEGER"], decimal: ["NUMBER", "BINARY_FLOAT", "BINARY_DOUBLE"], - string: ["VARCHAR", "VARCHAR2", "NVARCHAR2", "CHAR", "NCHAR", "CLOB", "BLOB", "XMLTYPE"], + string: ["VARCHAR", "VARCHAR2", "NVARCHAR2", "CHAR", "NCHAR", "CLOB", "BLOB", "XMLTYPE", "OPAQUE/XMLTYPE"], date: ["DATE"], time: ["DATE", "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE"], boolean: ["PL/SQL BOOLEAN"], @@ -149,10 +149,10 @@ def matching_oracle_types_for_ruby_value(value) end def construct_sql(args) - @declare_sql = "" - @assignment_sql = "" - @call_sql = "" - @return_sql = "" + @declare_sql = +"" + @assignment_sql = +"" + @call_sql = +"" + @return_sql = +"" @return_vars = [] @return_vars_metadata = {} @@ -218,7 +218,7 @@ def construct_sql(args) end add_out_variables - @sql = @declare_sql.empty? ? "" : "DECLARE\n" << @declare_sql + @sql = @declare_sql.empty? ? +"" : +"DECLARE\n" << @declare_sql @sql << "BEGIN\n" << @assignment_sql << dbms_output_enable_sql << @call_sql << @return_sql << "END;\n" end @@ -240,8 +240,8 @@ def add_argument(argument, value, argument_metadata = nil) @bind_values[argument] = value.nil? ? nil : (value ? 1 : 0) @bind_metadata[argument] = argument_metadata.merge(data_type: "NUMBER", data_precision: 1) "l_#{argument}" - when "UNDEFINED" - if argument_metadata[:type_name] == "XMLTYPE" + when "UNDEFINED", "XMLTYPE", "OPAQUE/XMLTYPE" + if argument_metadata[:type_name] == "XMLTYPE" || argument_metadata[:data_type] =~ /XMLTYPE/ @declare_sql << "l_#{argument} XMLTYPE;\n" @assignment_sql << "l_#{argument} := XMLTYPE(:#{argument});\n" if not value.nil? @bind_values[argument] = value if not value.nil? @@ -326,7 +326,7 @@ def add_record_declaration(argument, argument_metadata) "l_#{argument} #{argument_metadata[:sql_type_name]};\n" else fields_metadata = argument_metadata[:fields] - sql = "TYPE t_#{argument} IS RECORD (\n" + sql = +"TYPE t_#{argument} IS RECORD (\n" sql << record_fields_sorted_by_position(fields_metadata).map do |field| metadata = fields_metadata[field] "#{field} #{type_to_sql(metadata)}" @@ -341,7 +341,7 @@ def record_fields_sorted_by_position(fields_metadata) end def record_assignment_sql_values_metadata(argument, argument_metadata, record_value) - sql = "" + sql = +"" bind_values = {} bind_metadata = {} (record_value || {}).each do |key, value| @@ -395,8 +395,8 @@ def add_return_variable(argument, argument_metadata, is_return_value = false) end end "l_#{argument} := " if is_return_value - when "UNDEFINED" - if argument_metadata[:type_name] == "XMLTYPE" + when "UNDEFINED", "XMLTYPE", "OPAQUE/XMLTYPE" + if argument_metadata[:type_name] == "XMLTYPE" || argument_metadata[:data_type] =~ /XMLTYPE/ @declare_sql << "l_#{argument} XMLTYPE;\n" if is_return_value bind_variable = :"o_#{argument}" @return_vars << bind_variable @@ -517,8 +517,8 @@ def return_variable_value(argument, argument_metadata) when "PL/SQL BOOLEAN" numeric_value = @cursor[":o_#{argument}"] numeric_value.nil? ? nil : numeric_value == 1 - when "UNDEFINED" - if argument_metadata[:type_name] == "XMLTYPE" + when "UNDEFINED", "XMLTYPE", "OPAQUE/XMLTYPE" + if argument_metadata[:type_name] == "XMLTYPE" || argument_metadata[:data_type] =~ /XMLTYPE/ @cursor[":o_#{argument}"] end else diff --git a/lib/plsql/schema.rb b/lib/plsql/schema.rb index f6a5bf31..4dfc1274 100644 --- a/lib/plsql/schema.rb +++ b/lib/plsql/schema.rb @@ -4,8 +4,8 @@ class Schema @@schemas = {} - class <= 12") - skip "Skip until furtuer investigation for #114" if @oracle12c_or_higher plsql.execute <<-SQL CREATE OR REPLACE FUNCTION test_xmltype ( p_xml XMLTYPE ) @@ -261,8 +258,8 @@ end after(:all) do - plsql.execute "DROP FUNCTION test_xmltype" unless @oracle12c_or_higher - plsql.execute "DROP PROCEDURE test_xmltype2" unless @oracle12c_or_higher + plsql.execute "DROP FUNCTION test_xmltype" rescue nil + plsql.execute "DROP PROCEDURE test_xmltype2" rescue nil plsql.logoff end @@ -1966,7 +1963,7 @@ def new_candidate(status) @fields = [:col1, :col2 ] @rows = (1..3).map { |i| ["row #{i}", i] } - plsql.typed_ref_cursor_table.insert_values *@rows + plsql.typed_ref_cursor_table.insert_values(*@rows) plsql.commit end diff --git a/spec/plsql/schema_spec.rb b/spec/plsql/schema_spec.rb index 7966529d..0662882b 100644 --- a/spec/plsql/schema_spec.rb +++ b/spec/plsql/schema_spec.rb @@ -209,8 +209,12 @@ class TestModel < TestBaseModel expect(plsql.schema_name).to eq("HR") end - it "should use ActiveRecord::Base.default_timezone as default" do - ActiveRecord::Base.default_timezone = :utc + it "should use ActiveRecord default_timezone as default" do + if ActiveRecord.respond_to?(:default_timezone=) + ActiveRecord.default_timezone = :utc + else + ActiveRecord::Base.default_timezone = :utc + end expect(plsql.default_timezone).to eq(:utc) end @@ -300,7 +304,7 @@ class TestModel < TestBaseModel end it "should log output to specified stream in case of exception" do - expect { plsql.test_dbms_output("test_dbms_output", true) }.to raise_error /Test Error/ + expect { plsql.test_dbms_output("test_dbms_output", true) }.to raise_error(/Test Error/) expect(@buffer.string).to eq("DBMS_OUTPUT: test_dbms_output\n") end diff --git a/spec/plsql/table_spec.rb b/spec/plsql/table_spec.rb index 0a68fd3a..9e8c952a 100644 --- a/spec/plsql/table_spec.rb +++ b/spec/plsql/table_spec.rb @@ -239,7 +239,7 @@ end it "should insert many records with array of values" do - plsql.test_employees.insert_values *@employees_all_values + plsql.test_employees.insert_values(*@employees_all_values) expect(plsql.test_employees.all).to eq(@employees) end @@ -332,7 +332,7 @@ plsql.test_employees.update first_name: "Test", where: "employee_id = #{employee_id}" expect(plsql.test_employees.first(employee_id: employee_id)[:first_name]).to eq("Test") # all other records should not be changed - plsql.test_employees.all("WHERE employee_id > :1", employee_id) do |employee| + plsql.test_employees.all("WHERE employee_id > :1", employee_id).each do |employee| expect(employee[:first_name]).not_to eq("Test") end end @@ -340,7 +340,7 @@ it "should update all records in table" do plsql.test_employees.insert @employees plsql.test_employees.update first_name: "Test" - plsql.test_employees.all do |employee| + plsql.test_employees.all.each do |employee| expect(employee[:first_name]).to eq("Test") end end diff --git a/spec/plsql/view_spec.rb b/spec/plsql/view_spec.rb index 9f5a59b2..6d6df830 100644 --- a/spec/plsql/view_spec.rb +++ b/spec/plsql/view_spec.rb @@ -157,7 +157,7 @@ end it "should insert many records with array of values" do - plsql.test_employees_v.insert_values *@employees_all_values + plsql.test_employees_v.insert_values(*@employees_all_values) expect(plsql.test_employees_v.all).to eq(@employees) end @@ -230,7 +230,7 @@ plsql.test_employees_v.update first_name: "Test", where: "employee_id = #{employee_id}" expect(plsql.test_employees_v.first(employee_id: employee_id)[:first_name]).to eq("Test") # all other records should not be changed - plsql.test_employees_v.all("WHERE employee_id > :1", employee_id) do |employee| + plsql.test_employees_v.all("WHERE employee_id > :1", employee_id).each do |employee| expect(employee[:first_name]).not_to eq("Test") end end @@ -238,7 +238,7 @@ it "should update all records in view" do plsql.test_employees_v.insert @employees plsql.test_employees_v.update first_name: "Test" - plsql.test_employees_v.all do |employee| + plsql.test_employees_v.all.each do |employee| expect(employee[:first_name]).to eq("Test") end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3da16b8f..5b33c327 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -19,7 +19,16 @@ require "rspec" unless ENV["NO_ACTIVERECORD"] + require "logger" require "active_record" + require "active_record/connection_adapters/oracle_enhanced_adapter" + if ActiveRecord::ConnectionAdapters.respond_to?(:register) + ActiveRecord::ConnectionAdapters.register( + "oracle_enhanced", + "ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter", + "active_record/connection_adapters/oracle_enhanced_adapter" + ) + end else puts "Without ActiveRecord" end @@ -44,19 +53,10 @@ [ENV["DATABASE_USER"] || "hr", ENV["DATABASE_PASSWORD"] || "hr"], [ENV["DATABASE_USER2"] || "arunit", ENV["DATABASE_PASSWORD2"] || "arunit"] ] -# specify which database version is used (will be verified in one test) -DATABASE_VERSION = ENV["DATABASE_VERSION"] || "10.2.0.4" - if ENV["USE_VM_DATABASE"] == "Y" RSpec.configure do |config| config.before(:suite) do TestDb.build - - # Set Verbose off to hide warning: already initialized constant DATABASE_VERSION - original_verbosity = $VERBOSE - $VERBOSE = nil - DATABASE_VERSION = TestDb.database_version - $VERBOSE = original_verbosity end end end