dm-is-reflective 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +3 -0
- data/dm-is-reflective.gemspec +2 -2
- data/lib/dm-is-reflective/adapters/data_objects_adapter.rb +14 -0
- data/lib/dm-is-reflective/adapters/mysql_adapter.rb +42 -39
- data/lib/dm-is-reflective/adapters/postgres_adapter.rb +26 -33
- data/lib/dm-is-reflective/adapters/sqlite_adapter.rb +31 -35
- data/lib/dm-is-reflective/test.rb +21 -0
- data/lib/dm-is-reflective/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0cf6d64d700dd5f9892573cc43a1d19eb3ba2cd
|
4
|
+
data.tar.gz: 7c7647fd2e0a7c917aaf4b035432cff3849ad828
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2551113619f6540170864bcb217550037d70e5f4887812c88501b8aa302174080b7244817596e47d45e7d9826b0d152a39cc040d352a2d7803795b33e5946b0
|
7
|
+
data.tar.gz: eb33bdb42e9c47d686a7f8cd99a8848f99260fa82053d751e070855de838f045aa4b146b5919fa469a77b9b8b3b71cfd1f7b9cbb59b658d37c2e6702e64c10f6
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
data/dm-is-reflective.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "dm-is-reflective"
|
5
|
-
s.version = "1.3.
|
5
|
+
s.version = "1.3.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Lin Jen-Shin (godfat)"]
|
9
|
-
s.date = "2013-05-
|
9
|
+
s.date = "2013-05-22"
|
10
10
|
s.description = "DataMapper plugin that helps you manipulate an existing database.\nIt creates mappings between existing columns and model's properties."
|
11
11
|
s.email = ["godfat (XD) godfat.org"]
|
12
12
|
s.executables = ["dm-is-reflective"]
|
@@ -10,6 +10,12 @@ module DmIsReflective::DataObjectsAdapter
|
|
10
10
|
storages # call the overrided method
|
11
11
|
end
|
12
12
|
|
13
|
+
# returns all indices in the storage.
|
14
|
+
def indices storage
|
15
|
+
reflective_auto_load_adapter_extension
|
16
|
+
indices(storage) # call the overrided method
|
17
|
+
end
|
18
|
+
|
13
19
|
# returns all fields, with format [[name, type, attrs]]
|
14
20
|
# e.g.
|
15
21
|
# [[:created_at, DateTime, {:required => false}],
|
@@ -133,4 +139,12 @@ module DmIsReflective::DataObjectsAdapter
|
|
133
139
|
Adapters.const_get(class_name).__send__(:include,
|
134
140
|
DmIsReflective.const_get(class_name))
|
135
141
|
end
|
142
|
+
|
143
|
+
def reflective_indices_hash key, idx_uni, idx_com
|
144
|
+
h = {}
|
145
|
+
h[:key] = key if key
|
146
|
+
h[:unique_index] = idx_uni if idx_uni
|
147
|
+
h[ :index] = idx_com if idx_com
|
148
|
+
h
|
149
|
+
end
|
136
150
|
end
|
@@ -6,53 +6,51 @@ module DmIsReflective::MysqlAdapter
|
|
6
6
|
select('SHOW TABLES')
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def reflective_query_storage storage
|
12
|
-
sql_indices = <<-SQL
|
9
|
+
def indices storage
|
10
|
+
sql = <<-SQL
|
13
11
|
SELECT column_name, index_name, non_unique
|
14
12
|
FROM `information_schema`.`statistics`
|
15
13
|
WHERE table_schema = ? AND table_name = ?
|
16
14
|
SQL
|
17
15
|
|
18
|
-
|
16
|
+
select(Ext::String.compress_lines(sql),
|
17
|
+
reflective_table_schema, storage).group_by(&:column_name).
|
18
|
+
inject({}) do |r, (column, idxs)|
|
19
|
+
primary = idxs.find{ |i| i.index_name == 'PRIMARY' }
|
20
|
+
primary.index_name = :"#{storage}_pkey" if primary
|
21
|
+
key = !!primary
|
22
|
+
idx_uni, idx_com = idxs.partition{ |i| i.non_unique == 0 }.map{ |i|
|
23
|
+
if i.empty?
|
24
|
+
nil
|
25
|
+
elsif i.size == 1
|
26
|
+
i.first.index_name.to_sym
|
27
|
+
else
|
28
|
+
i.map{ |ii| ii.index_name.to_sym }
|
29
|
+
end
|
30
|
+
}
|
31
|
+
|
32
|
+
r[column.to_sym] = reflective_indices_hash(key, idx_uni, idx_com)
|
33
|
+
r
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
# construct needed table metadata
|
39
|
+
def reflective_query_storage storage
|
40
|
+
sql = <<-SQL
|
19
41
|
SELECT column_name, column_key, column_default, is_nullable,
|
20
42
|
data_type, character_maximum_length, extra, table_name
|
21
43
|
FROM `information_schema`.`columns`
|
22
44
|
WHERE table_schema = ? AND table_name = ?
|
23
45
|
SQL
|
24
46
|
|
25
|
-
|
26
|
-
path = (options[:path] || options['path'] ||
|
27
|
-
options[:database] || options['database']).sub('/', '')
|
28
|
-
|
29
|
-
indices =
|
30
|
-
select(Ext::String.compress_lines(sql_indices), path, storage).
|
31
|
-
group_by(&:column_name)
|
32
|
-
|
33
|
-
select(Ext::String.compress_lines(sql_columns), path, storage).
|
34
|
-
map do |column|
|
35
|
-
if idx = indices[column.column_name]
|
36
|
-
idx_uni, idx_com = idx.partition{ |i| i.non_unique == 0 }.map{ |i|
|
37
|
-
if i.empty?
|
38
|
-
nil
|
39
|
-
elsif i.size == 1
|
40
|
-
i.first.index_name.to_sym
|
41
|
-
else
|
42
|
-
i.map{ |ii| ii.index_name.to_sym }
|
43
|
-
end
|
44
|
-
}
|
45
|
-
else
|
46
|
-
idx_uni, idx_com = nil
|
47
|
-
end
|
48
|
-
|
49
|
-
column.instance_eval <<-RUBY
|
50
|
-
def unique_index; #{idx_uni.inspect}; end
|
51
|
-
def index ; #{idx_com.inspect}; end
|
52
|
-
RUBY
|
47
|
+
idxs = indices(storage)
|
53
48
|
|
54
|
-
|
55
|
-
|
49
|
+
select(Ext::String.compress_lines(sql),
|
50
|
+
reflective_table_schema, storage).map do |f|
|
51
|
+
f.define_singleton_method(:indices){ idxs[f.column_name.to_sym] }
|
52
|
+
f
|
53
|
+
end
|
56
54
|
end
|
57
55
|
|
58
56
|
def reflective_field_name field
|
@@ -63,15 +61,14 @@ module DmIsReflective::MysqlAdapter
|
|
63
61
|
field.data_type
|
64
62
|
end
|
65
63
|
|
66
|
-
def reflective_attributes field, attrs
|
64
|
+
def reflective_attributes field, attrs={}
|
65
|
+
attrs.merge!(field.indices) if field.indices
|
66
|
+
|
67
67
|
attrs[:serial] = true if field.extra == 'auto_increment'
|
68
68
|
|
69
69
|
if field.column_key == 'PRI'
|
70
70
|
attrs[:key] = true
|
71
71
|
attrs[:unique_index] = :"#{field.table_name}_pkey"
|
72
|
-
else
|
73
|
-
attrs[:unique_index] = field.unique_index if field.unique_index
|
74
|
-
attrs[ :index] = field. index if field. index
|
75
72
|
end
|
76
73
|
|
77
74
|
attrs[:allow_nil] = field.is_nullable == 'YES'
|
@@ -99,4 +96,10 @@ module DmIsReflective::MysqlAdapter
|
|
99
96
|
when /\w*TEXT/ ; Property::Text
|
100
97
|
end || super(primitive)
|
101
98
|
end
|
99
|
+
|
100
|
+
def reflective_table_schema
|
101
|
+
# TODO: can we fix this shit in dm-mysql-adapter?
|
102
|
+
(options[:path] || options['path'] ||
|
103
|
+
options[:database] || options['database']).sub('/', '')
|
104
|
+
end
|
102
105
|
end
|
@@ -11,9 +11,8 @@ module DmIsReflective::PostgresAdapter
|
|
11
11
|
select(Ext::String.compress_lines(sql))
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
sql_indices = <<-SQL
|
14
|
+
def indices storage
|
15
|
+
sql = <<-SQL
|
17
16
|
SELECT a.attname, i.relname, ix.indisprimary, ix.indisunique
|
18
17
|
FROM pg_class t, pg_class i, pg_index ix, pg_attribute a
|
19
18
|
WHERE t.oid = ix.indrelid
|
@@ -24,21 +23,10 @@ module DmIsReflective::PostgresAdapter
|
|
24
23
|
AND t.relname = ?
|
25
24
|
SQL
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
WHERE table_schema = current_schema() AND table_name = ?
|
32
|
-
SQL
|
33
|
-
|
34
|
-
indices =
|
35
|
-
select(Ext::String.compress_lines(sql_indices), storage).
|
36
|
-
group_by(&:attname)
|
37
|
-
|
38
|
-
select(Ext::String.compress_lines(sql_columns), storage).map do |column|
|
39
|
-
if idx = indices[column.column_name]
|
40
|
-
is_key = !!idx.find{ |i| i.indisprimary }
|
41
|
-
idx_uni, idx_com = idx.partition{ |i| i.indisunique }.map{ |i|
|
26
|
+
select(Ext::String.compress_lines(sql), storage).group_by(&:attname).
|
27
|
+
inject({}) do |r, (column, idxs)|
|
28
|
+
key = !!idxs.find(&:indisprimary)
|
29
|
+
idx_uni, idx_com = idxs.partition(&:indisunique).map{ |i|
|
42
30
|
if i.empty?
|
43
31
|
nil
|
44
32
|
elsif i.size == 1
|
@@ -47,18 +35,26 @@ module DmIsReflective::PostgresAdapter
|
|
47
35
|
i.map{ |ii| ii.relname.to_sym }
|
48
36
|
end
|
49
37
|
}
|
50
|
-
|
51
|
-
|
52
|
-
|
38
|
+
|
39
|
+
r[column.to_sym] = reflective_indices_hash(key, idx_uni, idx_com)
|
40
|
+
r
|
53
41
|
end
|
42
|
+
end
|
54
43
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
44
|
+
private
|
45
|
+
def reflective_query_storage storage
|
46
|
+
sql = <<-SQL
|
47
|
+
SELECT column_name, column_default, is_nullable,
|
48
|
+
character_maximum_length, udt_name
|
49
|
+
FROM "information_schema"."columns"
|
50
|
+
WHERE table_schema = current_schema() AND table_name = ?
|
51
|
+
SQL
|
52
|
+
|
53
|
+
idxs = indices(storage)
|
60
54
|
|
61
|
-
|
55
|
+
select(Ext::String.compress_lines(sql), storage).map do |f|
|
56
|
+
f.define_singleton_method(:indices){ idxs[f.column_name.to_sym] }
|
57
|
+
f
|
62
58
|
end
|
63
59
|
end
|
64
60
|
|
@@ -70,18 +66,15 @@ module DmIsReflective::PostgresAdapter
|
|
70
66
|
field.udt_name
|
71
67
|
end
|
72
68
|
|
73
|
-
def reflective_attributes field, attrs
|
69
|
+
def reflective_attributes field, attrs={}
|
74
70
|
# strip data type
|
75
71
|
if field.column_default
|
76
72
|
field.column_default.gsub!(/(.*?)::[\w\s]*/, '\1')
|
77
73
|
end
|
78
74
|
|
79
|
-
attrs
|
80
|
-
attrs[:key] = true if field.key?
|
81
|
-
|
82
|
-
attrs[:unique_index] = field.unique_index if field.unique_index
|
83
|
-
attrs[ :index] = field. index if field. index
|
75
|
+
attrs.merge!(field.indices) if field.indices
|
84
76
|
|
77
|
+
attrs[:serial] = true if field.column_default =~ /nextval\('\w+'\)/
|
85
78
|
attrs[:allow_nil] = field.is_nullable == 'YES'
|
86
79
|
# strip string quotation
|
87
80
|
attrs[:default] = field.column_default.gsub(/^'(.*?)'$/, '\1') if
|
@@ -11,49 +11,46 @@ module DmIsReflective::SqliteAdapter
|
|
11
11
|
select(Ext::String.compress_lines(sql))
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
sql_indices = <<-SQL
|
14
|
+
def indices storage
|
15
|
+
sql = <<-SQL
|
17
16
|
SELECT name, sql FROM sqlite_master
|
18
17
|
WHERE type = 'index' AND tbl_name = ?
|
19
18
|
SQL
|
20
19
|
|
21
|
-
|
22
|
-
columns =
|
23
|
-
uniqueness = !!
|
20
|
+
select(Ext::String.compress_lines(sql), storage).inject({}){ |r, idx|
|
21
|
+
columns = idx.sql[/\(.+\)/].scan(/\w+/)
|
22
|
+
uniqueness = !!idx.sql[/CREATE UNIQUE INDEX/]
|
24
23
|
|
25
24
|
columns.each{ |c|
|
26
25
|
type = if uniqueness then :unique_index else :index end
|
27
26
|
r[c] ||= {:unique_index => [], :index => []}
|
28
|
-
r[c][type] <<
|
27
|
+
r[c][type] << idx.name.to_sym
|
29
28
|
}
|
30
29
|
|
30
|
+
r
|
31
|
+
}.inject({}){ |r, (column, idxs)|
|
32
|
+
idx_uni, idx_com = [:unique_index, :index].map{ |type|
|
33
|
+
i = idxs[type]
|
34
|
+
if i.empty?
|
35
|
+
nil
|
36
|
+
elsif i.size == 1
|
37
|
+
i.first.to_sym
|
38
|
+
else
|
39
|
+
i.map(&:to_sym)
|
40
|
+
end
|
41
|
+
}
|
42
|
+
r[column.to_sym] = reflective_indices_hash(false, idx_uni, idx_com)
|
31
43
|
r
|
32
44
|
}
|
45
|
+
end
|
33
46
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
i.first.to_sym
|
42
|
-
else
|
43
|
-
i.map(&:to_sym)
|
44
|
-
end
|
45
|
-
}
|
46
|
-
else
|
47
|
-
idx_uni, idx_com = nil
|
48
|
-
end
|
49
|
-
|
50
|
-
field.instance_eval <<-RUBY
|
51
|
-
def table_name ; '#{storage}' ; end
|
52
|
-
def index ; #{idx_com.inspect}; end
|
53
|
-
def unique_index; #{idx_uni.inspect}; end
|
54
|
-
RUBY
|
55
|
-
|
56
|
-
field
|
47
|
+
private
|
48
|
+
def reflective_query_storage storage
|
49
|
+
idxs = indices(storage)
|
50
|
+
select('PRAGMA table_info(?)', storage).map{ |f|
|
51
|
+
f.define_singleton_method(:storage){ storage }
|
52
|
+
f.define_singleton_method(:indices){ idxs[f.name.to_sym] }
|
53
|
+
f
|
57
54
|
}
|
58
55
|
end
|
59
56
|
|
@@ -65,16 +62,15 @@ module DmIsReflective::SqliteAdapter
|
|
65
62
|
field.type.gsub(/\(\d+\)/, '')
|
66
63
|
end
|
67
64
|
|
68
|
-
def reflective_attributes field, attrs
|
65
|
+
def reflective_attributes field, attrs={}
|
66
|
+
attrs.merge!(field.indices) if field.indices
|
67
|
+
|
69
68
|
if field.pk != 0
|
70
69
|
attrs[:key] = true
|
71
70
|
attrs[:serial] = true
|
72
|
-
attrs[:unique_index] = :"#{field.
|
71
|
+
attrs[:unique_index] = :"#{field.storage}_pkey"
|
73
72
|
end
|
74
73
|
|
75
|
-
attrs[:unique_index] = field.unique_index if field.unique_index
|
76
|
-
attrs[ :index] = field. index if field. index
|
77
|
-
|
78
74
|
attrs[:allow_nil] = field.notnull == 0
|
79
75
|
attrs[:default] = field.dflt_value[1..-2] if field.dflt_value
|
80
76
|
|
@@ -69,6 +69,23 @@ end
|
|
69
69
|
include Abstract
|
70
70
|
|
71
71
|
shared :reflective do
|
72
|
+
def cat_indices
|
73
|
+
@cat_indices ||= begin
|
74
|
+
id = case DataMapper.repository.adapter.class.name
|
75
|
+
when 'DataMapper::Adapters::SqliteAdapter'
|
76
|
+
nil
|
77
|
+
else
|
78
|
+
[:id, {:unique_index => :abstract_cats_pkey, :key => true}]
|
79
|
+
end
|
80
|
+
[id ,
|
81
|
+
[:super_user_id, {:unique_index => :unique_abstract_cats_usu ,
|
82
|
+
:index => :index_abstract_cats_su }] ,
|
83
|
+
[ :user_id, {:unique_index => [:unique_abstract_cats_usu ,
|
84
|
+
:unique_abstract_cats_u]}] ].
|
85
|
+
compact
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
72
89
|
def cat_fields
|
73
90
|
@cat_fields ||=
|
74
91
|
[[:id, DataMapper::Property::Serial,
|
@@ -206,6 +223,10 @@ shared :reflective do
|
|
206
223
|
'abstract_super_users' => super_user_fields)
|
207
224
|
end
|
208
225
|
|
226
|
+
should 'indices' do
|
227
|
+
sort_fields(@dm.indices('abstract_cats')).should.eq cat_indices
|
228
|
+
end
|
229
|
+
|
209
230
|
should 'reflect type' do
|
210
231
|
model, local_dm = create_fake_model
|
211
232
|
model.storage_names[:default] = 'abstract_comments'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-is-reflective
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lin Jen-Shin (godfat)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dm-core
|