Skip to content

Commit 10011ec

Browse files
yahondaclaude
andcommitted
Use type_owner for cross-schema type lookups (fixes rsim#208)
Use argument_metadata[:type_owner] instead of @schema_name when querying ALL_PLSQL_TYPE_ATTRS, ALL_TAB_COLUMNS, ALL_PLSQL_COLL_TYPES, and ALL_COLL_TYPES so that types defined in another schema are resolved correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3a7a307 commit 10011ec

17 files changed

Lines changed: 86 additions & 337 deletions

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 0 additions & 22 deletions
This file was deleted.

.github/dependabot.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ updates:
44
- package-ecosystem: "github-actions"
55
directory: "/"
66
schedule:
7-
interval: "weekly"
7+
# Check for updates to GitHub Actions every weekday
8+
interval: "daily"

.github/workflows/release.yml

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,14 @@ jobs:
2323
- name: Build gem
2424
run: gem build ruby-plsql.gemspec
2525
- name: Upload gem artifact
26-
uses: actions/upload-artifact@v7
26+
uses: actions/upload-artifact@v4
2727
with:
2828
name: gem-cruby
2929
path: "*.gem"
3030

31-
build-jruby:
32-
name: Build gem (JRuby)
33-
runs-on: ubuntu-latest
34-
steps:
35-
- uses: actions/checkout@v6
36-
- name: Set up Ruby
37-
uses: ruby/setup-ruby@v1
38-
with:
39-
ruby-version: 'jruby-10.0.5.0'
40-
rubygems: latest
41-
- name: Build gem
42-
run: gem build ruby-plsql.gemspec
43-
- name: Upload gem artifact
44-
uses: actions/upload-artifact@v7
45-
with:
46-
name: gem-jruby
47-
path: "*.gem"
48-
4931
release:
50-
name: Push gems to RubyGems
51-
needs: [build-cruby, build-jruby]
32+
name: Push gem to RubyGems
33+
needs: [build-cruby]
5234
runs-on: ubuntu-latest
5335
environment: rubygems
5436
permissions:
@@ -57,21 +39,17 @@ jobs:
5739
actions: read
5840
steps:
5941
- name: Download CRuby gem
60-
uses: actions/download-artifact@v8
42+
uses: actions/download-artifact@v4
6143
with:
6244
name: gem-cruby
63-
- name: Download JRuby gem
64-
uses: actions/download-artifact@v8
65-
with:
66-
name: gem-jruby
6745
- name: Set up Ruby
6846
uses: ruby/setup-ruby@v1
6947
with:
7048
ruby-version: '4.0'
7149
rubygems: latest
7250
- name: Configure RubyGems credentials
7351
uses: rubygems/configure-rubygems-credentials@main
74-
- name: Push gems
52+
- name: Push gem
7553
run: |
7654
for gem in *.gem; do
7755
echo "Pushing $gem"

README.md

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Test](https://github.com/rsim/ruby-plsql/actions/workflows/test.yml/badge.svg)](https://github.com/rsim/ruby-plsql/actions/workflows/test.yml)
1+
[![Build Status](https://travis-ci.com/rsim/ruby-plsql.svg?branch=master)](https://travis-ci.com/rsim/ruby-plsql)
22

33
ruby-plsql
44
==========
@@ -120,22 +120,6 @@ plsql.activerecord_class = ActiveRecord::Base
120120
and then you do not need to specify plsql.connection (this is also safer when ActiveRecord reestablishes connection to database).
121121

122122

123-
### JRuby JDBC connection:
124-
125-
When using JRuby, the `connect!` method with `:host` and `:database` options uses the thin-style service name syntax by default:
126-
127-
```ruby
128-
# Connects using service name syntax: jdbc:oracle:thin:@//localhost:1521/MYSERVICENAME
129-
plsql.connect! username: "hr", password: "hr", host: "localhost", database: "MYSERVICENAME"
130-
```
131-
132-
If you need to connect using the legacy SID syntax (for Oracle databases older than 12c), prefix the database name with a colon:
133-
134-
```ruby
135-
# Connects using SID syntax: jdbc:oracle:thin:@localhost:1521:MYSID
136-
plsql.connect! username: "hr", password: "hr", host: "localhost", database: ":MYSID"
137-
```
138-
139123
### Cheat Sheet:
140124

141125
You may have a look at this [Cheat Sheet](http://cheatography.com/jgebal/cheat-sheets/ruby-plsql-cheat-sheet/) for instructions on how to use ruby-plsql
@@ -151,7 +135,7 @@ or include gem in Gemfile if using bundler.
151135

152136
In addition install either ruby-oci8 (for MRI/YARV) or copy Oracle JDBC driver to $JRUBY_HOME/lib (for JRuby).
153137

154-
If you are using MRI Ruby implementation then you need to install ruby-oci8 gem (version 2.1 or higher)
138+
If you are using MRI Ruby implementation then you need to install ruby-oci8 gem (version 2.0.x or 2.1.x)
155139
as well as Oracle client, e.g. [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html).
156140

157141
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.

lib/plsql/jdbc_connection.rb

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,31 +48,14 @@
4848
module PLSQL
4949
class JDBCConnection < Connection # :nodoc:
5050
def self.create_raw(params)
51-
url = jdbc_connection_url(params)
52-
new(java.sql.DriverManager.getConnection(url, params[:username], params[:password]))
53-
end
54-
55-
def self.jdbc_connection_url(params)
5651
database = params[:database]
57-
if ENV["TNS_ADMIN"] && database && database !~ %r{\A[:/]} && !params[:host] && !params[:url]
52+
url = if ENV["TNS_ADMIN"] && database && !params[:host] && !params[:url]
5853
"jdbc:oracle:thin:@#{database}"
5954
else
60-
return params[:url] if params[:url]
61-
62-
raise ArgumentError, "database or url option is required" if database.nil? || database.empty?
63-
64-
host = params[:host] || "localhost"
65-
port = params[:port] || 1521
66-
67-
if database =~ /^:/
68-
# SID syntax: jdbc:oracle:thin:@host:port:SID
69-
"jdbc:oracle:thin:@#{host}:#{port}#{database}"
70-
else
71-
# service name syntax: jdbc:oracle:thin:@//host:port/service_name
72-
database = "/#{database}" unless database =~ /^\//
73-
"jdbc:oracle:thin:@//#{host}:#{port}#{database}"
74-
end
55+
database = ":#{database}" unless database.match(/^(\:|\/)/)
56+
params[:url] || "jdbc:oracle:thin:@#{params[:host] || 'localhost'}:#{params[:port] || 1521}#{database}"
7557
end
58+
new(java.sql.DriverManager.getConnection(url, params[:username], params[:password]))
7659
end
7760

7861
def set_time_zone(time_zone = nil)

lib/plsql/oci8_patches.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# apply TIMESTAMP fractional seconds patch to ruby-oci8 2.0.3
2+
# see http://rubyforge.org/forum/forum.php?thread_id=46576&forum_id=1078
3+
if OCI8::VERSION == "2.0.3" &&
4+
!OCI8::BindType::Util.method_defined?(:datetime_to_array_without_timestamp_patch)
5+
6+
OCI8::BindType::Util.module_eval do
7+
alias :datetime_to_array_without_timestamp_patch :datetime_to_array
8+
def datetime_to_array(val, full)
9+
result = datetime_to_array_without_timestamp_patch(val, full)
10+
if result && result[6] == 0
11+
if val.respond_to? :nsec
12+
fsec = val.nsec
13+
elsif val.respond_to? :usec
14+
fsec = val.usec * 1000
15+
else
16+
fsec = 0
17+
end
18+
result[6] = fsec
19+
end
20+
result
21+
end
22+
private :datetime_to_array_without_timestamp_patch, :datetime_to_array
23+
end
24+
25+
end

lib/plsql/oci_connection.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
raise LoadError, "ERROR: ruby-plsql could not load ruby-oci8 library. #{msg}"
1515
end
1616

17+
require "plsql/oci8_patches"
18+
1719
# check ruby-oci8 version
18-
if Gem::Version.new(OCI8::VERSION) < Gem::Version.new("2.1.0")
19-
raise LoadError, "ERROR: ruby-oci8 version #{OCI8::VERSION} is too old. Please install ruby-oci8 version 2.1.0 or later."
20+
required_oci8_version = [2, 0, 3]
21+
oci8_version_ints = OCI8::VERSION.scan(/\d+/).map { |s| s.to_i }
22+
if (oci8_version_ints <=> required_oci8_version) < 0
23+
raise LoadError, "ERROR: ruby-oci8 version #{OCI8::VERSION} is too old. Please install ruby-oci8 version #{required_oci8_version.join('.')} or later."
2024
end
2125

2226
module PLSQL

lib/plsql/procedure.rb

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def get_field_definitions(argument_metadata) # :nodoc:
361361
WHERE t.OWNER = :owner AND t.type_name = :type_name AND t.package_name = :package_name
362362
AND ta.OWNER = t.owner AND ta.TYPE_NAME = t.TYPE_NAME AND ta.PACKAGE_NAME = t.PACKAGE_NAME
363363
ORDER BY attr_no",
364-
@schema_name, argument_metadata[:type_name], argument_metadata[:type_subname]) do |r|
364+
argument_metadata[:type_owner], argument_metadata[:type_name], argument_metadata[:type_subname]) do |r|
365365

366366
attr_no, attr_name, attr_type_owner, attr_type_name, attr_type_package, attr_length, attr_precision, attr_scale, attr_char_used = r
367367

@@ -391,9 +391,9 @@ def get_field_definitions(argument_metadata) # :nodoc:
391391
when "TABLE", "VIEW"
392392
@schema.select_all(
393393
"SELECT column_id, column_name, data_type, data_length, data_precision, data_scale, char_length, char_used
394-
FROM ALL_TAB_COLUMNS WHERE OWNER = :owner AND TABLE_NAME = :type_name
394+
FROM ALL_TAB_COLS WHERE OWNER = :owner AND TABLE_NAME = :type_name
395395
ORDER BY column_id",
396-
@schema_name, argument_metadata[:type_name]) do |r|
396+
argument_metadata[:type_owner], argument_metadata[:type_name]) do |r|
397397

398398
col_no, col_name, col_type_name, col_length, col_precision, col_scale, col_char_length, col_char_used = r
399399

@@ -426,7 +426,7 @@ def get_element_definition(argument_metadata) # :nodoc:
426426
"SELECT elem_type_owner, elem_type_name, elem_type_package, length, precision, scale, char_used, index_by
427427
FROM ALL_PLSQL_COLL_TYPES t
428428
WHERE t.OWNER = :owner AND t.TYPE_NAME = :type_name AND t.PACKAGE_NAME = :package_name",
429-
@schema_name, argument_metadata[:type_name], argument_metadata[:type_subname])
429+
argument_metadata[:type_owner], argument_metadata[:type_name], argument_metadata[:type_subname])
430430

