Skip to content
Merged
9 changes: 7 additions & 2 deletions .github/workflows/jruby_head.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
build:

runs-on: ubuntu-latest
continue-on-error: true
continue-on-error: false
strategy:
matrix:
ruby: [
Expand Down Expand Up @@ -39,6 +39,11 @@ jobs:

steps:
- uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: '21'
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand All @@ -57,7 +62,7 @@ jobs:
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
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/23261/ojdbc17.jar -O ./lib/ojdbc17.jar
Comment thread
yahonda marked this conversation as resolved.
Comment thread
yahonda marked this conversation as resolved.
- name: Create database user
run: |
./ci/setup_accounts.sh
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ jobs:
build:

runs-on: ubuntu-latest
continue-on-error: true
continue-on-error: false
strategy:
matrix:
ruby: [
'4.0',
'3.4',
'3.3',
'3.2'
'3.2',
'jruby-10.0.5.0',
]
env:
ORACLE_HOME: /opt/oracle/instantclient_23_26
Expand All @@ -42,6 +43,12 @@ jobs:

steps:
- uses: actions/checkout@v6
- name: Set up Java
if: startsWith(matrix.ruby, 'jruby')
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: '21'
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand All @@ -61,8 +68,9 @@ jobs:
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
Comment thread
yahonda marked this conversation as resolved.
if: startsWith(matrix.ruby, 'jruby')
run: |
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar -O ./lib/ojdbc11.jar
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/23261/ojdbc17.jar -O ./lib/ojdbc17.jar
- name: Create database user
run: |
./ci/setup_accounts.sh
Expand Down
26 changes: 17 additions & 9 deletions .github/workflows/test_11g.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ jobs:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft

runs-on: ubuntu-latest
continue-on-error: true
continue-on-error: false
strategy:
matrix:
ruby: [
'4.0',
'3.4',
'3.3',
'3.2'
'3.2',
'jruby-10.0.5.0',
]
env:
ORACLE_HOME: /opt/oracle/instantclient_21_15
Expand All @@ -46,6 +47,12 @@ jobs:

steps:
- uses: actions/checkout@v6
- name: Set up Java
if: startsWith(matrix.ruby, 'jruby')
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: '21'
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand All @@ -66,20 +73,21 @@ jobs:
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
if: startsWith(matrix.ruby, 'jruby')
run: |
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar -O ./lib/ojdbc11.jar
wget -q https://download.oracle.com/otn-pub/otn_software/jdbc/23261/ojdbc17.jar -O ./lib/ojdbc17.jar
Comment thread
yahonda marked this conversation as resolved.
- 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
# Oracle 11g XE uses timezone file v14; Instant Client 21.15 embeds
# v35. This mismatch causes ORA-01805 when fetching 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
ORACLE_CONTAINER="${{ job.services.oracle.id }}"
sudo mkdir -p "$ORACLE_HOME/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/
sudo mv /tmp/timezlrg_14.dat "$ORACLE_HOME/oracore/zoneinfo/"
sudo mv /tmp/timezone_14.dat "$ORACLE_HOME/oracore/zoneinfo/"
echo "ORA_TZFILE=timezlrg_14.dat" >> $GITHUB_ENV
- name: Create database user
run: |
Expand Down
94 changes: 94 additions & 0 deletions .github/workflows/test_11g_ojdbc11.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: test_11g_ojdbc11

on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

jobs:
build:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft

runs-on: ubuntu-latest
continue-on-error: false
strategy:
matrix:
ruby: [
'jruby-10.0.5.0'
]
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 Java
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: '21'
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
Comment thread
yahonda marked this conversation as resolved.
- 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/23261/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 fetching DATE/TIMESTAMP
# values. Copy the v14 files from the 11g container and point the
# Instant Client at them via ORA_TZFILE.
ORACLE_CONTAINER="${{ job.services.oracle.id }}"
sudo mkdir -p "$ORACLE_HOME/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 "$ORACLE_HOME/oracore/zoneinfo/"
sudo mv /tmp/timezone_14.dat "$ORACLE_HOME/oracore/zoneinfo/"
echo "ORA_TZFILE=timezlrg_14.dat" >> $GITHUB_ENV
- 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
3 changes: 0 additions & 3 deletions .github/workflows/test_gemfiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ jobs:
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
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ In addition install either ruby-oci8 (for MRI/YARV) or copy Oracle JDBC driver t
If you are using MRI Ruby implementation then you need to install ruby-oci8 gem (version 2.1 or higher)
as well as Oracle client, e.g. [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html).

If you are using JRuby then you need to download latest [Oracle JDBC driver](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html) - either ojdbc7.jar for Java 8 and 7, ojdbc6.jar for Java 6, 7, 8 or ojdbc5.jar for Java 5. You can refer [the support matrix](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#01_03) for details.
If you are using JRuby then you need to download the appropriate [Oracle JDBC driver](https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html) for your Java version - ojdbc17.jar for Java 17+, ojdbc11.jar for Java 11+, ojdbc8.jar for Java 8+, ojdbc7.jar for Java 7, ojdbc6.jar for Java 6, or ojdbc5.jar for Java 5.

And copy this file to one of these locations. JDBC driver will be searched in this order:

Expand Down
53 changes: 38 additions & 15 deletions lib/plsql/jdbc_connection.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
ojdbc_jars = []

begin
require "java"
require "jruby"

# ojdbc6.jar or ojdbc5.jar file should be in JRUBY_HOME/lib or should be in ENV['PATH'] or load path
# Oracle JDBC driver jar should be in JRUBY_HOME/lib or should be in ENV['PATH'] or load path

java_version = java.lang.System.getProperty("java.version")
ojdbc_jars = if java_version =~ /^1.5/
%w(ojdbc5.jar)
elsif java_version =~ /^1.6/
%w(ojdbc6.jar)
elsif java_version >= "1.7"
# Oracle 11g client ojdbc6.jar is also compatible with Java 1.7
# Oracle 12c client provides new ojdbc7.jar
%w(ojdbc7.jar ojdbc6.jar)
java_major = if java_version =~ /^1\.(\d+)/
$1.to_i
else
[]
java_version.to_i
end

if ENV_JAVA["java.class.path"] !~ Regexp.new(ojdbc_jars.join("|"))
ojdbc_jars << "ojdbc17.jar" if java_major >= 17
ojdbc_jars << "ojdbc11.jar" if java_major >= 11
ojdbc_jars << "ojdbc8.jar" if java_major >= 8
ojdbc_jars << "ojdbc7.jar" if java_major >= 7
ojdbc_jars << "ojdbc6.jar" if java_major >= 6
ojdbc_jars << "ojdbc5.jar" if java_major == 5

if ENV_JAVA["java.class.path"] !~ Regexp.union(ojdbc_jars)
# On Unix environment variable should be PATH, on Windows it is sometimes Path
env_path = (ENV["PATH"] || ENV["Path"] || "").split(File::PATH_SEPARATOR)
# Look for JDBC driver at first in lib subdirectory (application specific JDBC file version)
Expand All @@ -33,23 +36,43 @@
end
end

java.sql.DriverManager.registerDriver Java::oracle.jdbc.OracleDriver.new

# set tns_admin property from TNS_ADMIN environment variable
if !java.lang.System.get_property("oracle.net.tns_admin") && ENV["TNS_ADMIN"]
java.lang.System.set_property("oracle.net.tns_admin", ENV["TNS_ADMIN"])
end

rescue LoadError, NameError
rescue LoadError
# JDBC driver is unavailable.
raise LoadError, "ERROR: ruby-plsql could not load Oracle JDBC driver. Please install #{ojdbc_jars.empty? ? "Oracle JDBC" : ojdbc_jars.join(' or ') } library."
end
Comment thread
yahonda marked this conversation as resolved.

module PLSQL
class JDBCConnection < Connection # :nodoc:
begin
ORACLE_DRIVER = Java::oracle.jdbc.OracleDriver.new
java.sql.DriverManager.registerDriver ORACLE_DRIVER
rescue NameError
raise LoadError, "ERROR: ruby-plsql could not load Oracle JDBC driver. " \
"Please install the appropriate Oracle JDBC driver. " \
"See https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html"
Comment thread
yahonda marked this conversation as resolved.
end

def self.create_raw(params)
url = jdbc_connection_url(params)
new(java.sql.DriverManager.getConnection(url, params[:username], params[:password]))
conn = begin
java.sql.DriverManager.getConnection(url, params[:username], params[:password])
rescue Java::JavaSql::SQLException => e
raise unless e.message =~ /no suitable driver/i
# bypass DriverManager to work in cases where ojdbc*.jar
# is added to the load path at runtime and not on the
# system classpath
ORACLE_DRIVER.connect(url, java.util.Properties.new.tap do |props|
props.setProperty("user", params[:username])
props.setProperty("password", params[:password])
end)
Comment thread
yahonda marked this conversation as resolved.
end
conn.setAutoCommit(false)
new(conn)
Comment thread
yahonda marked this conversation as resolved.
end

def self.jdbc_connection_url(params)
Expand Down
2 changes: 1 addition & 1 deletion spec/plsql/procedure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1875,7 +1875,7 @@ def new_candidate(status)
expect(plsql.test_cursor do |cursor|
cursor2 = cursor
end).to be_nil
expect { cursor2.fetch }.to raise_error(/Cursor was already closed|Closed Statement/)
expect { cursor2.fetch }.to raise_error(/Cursor was already closed|Closed Statement|Closed ResultSet/)
end

it "should not raise error if cursor is closed inside block" do
Expand Down
13 changes: 12 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,18 @@ def get_connection(user_number = 0)
end
else
try_to_connect(Java::JavaSql::SQLException) do
java.sql.DriverManager.getConnection(get_connection_url, database_user, database_password)
begin
java.sql.DriverManager.getConnection(get_connection_url, database_user, database_password)
rescue Java::JavaSql::SQLException => e
raise unless e.message =~ /no suitable driver/i
# bypass DriverManager to work in cases where ojdbc*.jar
# is added to the load path at runtime and not on the
# system classpath
PLSQL::JDBCConnection::ORACLE_DRIVER.connect(get_connection_url, java.util.Properties.new.tap do |props|
props.setProperty("user", database_user)
props.setProperty("password", database_password)
end)
Comment thread
yahonda marked this conversation as resolved.
end.tap { |c| c.setAutoCommit(false) }
Comment thread
yahonda marked this conversation as resolved.
end
end
end
Expand Down
Loading