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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e05d37577ac7449933ee4680893d496c6ca138f
4
- data.tar.gz: ff50451f50e9b1094db71272cbda92bb7476015a
3
+ metadata.gz: e0cf6d64d700dd5f9892573cc43a1d19eb3ba2cd
4
+ data.tar.gz: 7c7647fd2e0a7c917aaf4b035432cff3849ad828
5
5
  SHA512:
6
- metadata.gz: eb614bb45b425c7d5cbdbeb9cbaa8b8acb34ff4492af861c277cdfb60c116ec5560504dd10402dbb492dfa7f5adbc441588f40e0bd3fd59fef29e7535c47d858
7
- data.tar.gz: 9bc150a2c0da4b77af03cca23f2f7c8148d7196689e714c4e8544e6fb38d506c2257dc5f5b25fca74b620e20893c4192eadbc8d2430f1f40ab0f2f8ecccbf5bd
6
+ metadata.gz: f2551113619f6540170864bcb217550037d70e5f4887812c88501b8aa302174080b7244817596e47d45e7d9826b0d152a39cc040d352a2d7803795b33e5946b0
7
+ data.tar.gz: eb33bdb42e9c47d686a7f8cd99a8848f99260fa82053d751e070855de838f045aa4b146b5919fa469a77b9b8b3b71cfd1f7b9cbb59b658d37c2e6702e64c10f6
data/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGES
2
2
 
3
+ ## dm-is-reflective 1.3.1, 2013-05-22
4
+
5
+ * Introduce `indices` method which would return all indices in the storage.
6
+
3
7
  ## dm-is-reflective 1.3.0, 2013-05-20
4
8
 
5
9
  * Warn instead of raising a TypeError if a datatype cannot be found.
data/README.md CHANGED
@@ -80,6 +80,9 @@ end
80
80
  dm.storages
81
81
  # => ['users']
82
82
 
83
+ # show all indices
84
+ dm.indices('users') # [:id, {:unique_index => :users_pkey}]
85
+
83
86
  # there's no guarantee of the order in fields array
84
87
  User.fields
85
88
  # => [[:created_at, DateTime, {:required => false}],
@@ -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.0"
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-20"
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
- private
10
- # construct needed table metadata
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
- sql_columns = <<-SQL
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
- # TODO: can we fix this shit in dm-mysql-adapter?
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
- column
55
- end
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
- private
15
- def reflective_query_storage storage
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
- sql_columns = <<-SQL
28
- SELECT column_name, column_default, is_nullable,
29
- character_maximum_length, udt_name
30
- FROM "information_schema"."columns"
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
- else
51
- is_key = false
52
- idx_uni, idx_com = nil
38
+
39
+ r[column.to_sym] = reflective_indices_hash(key, idx_uni, idx_com)
40
+ r
53
41
  end
42
+ end
54
43
 
55
- column.instance_eval <<-RUBY
56
- def key? ; #{is_key} ; end
57
- def unique_index; #{idx_uni.inspect}; end
58
- def index ; #{idx_com.inspect}; end
59
- RUBY
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
- column
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[:serial] = true if field.column_default =~ /nextval\('\w+'\)/
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
- private
15
- def reflective_query_storage storage
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
- indices = select(sql_indices, storage).inject({}){ |r, field|
22
- columns = field.sql[/\(.+\)/].scan(/\w+/)
23
- uniqueness = !!field.sql[/CREATE UNIQUE INDEX/]
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] << field.name
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
- select('PRAGMA table_info(?)', storage).map{ |field|
35
- if idx = indices[field.name]
36
- idx_uni, idx_com = [:unique_index, :index].map{ |type|
37
- i = idx[type]
38
- if i.empty?
39
- nil
40
- elsif i.size == 1
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.table_name}_pkey"
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'
@@ -1,4 +1,4 @@
1
1
 
2
2
  module DmIsReflective
3
- VERSION = '1.3.0'
3
+ VERSION = '1.3.1'
4
4
  end
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.0
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-20 00:00:00.000000000 Z
11
+ date: 2013-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dm-core