431431
elem_type_owner, elem_type_name, elem_type_package, elem_length, elem_precision, elem_scale, elem_char_used, index_by = r
432432

@@ -460,30 +460,13 @@ def get_element_definition(argument_metadata) # :nodoc:
460460

461461
if elem_type_package != nil
462462
element_metadata[:fields] = get_field_definitions(element_metadata)
463-
elsif elem_type_name && elem_type_name =~ /\A(.+)%ROWTYPE\z/
464-
# TABLE OF table%ROWTYPE: Oracle stores elem_type_name as "TABLE_NAME%ROWTYPE"
465-
rowtype_table_name = $1
466-
check_owner = elem_type_owner || @schema_name
467-
object_type_row = @schema.select_first(
468-
"SELECT object_type FROM ALL_OBJECTS WHERE owner = :owner AND object_name = :name AND object_type IN ('TABLE', 'VIEW')",
469-
check_owner, rowtype_table_name)
470-
if object_type_row
471-
element_metadata[:type_owner] ||= check_owner
472-
element_metadata[:type_name] = rowtype_table_name
473-
element_metadata[:sql_type_name] = build_sql_type_name(check_owner, nil, rowtype_table_name)
474-
element_metadata[:data_type] = "PL/SQL RECORD"
475-
element_metadata[:type_object_type] = object_type_row[0]
476-
element_metadata[:fields] = get_field_definitions(element_metadata)
477-
else
478-
raise ArgumentError, "Could not resolve #{check_owner}.#{rowtype_table_name} to a table or view for #{elem_type_name}"
479-
end
480463
end
481464
when "TYPE"
482465
r = @schema.select_first(
483466
"SELECT elem_type_owner, elem_type_name, length, precision, scale, char_used
484467
FROM ALL_COLL_TYPES t
485468
WHERE t.owner = :owner AND t.TYPE_NAME = :type_name",
486-
@schema_name, argument_metadata[:type_name]
469+
argument_metadata[:type_owner], argument_metadata[:type_name]
487470
)
488471
elem_type_owner, elem_type_name, elem_length, elem_precision, elem_scale, elem_char_used = r
489472

lib/plsql/schema.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def raw_connection=(raw_conn) # :nodoc:
4141
# or
4242
#
4343
# plsql.connection = java.sql.DriverManager.getConnection(
44-
# "jdbc:oracle:thin:@//#{database_host}:#{database_port}/#{database_service_name}",
44+
# "jdbc:oracle:thin:@#{database_host}:#{database_port}/#{database_service_name}",
4545
# database_user, database_password)
4646
#
4747
def connection=(conn)

lib/plsql/variable.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ def find(schema, variable, package, override_schema_name = nil)
99
AND type = 'PACKAGE'
1010
AND UPPER(text) LIKE :variable_name",
1111
override_schema_name || schema.schema_name, package, "%#{variable_upcase}%").each do |row|
12-
if row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*((:=|DEFAULT).*)?;\s*(--.*)?$/i ||
13-
row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*(:=|DEFAULT)\s*$/i
12+
if row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*((:=|DEFAULT).*)?;\s*(--.*)?$/i
1413
return new(schema, variable, package, $2.strip, override_schema_name)
1514
end
1615
end

0 commit comments

Comments
 (0)