dm-is-reflective 1.3.0 → 1.3.1
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/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
|