Skip to content

Commit b5bd98d

Browse files
committed
Merge pull request #73 from aboltart/feature/oracle_vagrant_box
Feature/oracle vagrant box
2 parents 2f92353 + 47008a5 commit b5bd98d

File tree

6 files changed

+244
-4
lines changed

6 files changed

+244
-4
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ log
99
tmp
1010
sqlnet.log
1111
Gemfile.lock
12+
*.zip
13+
.vagrant

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ ruby-plsql also provides simple API for select/insert/update/delete table operat
7070
employee = { :employee_id => 1, :first_name => 'First', :last_name => 'Last', :hire_date => Time.local(2000,01,31) }
7171
plsql.employees.insert employee # INSERT INTO employees VALUES (1, 'First', 'Last', ...)
7272

73-
# insert many records
73+
# insert many records
7474
employees = [employee1, employee2, ... ] # array of many Hashes
7575
plsql.employees.insert employees
7676

@@ -141,14 +141,26 @@ If you are using JRuby then you need to download latest [Oracle JDBC driver](htt
141141
TESTS
142142
-----
143143

144-
* Create Oracle database schema for test purposes. Review `spec/spec_helper.rb` to see default schema/user names and database names (use environment variables to override defaults)
144+
Review `spec/spec_helper.rb` to see default schema/user names and database names (use environment variables to override defaults)
145+
146+
##### Prepare database
147+
148+
* With local [Vagrant](https://www.vagrantup.com) based Oracle XE database.
149+
150+
Download Oracle XE database ```oracle-xe-11.2.0-1.0.x86_64.rpm.zip``` from [Oracle Home page](http://www.oracle.com/technetwork/database/database-technologies/express-edition/downloads/index.html) and put it into project home directory.
151+
152+
From project home directory run ```vagrant up``` command to build fully functioning **Centos 6.6** virtual machine with installed Oracle XE database.
153+
154+
* Within other Oracle Database create Oracle database schema for test purposes.
145155

146156
SQL> CREATE USER hr IDENTIFIED BY hr;
147157
SQL> GRANT unlimited tablespace, create session, create table, create sequence, create procedure, create type, create view, create synonym TO hr;
148158

149159
SQL> CREATE USER arunit IDENTIFIED BY arunit;
150160
SQL> GRANT create session TO arunit;
151161

162+
##### Prepare dependencies
163+
152164
* Install bundler with
153165

154166
gem install bundler
@@ -157,7 +169,13 @@ TESTS
157169

158170
bundle install
159171

160-
* Run tests with
172+
##### Run tests
173+
174+
* Run tests with local Vagrant based Oracle XE database
175+
176+
USE_VM_DATABASE=Y rake spec
177+
178+
* Run tests with other Oracle database
161179

162180
rake spec
163181

Vagrantfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
2+
VAGRANTFILE_API_VERSION = "2"
3+
4+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
5+
6+
# Every Vagrant virtual environment requires a box to build off of.
7+
config.vm.box = "chef/centos-6.6"
8+
config.vm.hostname = "vagrant.oracle"
9+
config.vm.network :forwarded_port, guest: 1521, host: 1521
10+
11+
config.vm.provider :virtualbox do |vb|
12+
vb.name = "Ruby-PLSQL Oracle XE box"
13+
# Speed up network
14+
# http://serverfault.com/a/453260/105586
15+
# http://serverfault.com/a/595010/105586
16+
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
17+
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
18+
end
19+
20+
# Check for Oracle XE installation file
21+
config.vm.provision :shell, path: "./spec/support/file_check_script.sh"
22+
23+
config.vm.provision :shell, inline: "yum update -y"
24+
config.vm.provision :shell, inline: "yum install -y libaio bc flex unzip"
25+
config.vm.provision :shell, inline: "mkdir -p /opt/oracle"
26+
config.vm.provision :shell, inline: "unzip -q -d /opt/oracle /vagrant/oracle-xe-11.2.0-1.0.x86_64.rpm.zip"
27+
config.vm.provision :shell, inline: "cd /opt/oracle/Disk1 && rpm -ivh oracle-xe-11.2.0-1.0.x86_64.rpm"
28+
config.vm.provision :shell, inline: %q{sed -i -E "s/<value required>/oracle/" /opt/oracle/Disk1/response/xe.rsp}
29+
config.vm.provision :shell, inline: "/etc/init.d/oracle-xe configure responseFile=/opt/oracle/Disk1/response/xe.rsp >> /opt/oracle/XEsilentinstall.log"
30+
config.vm.provision :shell, inline: ". /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh"
31+
config.vm.provision :shell, inline: "touch /etc/profile.d/oracle_profile.sh && cat /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh >> /etc/profile.d/oracle_profile.sh"
32+
config.vm.provision :shell, inline: %q{sed -i -E "s/HOST = [^)]+/HOST = $HOSTNAME/g" /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora}
33+
config.vm.provision :shell, inline: %q{sed -i -E "s/<ORACLE_BASE>/\/u01\/app\/oracle/" /u01/app/oracle/product/11.2.0/xe/dbs/init.ora}
34+
35+
# Change password for Oracle user
36+
config.vm.provision :shell, inline: "echo -e \"oracle\noracle\" | passwd oracle"
37+
38+
end

spec/spec_helper.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,16 @@
2323

2424
require 'ruby-plsql'
2525

26-
DATABASE_NAME = ENV['DATABASE_NAME'] || 'orcl'
26+
# Requires supporting ruby files with custom matchers and macros, etc,
27+
# in spec/support/ and its subdirectories.
28+
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each {|f| require f}
29+
30+
if ENV['USE_VM_DATABASE'] == 'Y'
31+
DATABASE_NAME = 'XE'
32+
else
33+
DATABASE_NAME = ENV['DATABASE_NAME'] || 'orcl'
34+
end
35+
2736
DATABASE_SERVICE_NAME = (defined?(JRUBY_VERSION) ? "/" : "") +
2837
(ENV['DATABASE_SERVICE_NAME'] || DATABASE_NAME)
2938
DATABASE_HOST = ENV['DATABASE_HOST'] || 'localhost'
@@ -35,6 +44,20 @@
3544
# specify which database version is used (will be verified in one test)
3645
DATABASE_VERSION = ENV['DATABASE_VERSION'] || '10.2.0.4'
3746

47+
if ENV['USE_VM_DATABASE'] == 'Y'
48+
RSpec.configure do |config|
49+
config.before(:suite) do
50+
TestDb.build
51+
52+
# Set Verbose off to hide warning: already initialized constant DATABASE_VERSION
53+
original_verbosity = $VERBOSE
54+
$VERBOSE = nil
55+
DATABASE_VERSION = TestDb.database_version
56+
$VERBOSE = original_verbosity
57+
end
58+
end
59+
end
60+
3861
def get_eazy_connect_url(svc_separator = "")
3962
"#{DATABASE_HOST}:#{DATABASE_PORT}#{svc_separator}#{DATABASE_SERVICE_NAME}"
4063
end

spec/support/file_check_script.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
set -e
3+
4+
FILE=/vagrant/oracle-xe-11.2.0-1.0.x86_64.rpm.zip
5+
6+
if [ ! -f "$FILE" ] ; then
7+
echo "Oracle XE database installation (oracle-xe-11.2.0-1.0.x86_64.rpm.zip) can not be found. Please download from Oracle homepage and put it into project home directory."
8+
exit 1
9+
fi

spec/support/test_db.rb

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
class TestDb
2+
3+
DATABASE_USERS = %w{hr arunit}
4+
5+
def self.build
6+
db = self.new
7+
db.cleanup_database_users
8+
db.create_user_tablespace
9+
db.setup_database_users
10+
db.connection.logoff
11+
end
12+
13+
def self.database_version
14+
db = self.new
15+
db.database_version
16+
end
17+
18+
def connection
19+
unless defined?(@connection)
20+
begin
21+
Timeout::timeout(5) {
22+
if defined?(JRUBY_VERSION)
23+
@connection = java.sql.DriverManager.get_connection(
24+
'jdbc:oracle:thin:@127.0.0.1:1521/XE',
25+
'system',
26+
'oracle'
27+
);
28+
else
29+
@connection = OCI8.new(
30+
'system',
31+
'oracle',
32+
'(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XE)))'
33+
)
34+
end
35+
}
36+
rescue Timeout::Error
37+
raise "Cannot establish connection with Oracle database as SYSTEM user. Seams you need to start local Oracle database"
38+
end
39+
end
40+
@connection
41+
end
42+
43+
def create_user_tablespace
44+
return unless connection
45+
execute_statement(<<-STATEMENT
46+
DECLARE
47+
v_exists number;
48+
BEGIN
49+
SELECT count(1)
50+
INTO v_exists
51+
FROM dba_tablespaces
52+
WHERE tablespace_name = 'TBS_USERS';
53+
54+
IF v_exists = 0 THEN
55+
EXECUTE IMMEDIATE 'ALTER SYSTEM SET DB_CREATE_FILE_DEST = ''/u01/app/oracle/oradata/XE''';
56+
EXECUTE IMMEDIATE 'CREATE TABLESPACE TBS_USERS DATAFILE ''tbs_users.dat'' SIZE 10M REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 200M';
57+
END IF;
58+
END;
59+
STATEMENT
60+
)
61+
end
62+
63+
def database_users
64+
DATABASE_USERS.inject([]){|array, user| array << [user.upcase, user]}
65+
end
66+
67+
def cleanup_database_users
68+
return unless connection
69+
database_users.each do | db, _ |
70+
execute_statement(<<-STATEMENT
71+
DECLARE
72+
v_count INTEGER := 0;
73+
l_cnt INTEGER;
74+
BEGIN
75+
76+
SELECT COUNT (1)
77+
INTO v_count
78+
FROM dba_users
79+
WHERE username = '#{db}';
80+
81+
IF v_count != 0 THEN
82+
FOR x IN (SELECT *
83+
FROM v$session
84+
WHERE username = '#{db}')
85+
LOOP
86+
EXECUTE IMMEDIATE 'ALTER SYSTEM DISCONNECT SESSION ''' || x.sid || ',' || x.serial# || ''' IMMEDIATE';
87+
END LOOP;
88+
89+
EXECUTE IMMEDIATE ('DROP USER #{db} CASCADE');
90+
END IF;
91+
END;
92+
STATEMENT
93+
)
94+
end
95+
end
96+
97+
def setup_database_users
98+
return unless connection
99+
database_users.each do | db, passwd |
100+
execute_statement(<<-STATEMENT
101+
DECLARE
102+
v_count INTEGER := 0;
103+
BEGIN
104+
105+
SELECT COUNT (1)
106+
INTO v_count
107+
FROM dba_users
108+
WHERE username = '#{db}';
109+
110+
IF v_count = 0 THEN
111+
EXECUTE IMMEDIATE ('CREATE USER #{db} IDENTIFIED BY #{passwd} DEFAULT TABLESPACE TBS_USERS QUOTA 10m ON TBS_USERS');
112+
EXECUTE IMMEDIATE ('GRANT create session, create table, create sequence, create procedure, create type, create view, create synonym TO #{db}');
113+
END IF;
114+
END;
115+
STATEMENT
116+
)
117+
end
118+
end
119+
120+
def database_version
121+
query = 'SELECT version FROM V$INSTANCE'
122+
123+
if defined?(JRUBY_VERSION)
124+
statement = connection.create_statement
125+
resource = statement.execute_query(query)
126+
127+
resource.next
128+
value = resource.get_string('VERSION')
129+
130+
resource.close
131+
statement.close
132+
else
133+
cursor = execute_statement(query)
134+
value = cursor.fetch()[0]
135+
cursor.close
136+
end
137+
138+
value.match(/(.*)\.\d$/)[1]
139+
end
140+
141+
def execute_statement(statement)
142+
if defined?(JRUBY_VERSION)
143+
statement = connection.prepare_call(statement)
144+
statement.execute
145+
statement.close
146+
else
147+
connection.exec(statement)
148+
end
149+
end
150+
end

0 commit comments

Comments
 (0)