dm-reflection 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+
23
+ ## Yard
24
+ .yardoc
25
+ measurements/report.txt
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009 Martin Gamsjaeger (snusnu)
2
+ Copyright (c) 2010 Montana State University
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,77 @@
1
+ = dm-reflection
2
+
3
+ For now, this gem only allows you to print the ruby source for any DataMapper::Model, taking all property and relationship definitions into account. However, the plan is to be able to reflect on an existing relational database schema and export the corresponding datamapper model definitions to ruby source files. Think of it as active_record and annotate_models combined to do something useful with legacy databases.
4
+
5
+ require 'rubygems'
6
+ require 'dm-core'
7
+ require 'dm-reflection'
8
+
9
+ class Project
10
+
11
+ include DataMapper::Resource
12
+
13
+ property :id, Serial
14
+
15
+ property :name, String, :required => true, :length => 200
16
+ property :created_at, DateTime
17
+ property :updated_at, DateTime
18
+
19
+ has 0..n, :project_tasks
20
+ has 0..n, :tasks, :through => :project_tasks
21
+ has 0..n, :people, :through => Resource
22
+
23
+ end
24
+
25
+ Project.to_ruby # produces this nicely formatted ruby code
26
+
27
+ <<-RUBY
28
+ class Project
29
+
30
+ include DataMapper::Resource
31
+
32
+ property :id, Serial
33
+
34
+ property :name, String, :required => true, :length => 200
35
+ property :created_at, DateTime
36
+ property :updated_at, DateTime
37
+
38
+ has 0..n, :project_tasks
39
+ has 0..n, :tasks, :through => :project_tasks
40
+ has 0..n, :people, :through => Resource
41
+
42
+ end
43
+ RUBY
44
+
45
+ Also, you can create models from a repository by doing the following:
46
+
47
+ require 'dm-reflection'
48
+ models = DataMapper::Reflection.reflect(:default)
49
+
50
+ == Note on Patches/Pull Requests
51
+
52
+ * Fork the project.
53
+ * Make your feature addition or bug fix.
54
+ * Add tests for it. This is important so I don't break it in a
55
+ future version unintentionally.
56
+ * Commit, do not mess with rakefile, version, or history.
57
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
58
+ * Send me a pull request. Bonus points for topic branches.
59
+
60
+ == Future Work
61
+
62
+ * Support Associations/Relationships
63
+ * Support Single Table Inheritance
64
+ * Ensure Round tripping is functional
65
+ ** Create model M in DataMapper
66
+ ** Migrate M to a repository
67
+ ** Reflect M' from the repository
68
+ ** M should == M'
69
+
70
+ * Having round tripping provably working is the first goal
71
+ * Legacy reflection is something to make work after round tripping (because the assumptions DM makes won't always hold.)
72
+
73
+ == Copyright
74
+
75
+ See LICENSE for details.
76
+ Copyright (c) 2009 Martin Gamsjaeger (snusnu).
77
+ Copyright (c) 2010 Montana State University, Bozeman (The Yogo Data Management Team).
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+
6
+ gem 'jeweler', '>= 1.4'
7
+ require 'jeweler'
8
+
9
+ require File.expand_path('../lib/dm-reflection/version', __FILE__)
10
+
11
+ Jeweler::Tasks.new do |gem|
12
+
13
+ gem.version = DataMapper::Reflection::VERSION
14
+
15
+ gem.name = "dm-reflection"
16
+ gem.summary = %Q{Generates datamapper models from existing database schemas}
17
+ gem.description = %Q{Generates datamapper models from existing database schemas and export them to files}
18
+ gem.email = "irjudson@gmail.com"
19
+ gem.homepage = "http://github.com/irjudson/dm-reflection"
20
+ gem.authors = ["Martin Gamsjaeger (snusnu), Yogo Team"]
21
+
22
+ gem.add_dependency 'dm-core', '~> 0.10.2'
23
+
24
+ gem.add_development_dependency 'rspec', '~> 1.3'
25
+ gem.add_development_dependency 'yard', '~> 0.5'
26
+
27
+ end
28
+
29
+ Jeweler::GemcutterTasks.new
30
+
31
+ FileList['tasks/**/*.rake'].each { |task| import task }
32
+
33
+ rescue LoadError
34
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{dm-reflection}
8
+ s.version = "0.0.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Martin Gamsjaeger (snusnu), Yogo Team"]
12
+ s.date = %q{2010-05-03}
13
+ s.description = %q{Generates datamapper models from existing database schemas and export them to files}
14
+ s.email = %q{irjudson@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "dm-reflection.gemspec",
27
+ "lib/dm-reflection.rb",
28
+ "lib/dm-reflection/adapters/mysql.rb",
29
+ "lib/dm-reflection/adapters/persevere.rb",
30
+ "lib/dm-reflection/adapters/postgres.rb",
31
+ "lib/dm-reflection/adapters/sqlite3.rb",
32
+ "lib/dm-reflection/builders/source_builder.rb",
33
+ "lib/dm-reflection/reflection.rb",
34
+ "lib/dm-reflection/version.rb",
35
+ "spec/persevere_reflection_spec.rb",
36
+ "spec/rcov.opts",
37
+ "spec/reflection_spec.rb",
38
+ "spec/source_builder_spec.rb",
39
+ "spec/spec.opts",
40
+ "spec/spec_helper.rb",
41
+ "tasks/changelog.rake",
42
+ "tasks/ci.rake",
43
+ "tasks/metrics.rake",
44
+ "tasks/spec.rake",
45
+ "tasks/yard.rake",
46
+ "tasks/yardstick.rake"
47
+ ]
48
+ s.homepage = %q{http://github.com/irjudson/dm-reflection}
49
+ s.rdoc_options = ["--charset=UTF-8"]
50
+ s.require_paths = ["lib"]
51
+ s.rubygems_version = %q{1.3.6}
52
+ s.summary = %q{Generates datamapper models from existing database schemas}
53
+ s.test_files = [
54
+ "spec/persevere_reflection_spec.rb",
55
+ "spec/reflection_spec.rb",
56
+ "spec/source_builder_spec.rb",
57
+ "spec/spec_helper.rb"
58
+ ]
59
+
60
+ if s.respond_to? :specification_version then
61
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
65
+ s.add_runtime_dependency(%q<dm-core>, ["~> 0.10.2"])
66
+ s.add_development_dependency(%q<rspec>, ["~> 1.3"])
67
+ s.add_development_dependency(%q<yard>, ["~> 0.5"])
68
+ else
69
+ s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
70
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
71
+ s.add_dependency(%q<yard>, ["~> 0.5"])
72
+ end
73
+ else
74
+ s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
75
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
76
+ s.add_dependency(%q<yard>, ["~> 0.5"])
77
+ end
78
+ end
79
+
@@ -0,0 +1,95 @@
1
+ module DataMapper
2
+ module Reflection
3
+ module MysqlAdapter
4
+
5
+ ##
6
+ # Convert the database type into a DataMapper type
7
+ #
8
+ # @todo This should be verified to identify all mysql primitive types
9
+ # and that they map to the correct DataMapper/Ruby types.
10
+ #
11
+ # @param [String] db_type type specified by the database
12
+ # @return [Type] a DataMapper or Ruby type object.
13
+ #
14
+ def get_type(db_type)
15
+ # TODO: return a Hash with the :type, :min, :max and other
16
+ # options rather than just the type
17
+
18
+ db_type.match(/\A(\w+)/)
19
+ {
20
+ 'tinyint' => Integer ,
21
+ 'smallint' => Integer ,
22
+ 'mediumint' => Integer ,
23
+ 'int' => Integer ,
24
+ 'bigint' => Integer ,
25
+ 'integer' => Integer ,
26
+ 'varchar' => String ,
27
+ 'char' => String ,
28
+ 'enum' => String ,
29
+ 'decimal' => BigDecimal ,
30
+ 'double' => Float ,
31
+ 'float' => Float ,
32
+ 'datetime' => DateTime ,
33
+ 'timestamp' => DateTime ,
34
+ 'date' => Date ,
35
+ 'boolean' => Types::Boolean,
36
+ 'tinyblob' => Types::Text,
37
+ 'blob' => Types::Text,
38
+ 'mediumblob' => Types::Text,
39
+ 'longblob' => Types::Text,
40
+ 'tinytext' => Types::Text,
41
+ 'text' => Types::Text,
42
+ 'mediumtext' => Types::Text,
43
+ 'longtext' => Types::Text,
44
+ }[$1] || raise("unknown type: #{db_type}")
45
+ end
46
+
47
+ ##
48
+ # Get the list of table names
49
+ #
50
+ # @return [String Array] the names of the tables in the database.
51
+ #
52
+ def get_storage_names
53
+ # This gets all the non view tables, but has to strip column 0 out of the two column response.
54
+ select("SHOW FULL TABLES FROM #{options[:path][1..-1]} WHERE Table_type = 'BASE TABLE'").map { |item| item.first }
55
+ end
56
+
57
+ ##
58
+ # Get the column specifications for a specific table
59
+ #
60
+ # @todo Consider returning actual DataMapper::Properties from this.
61
+ # It would probably require passing in a Model Object.
62
+ #
63
+ # @param [String] table the name of the table to get column specifications for
64
+ # @return [Hash] the column specs are returned in a hash keyed by `:name`, `:field`, `:type`, `:required`, `:default`, `:key`
65
+ #
66
+ def get_properties(table)
67
+ # TODO: use SHOW INDEXES to find out unique and non-unique indexes
68
+
69
+ select("SHOW COLUMNS FROM #{table} IN #{options[:path][1..-1]};").map do |column|
70
+ type = get_type(column.type)
71
+ auto_increment = column.extra == 'auto_increment'
72
+
73
+ if type == Integer && auto_increment
74
+ type = DataMapper::Types::Serial
75
+ end
76
+
77
+ attribute = {
78
+ :name => column.field.downcase,
79
+ :type => type,
80
+ :required => column.null == 'NO',
81
+ :default => column.default,
82
+ :key => column.key == 'PRI',
83
+ }
84
+
85
+ # TODO: use the naming convention to compare the name vs the column name
86
+ unless attribute[:name] == column.field
87
+ attribute[:field] = column.field
88
+ end
89
+
90
+ attribute
91
+ end
92
+ end
93
+ end # module MysqlAdapter
94
+ end # module Reflection
95
+ end # module DataMapper
@@ -0,0 +1,98 @@
1
+ module DataMapper
2
+ module Reflection
3
+ module PersevereAdapter
4
+ extend Chainable
5
+
6
+ ##
7
+ # Convert the JSON Schema type into a DataMapper type
8
+ #
9
+ # @todo This should be verified to identify all mysql primitive types
10
+ # and that they map to the correct DataMapper/Ruby types.
11
+ #
12
+ # @param [String] db_type type specified by the database
13
+ # @param [String] optional format format specification for string attributes
14
+ # @return [Type] a DataMapper or Ruby type object.
15
+ #
16
+ chainable do
17
+ def get_type(db_type)
18
+ type = db_type['type']
19
+ format = db_type['format']
20
+
21
+ case type
22
+ when Hash then DataMapper::Types::JsonReference
23
+ when 'array' then DataMapper::Types::JsonReferenceCollection
24
+ when 'serial' then DataMapper::Types::Serial
25
+ when 'integer' then Integer
26
+ # when 'number' then BigDecimal
27
+ when 'number' then Float
28
+ when 'boolean' then DataMapper::Types::Boolean
29
+ when 'string' then
30
+ case format
31
+ when nil then DataMapper::Types::Text
32
+ when 'date-time' then DateTime
33
+ when 'date' then Date
34
+ when 'time' then Time
35
+ end
36
+ end
37
+ end
38
+ end
39
+ ##
40
+ # Get the list of schema names
41
+ #
42
+ # @return [String Array] the names of the schemas in the server.
43
+ #
44
+ def get_storage_names
45
+ @schemas = self.get_schema
46
+ @schemas.map { |schema| schema['id'].gsub('/', '__') }
47
+ end
48
+
49
+ ##
50
+ # Get the attribute specifications for a specific schema
51
+ #
52
+ # @todo Consider returning actual DataMapper::Properties from this.
53
+ # It would probably require passing in a Model Object.
54
+ #
55
+ # @param [String] table the name of the schema to get attribute specifications for
56
+ # @return [Array] of hashes the column specs are returned in a hash keyed by `:name`, `:field`, `:type`, `:required`, `:default`, `:key`
57
+ #
58
+ chainable do
59
+ def get_properties(table)
60
+ results = Array.new
61
+ schema = self.get_schema(table.gsub('__', '/'))[0]
62
+ schema['properties'].each_pair do |key, value|
63
+ type = get_type(value)
64
+ property = {:name => key, :type => type }
65
+ property.merge!({ :required => !value.delete('optional'),
66
+ :key => value.has_key?('index') && value.delete('index') }) unless property[:type] == DataMapper::Types::Serial
67
+
68
+ if type.kind_of?(DataMapper::Types::JsonReference)
69
+ property.merge!( {:reference => derive_relationship_model(value[:type]["$ref"])} )
70
+ end
71
+
72
+ if type.kind_of?(DataMapper::Types::JsonReferenceCollection)
73
+ property.merge!( {:reference => derive_relationship_model(value[:items]["$ref"])} )
74
+ end
75
+
76
+ value.delete('type')
77
+ value.delete('format')
78
+ value.delete('unique')
79
+ value.delete('index')
80
+ value.delete('items')
81
+ value.keys.each { |key| value[key.to_sym] = value[key]; value.delete(key) }
82
+ property.merge!(value)
83
+ results << property
84
+ end
85
+ return results
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ # Turns 'class_path/class' into 'ClassPath::Class
92
+ def derive_relationship_model(input)
93
+ input.match(/(Class)?\/([a-z\-\/\_]+)$/)[-1].split('/').map{|i| ExtLib::Inflection.classify(i) }.join("::")
94
+ end
95
+
96
+ end # module PersevereAdapter
97
+ end # module Reflection
98
+ end # module DataMapper
@@ -0,0 +1,126 @@
1
+ module DataMapper
2
+ module Reflection
3
+ ##
4
+ # @todo The postgres adapter extensions have not been tested yet.
5
+ #
6
+ module PostgresAdapter
7
+
8
+ ##
9
+ # Convert the database type into a DataMapper type
10
+ #
11
+ # @todo This should be verified to identify all mysql primitive types
12
+ # and that they map to the correct DataMapper/Ruby types.
13
+ #
14
+ # @param [String] db_type type specified by the database
15
+ # @return [Type] a DataMapper or Ruby type object.
16
+ #
17
+ def get_type(db_type)
18
+ {
19
+ 'integer' => Integer ,
20
+ 'varchar' => String ,
21
+ 'character varying' => String ,
22
+ 'numeric' => BigDecimal ,
23
+ 'double precision' => Float ,
24
+ 'datetime' => DateTime ,
25
+ 'date' => Date ,
26
+ 'boolean' => Types::Boolean ,
27
+ 'text' => Types::Text ,
28
+ 'timestamp without time zone' => DateTime ,
29
+ }[db_type] || raise("unknown db type: #{db_type}")
30
+ end
31
+
32
+ ##
33
+ # Get the list of table names
34
+ #
35
+ # @return [String Array] the names of the tables in the database.
36
+ #
37
+ def get_storage_names
38
+ select(<<-SQL.compress_lines)
39
+ SELECT "relname"
40
+ FROM "pg_stat_user_tables"
41
+ WHERE "schemaname" = 'public'
42
+ SQL
43
+ end
44
+
45
+ # Returna list of columns in the primary key
46
+ #
47
+ # @param [String] the table name
48
+ #
49
+ # @return [Array<String>] the names of the columns in the primary key
50
+ #
51
+ def get_primary_keys(table)
52
+ select(<<-SQL.compress_lines, table).to_set
53
+ SELECT "key_column_usage"."column_name"
54
+ FROM "information_schema"."table_constraints"
55
+ INNER JOIN "information_schema"."key_column_usage" USING("constraint_schema", "constraint_name")
56
+ WHERE "table_constraints"."constraint_type" = 'PRIMARY KEY'
57
+ AND "table_constraints"."table_name" = ?
58
+ SQL
59
+ end
60
+
61
+ ##
62
+ # Get the column specifications for a specific table
63
+ #
64
+ # @todo Consider returning actual DataMapper::Properties from this.
65
+ # It would probably require passing in a Model Object.
66
+ #
67
+ # @param [String] table the name of the table to get column specifications for
68
+ # @return [Hash] the column specs are returned in a hash keyed by `:name`, `:field`, `:type`, `:required`, `:default`, `:key`
69
+ #
70
+ def get_properties(table)
71
+ columns = select(<<-SQL.compress_lines, schema_name, table)
72
+ SELECT "column_name"
73
+ , "data_type"
74
+ , "column_default"
75
+ , "is_nullable"
76
+ , "character_maximum_length"
77
+ , "numeric_precision"
78
+ FROM "information_schema"."columns"
79
+ WHERE "table_schema" = ?
80
+ AND "table_name" = ?
81
+ ORDER BY "ordinal_position"
82
+ SQL
83
+
84
+ primary_keys = get_primary_keys(table)
85
+
86
+ columns.map do |column|
87
+ type = get_type(column.data_type)
88
+ default = column.column_default
89
+ required = column.is_nullable == 'NO'
90
+ key = primary_keys.include?(column.column_name)
91
+ length = column.character_maximum_length
92
+
93
+ if type == Integer && default
94
+ if key
95
+ type = DataMapper::Types::Serial if default[/\Anextval/]
96
+ default = nil
97
+ else
98
+ default = default.to_i
99
+ end
100
+ end
101
+
102
+ if length
103
+ length = (required ? 1 : 0)..length
104
+ end
105
+
106
+ attribute = {
107
+ :name => column.column_name.downcase,
108
+ :type => type,
109
+ :required => required,
110
+ :default => default,
111
+ :key => key,
112
+ :length => length,
113
+ }
114
+
115
+ # TODO: use the naming convention to compare the name vs the column name
116
+ unless attribute[:name] == column.column_name
117
+ attribute[:field] = column.column_name
118
+ end
119
+
120
+ attribute
121
+ end
122
+ end
123
+
124
+ end # module PostgresAdapter
125
+ end # module Reflection
126
+ end # module DataMapper
@@ -0,0 +1,85 @@
1
+ module DataMapper
2
+ module Reflection
3
+ module Sqlite3Adapter
4
+
5
+ ##
6
+ # Convert the database type into a DataMapper type
7
+ #
8
+ # @todo This should be verified to identify all sqlite3 primitive types
9
+ # and that they map to the correct DataMapper/Ruby types.
10
+ #
11
+ # @param [String] db_type type specified by the database
12
+ # @return [Type] a DataMapper or Ruby type object.
13
+ #
14
+ def get_type(db_type)
15
+ db_type.match(/\A(\w+)/)
16
+ {
17
+ 'INTEGER' => Integer ,
18
+ 'VARCHAR' => String ,
19
+ 'DECIMAL' => BigDecimal ,
20
+ 'FLOAT' => Float ,
21
+ 'TIMESTAMP' => DateTime ,
22
+ 'DATE' => Date ,
23
+ 'BOOLEAN' => Types::Boolean,
24
+ 'TEXT' => Types::Text
25
+ }[$1] || raise("unknown db type: #{db_type}")
26
+ end
27
+
28
+ ##
29
+ # Get the list of table names
30
+ #
31
+ # @return [String Array] the names of the tables in the database.
32
+ #
33
+ def get_storage_names
34
+ select(<<-SQL.compress_lines)
35
+ SELECT name
36
+ FROM (SELECT * FROM sqlite_master UNION SELECT * FROM sqlite_temp_master)
37
+ WHERE type IN('table', 'view')
38
+ AND name NOT LIKE 'sqlite_%'
39
+ ORDER BY name
40
+ SQL
41
+ end
42
+
43
+ ##
44
+ # Get the column specifications for a specific table
45
+ #
46
+ # @todo Consider returning actual DataMapper::Properties from this.
47
+ # It would probably require passing in a Model Object.
48
+ #
49
+ # @param [String] table the name of the table to get column specifications for
50
+ # @return [Hash] the column specs are returned in a hash keyed by `:name`, `:field`, `:type`, `:required`, `:default`, `:key`
51
+ #
52
+ def get_properties(table)
53
+ # TODO: consider using "SELECT sql FROM sqlite_master WHERE tbl_name = ?"
54
+ # and parsing the create table statement since it will provide
55
+ # more information like if a column is auto-incrementing, and what
56
+ # indexes are used.
57
+
58
+ select('PRAGMA table_info(%s)' % table).map do |column|
59
+ type = get_type(column.type)
60
+ default = column.dflt_value
61
+
62
+ if type == Integer && default
63
+ default = default.to_i
64
+ end
65
+
66
+ attribute = {
67
+ :name => column.name.downcase,
68
+ :type => type,
69
+ :required => column.notnull == 1,
70
+ :default => default,
71
+ :key => column.pk == 1,
72
+ }
73
+
74
+ # TODO: use the naming convention to compare the name vs the column name
75
+ unless attribute[:name] == column.name
76
+ attribute[:field] = column.name
77
+ end
78
+
79
+ attribute
80
+ end
81
+ end
82
+
83
+ end # module Sqlite3Adapter
84
+ end # module Reflection
85
+ end # module DataMapper