db_meta 0.13.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/01_test.yml +2 -2
- data/.github/workflows/02_release.yml +2 -2
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +20 -0
- data/README.md +26 -5
- data/db_meta.gemspec +1 -1
- data/lib/db_meta/oracle/connection.rb +15 -2
- data/lib/db_meta/oracle/objects.rb +5 -2
- data/lib/db_meta/oracle/types/column.rb +0 -2
- data/lib/db_meta/oracle/types/comment.rb +0 -2
- data/lib/db_meta/oracle/types/constraint.rb +83 -27
- data/lib/db_meta/oracle/types/database_link.rb +0 -2
- data/lib/db_meta/oracle/types/function.rb +0 -2
- data/lib/db_meta/oracle/types/index.rb +0 -2
- data/lib/db_meta/oracle/types/materialized_view.rb +0 -2
- data/lib/db_meta/oracle/types/package.rb +3 -4
- data/lib/db_meta/oracle/types/procedure.rb +0 -2
- data/lib/db_meta/oracle/types/queue.rb +0 -2
- data/lib/db_meta/oracle/types/sequence.rb +0 -2
- data/lib/db_meta/oracle/types/synonym.rb +0 -2
- data/lib/db_meta/oracle/types/table.rb +1 -3
- data/lib/db_meta/oracle/types/table_data_collection.rb +0 -2
- data/lib/db_meta/oracle/types/trigger.rb +0 -2
- data/lib/db_meta/oracle/types/type.rb +0 -2
- data/lib/db_meta/oracle/types/view.rb +2 -4
- data/lib/db_meta/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2a8daf933344c242f2d8b50b218bddb5a4cf488a729316ad11c658af6c5cb782
|
|
4
|
+
data.tar.gz: b20f8d156bdfd1839d52781603a4abb83a099adfa415399acf53308cf887a566
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cdddc2bfff37d407e381f9a642dd586c6ecf728f3db170f9db6e0ffc03d4c999633ee8c840d80fb4c2ced75910e399f8ea063825000c143bd4df87ea725eb863
|
|
7
|
+
data.tar.gz: 5ff480c88420a57634dc65bdd99dcf418a82bbd978457a42b8fd610c4c6d4896243f6b62fa312536b08efc4b21fc43ee4df90694b55c091a1d14c90d646e70d8
|
|
@@ -28,11 +28,11 @@ jobs:
|
|
|
28
28
|
strategy:
|
|
29
29
|
fail-fast: false
|
|
30
30
|
matrix:
|
|
31
|
-
ruby: [ '
|
|
31
|
+
ruby: [ '4.0', '3.4', '3.3']
|
|
32
32
|
|
|
33
33
|
name: Ruby ${{ matrix.ruby }}
|
|
34
34
|
steps:
|
|
35
|
-
- uses: actions/checkout@
|
|
35
|
+
- uses: actions/checkout@v6
|
|
36
36
|
|
|
37
37
|
- name: Install Oracle instant client
|
|
38
38
|
run: |
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
22
|
- name: Checkout current code
|
|
23
|
-
uses: actions/checkout@
|
|
23
|
+
uses: actions/checkout@v6
|
|
24
24
|
|
|
25
25
|
- name: Install Oracle instant client
|
|
26
26
|
run: |
|
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
- name: Set up Ruby
|
|
46
46
|
uses: ruby/setup-ruby@v1
|
|
47
47
|
with:
|
|
48
|
-
ruby-version: '
|
|
48
|
+
ruby-version: '4.0'
|
|
49
49
|
bundler: latest
|
|
50
50
|
bundler-cache: true
|
|
51
51
|
cache-version: 1
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.3
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby
|
|
1
|
+
ruby 4.0.3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## [0.14.0] - 2026-04-28
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
- Reuse a single OCI8 logical connection per worker thread for the duration of the fetch instead of acquiring/logging off on every type fetch. Drastically reduces session attach/detach traffic against the connection pool, which avoids the per-attach overhead (and the 23c Instant Client byte-leak symptom) on long extracts.
|
|
5
|
+
- Batch-load constraint metadata via two bulk queries against `USER_CONSTRAINTS` and `USER_CONS_COLUMNS` once before the parallel object fetch, and have `Constraint#fetch` read from an in-memory cache. Removes 2-3 round-trips per constraint.
|
|
6
|
+
- Constraints with Oracle-generated `SYS_*` names are now emitted without an explicit `CONSTRAINT <name>` clause, so DDL diffs across instances aren't dominated by name churn. User-given names are preserved.
|
|
7
|
+
- Redundant `SYS_*` NOT NULL CHECK constraints (whose condition is just `"COL" IS NOT NULL`) are filtered out — the column-level NOT NULL in the table DDL already covers them.
|
|
8
|
+
- Fixed `View#fetch` to reuse the acquired connection (previously called `Connection.instance.get` twice, leaking a logical connection per view).
|
|
9
|
+
- Fixed `View#extract` crash when a view has columns without comments (`column.comment.size` on nil).
|
|
10
|
+
- Fixed `Table#fetch` ensure logic (was `rescue` instead of `ensure`).
|
|
11
|
+
- Fixed `Column.all` typo (`loggoff` → cleanup no longer needed).
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- README troubleshooting section for macOS / Apple Silicon: short tip covering both the 23c OID lookup hang and the `libclntsh` ↔ OpenLDAP symbol-clash, with the shared `tnsnames.ora` + `NAMES.DIRECTORY_PATH=(TNSNAMES, EZCONNECT)` fix and links to the relevant ruby-oci8 / Oracle docs.
|
|
15
|
+
- Significantly expanded test coverage (49 → 125 examples; line coverage 58.94% → ~86%).
|
|
16
|
+
- Added Ruby 4.0 to the supported/tested matrix.
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
- Dropped Ruby 3.2 from the actively tested matrix (EOL 31 Mar 2026).
|
|
20
|
+
|
|
1
21
|
## [0.13.1] - 2025-11-09
|
|
2
22
|
|
|
3
23
|
### Added
|
data/README.md
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
[](https://github.com/thomis/db_meta/actions/workflows/01_test.yml)
|
|
3
3
|
[](https://github.com/thomis/db_meta/actions/workflows/02_release.yml)
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
Database meta and core data extraction.
|
|
5
|
+
# db_meta
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
Extract Oracle schema metadata and core data as SQL DDL files.
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
`db_meta` connects to an Oracle schema and writes out DDL for every object (tables, views, indexes, constraints, packages, sequences, synonyms, grants, …), plus optional `INSERT` scripts for reference/lookup data. The output is a folder of `.sql` files organized by object type — suitable for checking into version control, diffing across environments, or seeding a fresh schema.
|
|
10
|
+
|
|
11
|
+
## Status
|
|
12
|
+
|
|
13
|
+
Used in day-to-day database development by the author. It covers the most common Oracle object types but is not exhaustive — exotic features (advanced storage clauses, partitioning details, etc.) may be missing or simplified. Spot-check the output before relying on it for a migration, and please open an issue if you hit something that's wrong or missing.
|
|
11
14
|
|
|
12
15
|
## Installation
|
|
13
16
|
via Gemfile
|
|
@@ -30,6 +33,13 @@ meta.fetch
|
|
|
30
33
|
meta.extract
|
|
31
34
|
```
|
|
32
35
|
|
|
36
|
+
## Output conventions
|
|
37
|
+
|
|
38
|
+
A few decisions worth knowing about, especially if you compare extracts across instances:
|
|
39
|
+
|
|
40
|
+
- **Auto-generated `SYS_*` constraint names are stripped from the output.** Oracle invents names like `SYS_C0012345` for unnamed constraints, and those names differ between instances — making schema diffs noisy. Constraints with a `SYS_*` name are emitted without an explicit `CONSTRAINT <name>` clause; on import, Oracle just generates a fresh name. User-given constraint names are preserved as-is.
|
|
41
|
+
- **Redundant `NOT NULL` CHECK constraints are omitted.** Oracle exposes column-level `NOT NULL` both as a column attribute and as a `SYS_*` CHECK constraint with a body of `"COL" IS NOT NULL`. The column-level form is already in the table DDL, so the duplicate CHECK is filtered out.
|
|
42
|
+
|
|
33
43
|
## Supported Databases
|
|
34
44
|
- Oracle
|
|
35
45
|
|
|
@@ -49,12 +59,13 @@ meta.extract
|
|
|
49
59
|
|
|
50
60
|
Currently supported and tested ruby versions are:
|
|
51
61
|
|
|
62
|
+
- 4.0 (EOL 31 Mar 2029)
|
|
52
63
|
- 3.4 (EOL 31 Mar 2028)
|
|
53
64
|
- 3.3 (EOL 31 Mar 2027)
|
|
54
|
-
- 3.2 (EOL 31 Mar 2026)
|
|
55
65
|
|
|
56
66
|
Ruby versions not tested anymore:
|
|
57
67
|
|
|
68
|
+
- 3.2 (EOL 31 Mar 2026)
|
|
58
69
|
- 3.1 (EOL 31 Mar 2025)
|
|
59
70
|
- 3.0 (EOL 31 Mar 2024)
|
|
60
71
|
- 2.7 (EOL 31 Mar 2023)
|
|
@@ -63,6 +74,16 @@ Ruby versions not tested anymore:
|
|
|
63
74
|
## Planned Features
|
|
64
75
|
- Storage and tablespace clause
|
|
65
76
|
|
|
77
|
+
## Troubleshooting (macOS / Apple Silicon)
|
|
78
|
+
|
|
79
|
+
If `OCI8.new` hangs for ~10s, prints "byte leak" gibberish, or crashes with `ldap_first_entry: Assertion …`, the issue is almost always that the Instant Client is trying to use LDAP/OID for database name resolution. The fix is the same in both cases: tell Oracle to use a local `tnsnames.ora` instead of LDAP. Create `~/opt/oracle/admin/tnsnames.ora` with your DB alias and `~/opt/oracle/admin/sqlnet.ora` containing `NAMES.DIRECTORY_PATH=(TNSNAMES, EZCONNECT)`, then `export TNS_ADMIN=$HOME/opt/oracle/admin`.
|
|
80
|
+
|
|
81
|
+
For background and the `libclntsh` ↔ OpenLDAP symbol-clash variant (caused by Oracle's bundled LDAP client and Homebrew's OpenLDAP both loading into the same Ruby process), see:
|
|
82
|
+
|
|
83
|
+
- [ruby-oci8 #32 — OCI8 hangs when switching to LDAP](https://github.com/kubo/ruby-oci8/issues/32)
|
|
84
|
+
- [ruby-oci8 #41 — Assertion failure using LDAP](https://github.com/kubo/ruby-oci8/issues/41)
|
|
85
|
+
- [Oracle Instant Client FAQ](https://www.oracle.com/database/technologies/instant-client/faqs.html)
|
|
86
|
+
|
|
66
87
|
## Publishing
|
|
67
88
|
|
|
68
89
|
This project uses [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) to securely publish gems to RubyGems.org. Trusted Publishing eliminates the need for long-lived API tokens by using OpenID Connect (OIDC) to establish a trusted relationship between GitHub Actions and RubyGems.org.
|
data/db_meta.gemspec
CHANGED
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_development_dependency "bundler", "
|
|
21
|
+
spec.add_development_dependency "bundler", ">= 2.3"
|
|
22
22
|
spec.add_development_dependency "rake", "~> 13.1"
|
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.13"
|
|
24
24
|
spec.add_development_dependency "standard", "~> 1.34"
|
|
@@ -5,6 +5,8 @@ module DbMeta
|
|
|
5
5
|
class Connection
|
|
6
6
|
include Singleton
|
|
7
7
|
|
|
8
|
+
THREAD_KEY = :db_meta_oracle_connection
|
|
9
|
+
|
|
8
10
|
attr_accessor :username, :password, :database_instance
|
|
9
11
|
attr_reader :pool
|
|
10
12
|
attr_reader :worker
|
|
@@ -23,11 +25,22 @@ module DbMeta
|
|
|
23
25
|
Log.info("Connected to #{@username}@#{@database_instance}")
|
|
24
26
|
end
|
|
25
27
|
|
|
26
|
-
#
|
|
27
|
-
::OCI8.new(@username, @password, @pool)
|
|
28
|
+
# one logical connection per thread - reused across all fetches in that thread
|
|
29
|
+
Thread.current[THREAD_KEY] ||= ::OCI8.new(@username, @password, @pool)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def release_thread_connection
|
|
33
|
+
connection = Thread.current[THREAD_KEY]
|
|
34
|
+
return unless connection
|
|
35
|
+
connection.logoff
|
|
36
|
+
rescue
|
|
37
|
+
# connection may already be closed
|
|
38
|
+
ensure
|
|
39
|
+
Thread.current[THREAD_KEY] = nil
|
|
28
40
|
end
|
|
29
41
|
|
|
30
42
|
def disconnect
|
|
43
|
+
release_thread_connection
|
|
31
44
|
return unless @pool
|
|
32
45
|
@pool.destroy
|
|
33
46
|
Log.info("Logged off from #{@username}@#{@database_instance}")
|
|
@@ -26,6 +26,9 @@ module DbMeta
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def fetch(args = {})
|
|
29
|
+
# bulk-load metadata that would otherwise drive N round-trips per object
|
|
30
|
+
Constraint.preload
|
|
31
|
+
|
|
29
32
|
# fetch details in parallel
|
|
30
33
|
# number of threads = physical connections / 2 to prevent application locking
|
|
31
34
|
worker = (1..Connection.instance.worker / 2).map {
|
|
@@ -35,6 +38,8 @@ module DbMeta
|
|
|
35
38
|
object.fetch
|
|
36
39
|
end
|
|
37
40
|
rescue ThreadError
|
|
41
|
+
ensure
|
|
42
|
+
Connection.instance.release_thread_connection
|
|
38
43
|
end
|
|
39
44
|
}
|
|
40
45
|
worker.map(&:join) # wait until all are done
|
|
@@ -215,8 +220,6 @@ module DbMeta
|
|
|
215
220
|
Log.info("Objects: #{items.size}, Object Types: #{types.uniq.size}")
|
|
216
221
|
|
|
217
222
|
objects
|
|
218
|
-
ensure
|
|
219
|
-
connection&.logoff # closes logical connection
|
|
220
223
|
end
|
|
221
224
|
end
|
|
222
225
|
end
|
|
@@ -5,6 +5,72 @@ module DbMeta
|
|
|
5
5
|
|
|
6
6
|
attr_reader :constraint_type, :table_name, :search_condition, :referential_constraint, :delete_rule, :columns
|
|
7
7
|
|
|
8
|
+
@@cache = {}
|
|
9
|
+
@@cache_mutex = Mutex.new
|
|
10
|
+
|
|
11
|
+
def self.preload(args = {})
|
|
12
|
+
connection_class = args[:connection_class] || Connection
|
|
13
|
+
connection = connection_class.instance.get
|
|
14
|
+
|
|
15
|
+
meta = {}
|
|
16
|
+
cursor = connection.exec(
|
|
17
|
+
"select constraint_name, constraint_type, table_name, search_condition, r_constraint_name, delete_rule " \
|
|
18
|
+
"from user_constraints"
|
|
19
|
+
)
|
|
20
|
+
cursor.fetch_hash do |row|
|
|
21
|
+
name = row["CONSTRAINT_NAME"]
|
|
22
|
+
type = translate_constraint_type(row["CONSTRAINT_TYPE"])
|
|
23
|
+
search_condition = row["SEARCH_CONDITION"]
|
|
24
|
+
|
|
25
|
+
# Skip Oracle-generated NOT NULL CHECK constraints. They are already
|
|
26
|
+
# represented by the column's NOT NULL clause in the table DDL, so
|
|
27
|
+
# emitting them again is redundant noise that breaks schema diffs.
|
|
28
|
+
next if redundant_not_null?(name, type, search_condition)
|
|
29
|
+
|
|
30
|
+
meta[name] = {
|
|
31
|
+
constraint_type: type,
|
|
32
|
+
table_name: row["TABLE_NAME"],
|
|
33
|
+
search_condition: search_condition,
|
|
34
|
+
r_constraint_name: row["R_CONSTRAINT_NAME"],
|
|
35
|
+
delete_rule: row["DELETE_RULE"],
|
|
36
|
+
columns: []
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
cursor.close
|
|
40
|
+
|
|
41
|
+
cursor = connection.exec(
|
|
42
|
+
"select constraint_name, column_name, position " \
|
|
43
|
+
"from user_cons_columns order by constraint_name, position"
|
|
44
|
+
)
|
|
45
|
+
cursor.fetch_hash do |row|
|
|
46
|
+
entry = meta[row["CONSTRAINT_NAME"]]
|
|
47
|
+
next unless entry
|
|
48
|
+
entry[:columns] << row["COLUMN_NAME"]
|
|
49
|
+
end
|
|
50
|
+
cursor.close
|
|
51
|
+
|
|
52
|
+
@@cache_mutex.synchronize { @@cache = meta }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.system_generated?(name)
|
|
56
|
+
name.to_s.start_with?("SYS_")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.redundant_not_null?(name, type, search_condition)
|
|
60
|
+
return false unless system_generated?(name) && type == "CHECK"
|
|
61
|
+
return false if search_condition.nil?
|
|
62
|
+
# Match patterns like: "COL_NAME" IS NOT NULL or COL_NAME IS NOT NULL
|
|
63
|
+
!!search_condition.match?(/\A\s*"?[A-Z0-9_$#]+"?\s+IS\s+NOT\s+NULL\s*\z/i)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.cache
|
|
67
|
+
@@cache
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.reset_cache
|
|
71
|
+
@@cache_mutex.synchronize { @@cache = {} }
|
|
72
|
+
end
|
|
73
|
+
|
|
8
74
|
def initialize(args = {})
|
|
9
75
|
super
|
|
10
76
|
|
|
@@ -13,37 +79,29 @@ module DbMeta
|
|
|
13
79
|
end
|
|
14
80
|
|
|
15
81
|
def fetch(args = {})
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
cursor.fetch_hash do |item|
|
|
19
|
-
@constraint_type = translate_constraint_type(item["CONSTRAINT_TYPE"])
|
|
20
|
-
@extract_type = :merged if @constraint_type == "FOREIGN KEY"
|
|
21
|
-
@table_name = item["TABLE_NAME"]
|
|
22
|
-
@search_condition = item["SEARCH_CONDITION"]
|
|
23
|
-
@delete_rule = item["DELETE_RULE"]
|
|
24
|
-
|
|
25
|
-
if @constraint_type == "FOREIGN KEY"
|
|
26
|
-
constraint = Constraint.new("OBJECT_TYPE" => "CONSTRAINT", "OBJECT_NAME" => item["R_CONSTRAINT_NAME"])
|
|
27
|
-
constraint.fetch
|
|
28
|
-
@referential_constraint = constraint
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
cursor.close
|
|
82
|
+
entry = @@cache[@name]
|
|
83
|
+
return unless entry
|
|
32
84
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
85
|
+
@constraint_type = entry[:constraint_type]
|
|
86
|
+
@table_name = entry[:table_name]
|
|
87
|
+
@search_condition = entry[:search_condition]
|
|
88
|
+
@delete_rule = entry[:delete_rule]
|
|
89
|
+
@columns = entry[:columns].dup
|
|
90
|
+
@extract_type = :merged if @constraint_type == "FOREIGN KEY"
|
|
91
|
+
|
|
92
|
+
if @constraint_type == "FOREIGN KEY" && entry[:r_constraint_name]
|
|
93
|
+
@referential_constraint = Constraint.new(
|
|
94
|
+
"OBJECT_TYPE" => "CONSTRAINT",
|
|
95
|
+
"OBJECT_NAME" => entry[:r_constraint_name]
|
|
96
|
+
)
|
|
97
|
+
@referential_constraint.fetch
|
|
37
98
|
end
|
|
38
|
-
cursor.close
|
|
39
|
-
ensure
|
|
40
|
-
connection.logoff
|
|
41
99
|
end
|
|
42
100
|
|
|
43
101
|
def extract(args = {})
|
|
44
102
|
buffer = []
|
|
45
103
|
buffer << "ALTER TABLE #{@table_name} ADD ("
|
|
46
|
-
buffer << " CONSTRAINT #{@name}"
|
|
104
|
+
buffer << " CONSTRAINT #{@name}" unless Constraint.system_generated?(@name)
|
|
47
105
|
|
|
48
106
|
case @constraint_type
|
|
49
107
|
when "CHECK"
|
|
@@ -69,9 +127,7 @@ module DbMeta
|
|
|
69
127
|
["PRIMARY KEY", "FOREIGN KEY", "UNIQUE", "CHECK"].index(type)
|
|
70
128
|
end
|
|
71
129
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def translate_constraint_type(type)
|
|
130
|
+
def self.translate_constraint_type(type)
|
|
75
131
|
case type
|
|
76
132
|
when "P"
|
|
77
133
|
"PRIMARY KEY"
|
|
@@ -6,22 +6,21 @@ module DbMeta
|
|
|
6
6
|
attr_reader :header, :body
|
|
7
7
|
|
|
8
8
|
def fetch
|
|
9
|
+
connection = Connection.instance.get
|
|
10
|
+
|
|
9
11
|
@header = ""
|
|
10
|
-
cursor =
|
|
12
|
+
cursor = connection.exec("select text from user_source where type = 'PACKAGE' and name = '#{@name}' order by line")
|
|
11
13
|
while (row = cursor.fetch)
|
|
12
14
|
@header << row[0].to_s
|
|
13
15
|
end
|
|
14
16
|
cursor.close
|
|
15
17
|
|
|
16
18
|
@body = ""
|
|
17
|
-
connection = Connection.instance.get
|
|
18
19
|
cursor = connection.exec("select text from user_source where type = 'PACKAGE BODY' and name = '#{@name}' order by line")
|
|
19
20
|
while (row = cursor.fetch)
|
|
20
21
|
@body << row[0].to_s
|
|
21
22
|
end
|
|
22
23
|
cursor.close
|
|
23
|
-
ensure
|
|
24
|
-
connection.logoff
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def extract(args = {})
|
|
@@ -36,8 +36,6 @@ module DbMeta
|
|
|
36
36
|
@duration = row[3].to_s
|
|
37
37
|
end
|
|
38
38
|
cursor.close
|
|
39
|
-
rescue
|
|
40
|
-
connection.logoff
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
def extract(args = {})
|
|
@@ -54,7 +52,7 @@ module DbMeta
|
|
|
54
52
|
if @iot_type == "IOT"
|
|
55
53
|
constraint = @constraints.find { |c| c.constraint_type == "PRIMARY KEY" }
|
|
56
54
|
buffer[-1] += ","
|
|
57
|
-
buffer << " CONSTRAINT #{constraint.name}"
|
|
55
|
+
buffer << " CONSTRAINT #{constraint.name}" unless Constraint.system_generated?(constraint.name)
|
|
58
56
|
buffer << " PRIMARY KEY (#{constraint.columns.join(", ")})"
|
|
59
57
|
buffer << " ENABLE VALIDATE"
|
|
60
58
|
end
|
|
@@ -15,13 +15,11 @@ module DbMeta
|
|
|
15
15
|
|
|
16
16
|
@source = ""
|
|
17
17
|
connection = Connection.instance.get
|
|
18
|
-
cursor =
|
|
18
|
+
cursor = connection.exec("select text from user_views where view_name = '#{@name}'")
|
|
19
19
|
while (row = cursor.fetch)
|
|
20
20
|
@source << row[0].to_s
|
|
21
21
|
end
|
|
22
22
|
cursor.close
|
|
23
|
-
ensure
|
|
24
|
-
connection.logoff
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
def extract(args = {})
|
|
@@ -47,7 +45,7 @@ module DbMeta
|
|
|
47
45
|
|
|
48
46
|
# view column comments
|
|
49
47
|
@columns.each do |column|
|
|
50
|
-
next if column.comment.size == 0
|
|
48
|
+
next if column.comment.nil? || column.comment.size == 0
|
|
51
49
|
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'", "''")}';"
|
|
52
50
|
end
|
|
53
51
|
|
data/lib/db_meta/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: db_meta
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thomi
|
|
@@ -13,14 +13,14 @@ dependencies:
|
|
|
13
13
|
name: bundler
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '2.3'
|
|
19
19
|
type: :development
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '2.3'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
@@ -185,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
185
185
|
- !ruby/object:Gem::Version
|
|
186
186
|
version: '0'
|
|
187
187
|
requirements: []
|
|
188
|
-
rubygems_version:
|
|
188
|
+
rubygems_version: 4.0.6
|
|
189
189
|
specification_version: 4
|
|
190
190
|
summary: Database meta and core data extraction
|
|
191
191
|
test_files: []
|