activerecord_csi 2.3.5.p6

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.
Files changed (333) hide show
  1. data/CHANGELOG +5858 -0
  2. data/README +351 -0
  3. data/RUNNING_UNIT_TESTS +36 -0
  4. data/Rakefile +270 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/performance.rb +162 -0
  7. data/install.rb +30 -0
  8. data/lib/active_record/aggregations.rb +261 -0
  9. data/lib/active_record/association_preload.rb +389 -0
  10. data/lib/active_record/associations/association_collection.rb +475 -0
  11. data/lib/active_record/associations/association_proxy.rb +278 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +76 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +53 -0
  14. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +143 -0
  15. data/lib/active_record/associations/has_many_association.rb +122 -0
  16. data/lib/active_record/associations/has_many_through_association.rb +266 -0
  17. data/lib/active_record/associations/has_one_association.rb +133 -0
  18. data/lib/active_record/associations/has_one_through_association.rb +37 -0
  19. data/lib/active_record/associations.rb +2241 -0
  20. data/lib/active_record/attribute_methods.rb +388 -0
  21. data/lib/active_record/autosave_association.rb +364 -0
  22. data/lib/active_record/base.rb +3171 -0
  23. data/lib/active_record/batches.rb +81 -0
  24. data/lib/active_record/calculations.rb +311 -0
  25. data/lib/active_record/callbacks.rb +360 -0
  26. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +371 -0
  27. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +139 -0
  28. data/lib/active_record/connection_adapters/abstract/database_statements.rb +289 -0
  29. data/lib/active_record/connection_adapters/abstract/query_cache.rb +94 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +722 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +434 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +241 -0
  34. data/lib/active_record/connection_adapters/mysql_adapter.rb +630 -0
  35. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1113 -0
  36. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  37. data/lib/active_record/connection_adapters/sqlite_adapter.rb +453 -0
  38. data/lib/active_record/dirty.rb +183 -0
  39. data/lib/active_record/dynamic_finder_match.rb +41 -0
  40. data/lib/active_record/dynamic_scope_match.rb +25 -0
  41. data/lib/active_record/fixtures.rb +996 -0
  42. data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
  43. data/lib/active_record/locale/en.yml +58 -0
  44. data/lib/active_record/locking/optimistic.rb +148 -0
  45. data/lib/active_record/locking/pessimistic.rb +55 -0
  46. data/lib/active_record/migration.rb +566 -0
  47. data/lib/active_record/named_scope.rb +192 -0
  48. data/lib/active_record/nested_attributes.rb +392 -0
  49. data/lib/active_record/observer.rb +197 -0
  50. data/lib/active_record/query_cache.rb +33 -0
  51. data/lib/active_record/reflection.rb +320 -0
  52. data/lib/active_record/schema.rb +51 -0
  53. data/lib/active_record/schema_dumper.rb +182 -0
  54. data/lib/active_record/serialization.rb +101 -0
  55. data/lib/active_record/serializers/json_serializer.rb +91 -0
  56. data/lib/active_record/serializers/xml_serializer.rb +357 -0
  57. data/lib/active_record/session_store.rb +326 -0
  58. data/lib/active_record/test_case.rb +66 -0
  59. data/lib/active_record/timestamp.rb +71 -0
  60. data/lib/active_record/transactions.rb +235 -0
  61. data/lib/active_record/validations.rb +1135 -0
  62. data/lib/active_record/version.rb +9 -0
  63. data/lib/active_record.rb +84 -0
  64. data/lib/activerecord.rb +2 -0
  65. data/test/assets/example.log +1 -0
  66. data/test/assets/flowers.jpg +0 -0
  67. data/test/cases/aaa_create_tables_test.rb +24 -0
  68. data/test/cases/active_schema_test_mysql.rb +100 -0
  69. data/test/cases/active_schema_test_postgresql.rb +24 -0
  70. data/test/cases/adapter_test.rb +145 -0
  71. data/test/cases/aggregations_test.rb +167 -0
  72. data/test/cases/ar_schema_test.rb +32 -0
  73. data/test/cases/associations/belongs_to_associations_test.rb +425 -0
  74. data/test/cases/associations/callbacks_test.rb +161 -0
  75. data/test/cases/associations/cascaded_eager_loading_test.rb +131 -0
  76. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  77. data/test/cases/associations/eager_load_nested_include_test.rb +130 -0
  78. data/test/cases/associations/eager_singularization_test.rb +145 -0
  79. data/test/cases/associations/eager_test.rb +834 -0
  80. data/test/cases/associations/extension_test.rb +62 -0
  81. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  82. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +822 -0
  83. data/test/cases/associations/has_many_associations_test.rb +1134 -0
  84. data/test/cases/associations/has_many_through_associations_test.rb +346 -0
  85. data/test/cases/associations/has_one_associations_test.rb +330 -0
  86. data/test/cases/associations/has_one_through_associations_test.rb +209 -0
  87. data/test/cases/associations/inner_join_association_test.rb +93 -0
  88. data/test/cases/associations/join_model_test.rb +712 -0
  89. data/test/cases/associations_test.rb +262 -0
  90. data/test/cases/attribute_methods_test.rb +305 -0
  91. data/test/cases/autosave_association_test.rb +1142 -0
  92. data/test/cases/base_test.rb +2154 -0
  93. data/test/cases/batches_test.rb +61 -0
  94. data/test/cases/binary_test.rb +30 -0
  95. data/test/cases/calculations_test.rb +348 -0
  96. data/test/cases/callbacks_observers_test.rb +38 -0
  97. data/test/cases/callbacks_test.rb +438 -0
  98. data/test/cases/class_inheritable_attributes_test.rb +32 -0
  99. data/test/cases/column_alias_test.rb +17 -0
  100. data/test/cases/column_definition_test.rb +70 -0
  101. data/test/cases/connection_pool_test.rb +25 -0
  102. data/test/cases/connection_test_firebird.rb +8 -0
  103. data/test/cases/connection_test_mysql.rb +64 -0
  104. data/test/cases/copy_table_test_sqlite.rb +80 -0
  105. data/test/cases/database_statements_test.rb +12 -0
  106. data/test/cases/datatype_test_postgresql.rb +204 -0
  107. data/test/cases/date_time_test.rb +37 -0
  108. data/test/cases/default_test_firebird.rb +16 -0
  109. data/test/cases/defaults_test.rb +111 -0
  110. data/test/cases/deprecated_finder_test.rb +30 -0
  111. data/test/cases/dirty_test.rb +316 -0
  112. data/test/cases/finder_respond_to_test.rb +76 -0
  113. data/test/cases/finder_test.rb +1066 -0
  114. data/test/cases/fixtures_test.rb +656 -0
  115. data/test/cases/helper.rb +68 -0
  116. data/test/cases/i18n_test.rb +46 -0
  117. data/test/cases/inheritance_test.rb +262 -0
  118. data/test/cases/invalid_date_test.rb +24 -0
  119. data/test/cases/json_serialization_test.rb +205 -0
  120. data/test/cases/lifecycle_test.rb +193 -0
  121. data/test/cases/locking_test.rb +304 -0
  122. data/test/cases/method_scoping_test.rb +704 -0
  123. data/test/cases/migration_test.rb +1523 -0
  124. data/test/cases/migration_test_firebird.rb +124 -0
  125. data/test/cases/mixin_test.rb +96 -0
  126. data/test/cases/modules_test.rb +81 -0
  127. data/test/cases/multiple_db_test.rb +85 -0
  128. data/test/cases/named_scope_test.rb +361 -0
  129. data/test/cases/nested_attributes_test.rb +581 -0
  130. data/test/cases/pk_test.rb +119 -0
  131. data/test/cases/pooled_connections_test.rb +103 -0
  132. data/test/cases/query_cache_test.rb +123 -0
  133. data/test/cases/readonly_test.rb +107 -0
  134. data/test/cases/reflection_test.rb +194 -0
  135. data/test/cases/reload_models_test.rb +22 -0
  136. data/test/cases/repair_helper.rb +50 -0
  137. data/test/cases/reserved_word_test_mysql.rb +176 -0
  138. data/test/cases/sanitize_test.rb +25 -0
  139. data/test/cases/schema_authorization_test_postgresql.rb +75 -0
  140. data/test/cases/schema_dumper_test.rb +211 -0
  141. data/test/cases/schema_test_postgresql.rb +178 -0
  142. data/test/cases/serialization_test.rb +47 -0
  143. data/test/cases/synonym_test_oracle.rb +17 -0
  144. data/test/cases/timestamp_test.rb +75 -0
  145. data/test/cases/transactions_test.rb +522 -0
  146. data/test/cases/unconnected_test.rb +32 -0
  147. data/test/cases/validations_i18n_test.rb +955 -0
  148. data/test/cases/validations_test.rb +1640 -0
  149. data/test/cases/xml_serialization_test.rb +240 -0
  150. data/test/config.rb +5 -0
  151. data/test/connections/jdbc_jdbcderby/connection.rb +18 -0
  152. data/test/connections/jdbc_jdbch2/connection.rb +18 -0
  153. data/test/connections/jdbc_jdbchsqldb/connection.rb +18 -0
  154. data/test/connections/jdbc_jdbcmysql/connection.rb +26 -0
  155. data/test/connections/jdbc_jdbcpostgresql/connection.rb +26 -0
  156. data/test/connections/jdbc_jdbcsqlite3/connection.rb +25 -0
  157. data/test/connections/native_db2/connection.rb +25 -0
  158. data/test/connections/native_firebird/connection.rb +26 -0
  159. data/test/connections/native_frontbase/connection.rb +27 -0
  160. data/test/connections/native_mysql/connection.rb +25 -0
  161. data/test/connections/native_openbase/connection.rb +21 -0
  162. data/test/connections/native_oracle/connection.rb +27 -0
  163. data/test/connections/native_postgresql/connection.rb +25 -0
  164. data/test/connections/native_sqlite/connection.rb +25 -0
  165. data/test/connections/native_sqlite3/connection.rb +25 -0
  166. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  167. data/test/connections/native_sybase/connection.rb +23 -0
  168. data/test/fixtures/accounts.yml +29 -0
  169. data/test/fixtures/all/developers.yml +0 -0
  170. data/test/fixtures/all/people.csv +0 -0
  171. data/test/fixtures/all/tasks.yml +0 -0
  172. data/test/fixtures/author_addresses.yml +5 -0
  173. data/test/fixtures/author_favorites.yml +4 -0
  174. data/test/fixtures/authors.yml +9 -0
  175. data/test/fixtures/binaries.yml +132 -0
  176. data/test/fixtures/books.yml +7 -0
  177. data/test/fixtures/categories/special_categories.yml +9 -0
  178. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  179. data/test/fixtures/categories.yml +14 -0
  180. data/test/fixtures/categories_ordered.yml +7 -0
  181. data/test/fixtures/categories_posts.yml +23 -0
  182. data/test/fixtures/categorizations.yml +17 -0
  183. data/test/fixtures/clubs.yml +6 -0
  184. data/test/fixtures/comments.yml +59 -0
  185. data/test/fixtures/companies.yml +56 -0
  186. data/test/fixtures/computers.yml +4 -0
  187. data/test/fixtures/courses.yml +7 -0
  188. data/test/fixtures/customers.yml +26 -0
  189. data/test/fixtures/developers.yml +21 -0
  190. data/test/fixtures/developers_projects.yml +17 -0
  191. data/test/fixtures/edges.yml +6 -0
  192. data/test/fixtures/entrants.yml +14 -0
  193. data/test/fixtures/fixture_database.sqlite3 +0 -0
  194. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  195. data/test/fixtures/fk_test_has_fk.yml +3 -0
  196. data/test/fixtures/fk_test_has_pk.yml +2 -0
  197. data/test/fixtures/funny_jokes.yml +10 -0
  198. data/test/fixtures/items.yml +4 -0
  199. data/test/fixtures/jobs.yml +7 -0
  200. data/test/fixtures/legacy_things.yml +3 -0
  201. data/test/fixtures/mateys.yml +4 -0
  202. data/test/fixtures/member_types.yml +6 -0
  203. data/test/fixtures/members.yml +6 -0
  204. data/test/fixtures/memberships.yml +20 -0
  205. data/test/fixtures/minimalistics.yml +2 -0
  206. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  207. data/test/fixtures/mixins.yml +29 -0
  208. data/test/fixtures/movies.yml +7 -0
  209. data/test/fixtures/naked/csv/accounts.csv +1 -0
  210. data/test/fixtures/naked/yml/accounts.yml +1 -0
  211. data/test/fixtures/naked/yml/companies.yml +1 -0
  212. data/test/fixtures/naked/yml/courses.yml +1 -0
  213. data/test/fixtures/organizations.yml +5 -0
  214. data/test/fixtures/owners.yml +7 -0
  215. data/test/fixtures/parrots.yml +27 -0
  216. data/test/fixtures/parrots_pirates.yml +7 -0
  217. data/test/fixtures/people.yml +15 -0
  218. data/test/fixtures/pets.yml +14 -0
  219. data/test/fixtures/pirates.yml +9 -0
  220. data/test/fixtures/posts.yml +52 -0
  221. data/test/fixtures/price_estimates.yml +7 -0
  222. data/test/fixtures/projects.yml +7 -0
  223. data/test/fixtures/readers.yml +9 -0
  224. data/test/fixtures/references.yml +17 -0
  225. data/test/fixtures/reserved_words/distinct.yml +5 -0
  226. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  227. data/test/fixtures/reserved_words/group.yml +14 -0
  228. data/test/fixtures/reserved_words/select.yml +8 -0
  229. data/test/fixtures/reserved_words/values.yml +7 -0
  230. data/test/fixtures/ships.yml +5 -0
  231. data/test/fixtures/sponsors.yml +9 -0
  232. data/test/fixtures/subscribers.yml +7 -0
  233. data/test/fixtures/subscriptions.yml +12 -0
  234. data/test/fixtures/taggings.yml +28 -0
  235. data/test/fixtures/tags.yml +7 -0
  236. data/test/fixtures/tasks.yml +7 -0
  237. data/test/fixtures/topics.yml +42 -0
  238. data/test/fixtures/toys.yml +4 -0
  239. data/test/fixtures/treasures.yml +10 -0
  240. data/test/fixtures/vertices.yml +4 -0
  241. data/test/fixtures/warehouse-things.yml +3 -0
  242. data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
  243. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  244. data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
  245. data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
  246. data/test/migrations/duplicate/3_foo.rb +7 -0
  247. data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
  248. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  249. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  250. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
  251. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
  252. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
  253. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
  254. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  255. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  256. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  257. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  258. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  259. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  260. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  261. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  262. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  263. data/test/models/author.rb +146 -0
  264. data/test/models/auto_id.rb +4 -0
  265. data/test/models/binary.rb +2 -0
  266. data/test/models/bird.rb +3 -0
  267. data/test/models/book.rb +4 -0
  268. data/test/models/categorization.rb +5 -0
  269. data/test/models/category.rb +34 -0
  270. data/test/models/citation.rb +6 -0
  271. data/test/models/club.rb +13 -0
  272. data/test/models/column_name.rb +3 -0
  273. data/test/models/comment.rb +29 -0
  274. data/test/models/company.rb +171 -0
  275. data/test/models/company_in_module.rb +61 -0
  276. data/test/models/computer.rb +3 -0
  277. data/test/models/contact.rb +16 -0
  278. data/test/models/contract.rb +5 -0
  279. data/test/models/course.rb +3 -0
  280. data/test/models/customer.rb +73 -0
  281. data/test/models/default.rb +2 -0
  282. data/test/models/developer.rb +101 -0
  283. data/test/models/edge.rb +5 -0
  284. data/test/models/entrant.rb +3 -0
  285. data/test/models/essay.rb +3 -0
  286. data/test/models/event.rb +3 -0
  287. data/test/models/guid.rb +2 -0
  288. data/test/models/item.rb +7 -0
  289. data/test/models/job.rb +5 -0
  290. data/test/models/joke.rb +3 -0
  291. data/test/models/keyboard.rb +3 -0
  292. data/test/models/legacy_thing.rb +3 -0
  293. data/test/models/matey.rb +4 -0
  294. data/test/models/member.rb +12 -0
  295. data/test/models/member_detail.rb +5 -0
  296. data/test/models/member_type.rb +3 -0
  297. data/test/models/membership.rb +9 -0
  298. data/test/models/minimalistic.rb +2 -0
  299. data/test/models/mixed_case_monkey.rb +3 -0
  300. data/test/models/movie.rb +5 -0
  301. data/test/models/order.rb +4 -0
  302. data/test/models/organization.rb +6 -0
  303. data/test/models/owner.rb +5 -0
  304. data/test/models/parrot.rb +16 -0
  305. data/test/models/person.rb +16 -0
  306. data/test/models/pet.rb +5 -0
  307. data/test/models/pirate.rb +70 -0
  308. data/test/models/post.rb +100 -0
  309. data/test/models/price_estimate.rb +3 -0
  310. data/test/models/project.rb +30 -0
  311. data/test/models/reader.rb +4 -0
  312. data/test/models/reference.rb +4 -0
  313. data/test/models/reply.rb +46 -0
  314. data/test/models/ship.rb +10 -0
  315. data/test/models/ship_part.rb +5 -0
  316. data/test/models/sponsor.rb +4 -0
  317. data/test/models/subject.rb +4 -0
  318. data/test/models/subscriber.rb +8 -0
  319. data/test/models/subscription.rb +4 -0
  320. data/test/models/tag.rb +7 -0
  321. data/test/models/tagging.rb +10 -0
  322. data/test/models/task.rb +3 -0
  323. data/test/models/topic.rb +80 -0
  324. data/test/models/toy.rb +6 -0
  325. data/test/models/treasure.rb +8 -0
  326. data/test/models/vertex.rb +9 -0
  327. data/test/models/warehouse_thing.rb +5 -0
  328. data/test/schema/mysql_specific_schema.rb +24 -0
  329. data/test/schema/postgresql_specific_schema.rb +114 -0
  330. data/test/schema/schema.rb +493 -0
  331. data/test/schema/schema2.rb +6 -0
  332. data/test/schema/sqlite_specific_schema.rb +25 -0
  333. metadata +420 -0
@@ -0,0 +1,722 @@
1
+ require 'date'
2
+ require 'set'
3
+ require 'bigdecimal'
4
+ require 'bigdecimal/util'
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters #:nodoc:
8
+ # An abstract definition of a column in a table.
9
+ class Column
10
+ TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
11
+ FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
12
+
13
+ module Format
14
+ ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
15
+ ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
16
+ end
17
+
18
+ attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
19
+ attr_accessor :primary
20
+
21
+ # Instantiates a new column in the table.
22
+ #
23
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
24
+ # +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
25
+ # +sql_type+ is only used to extract the column's length, if necessary. For example +60+ in <tt>company_name varchar(60)</tt>.
26
+ # +null+ determines if this column allows +NULL+ values.
27
+ def initialize(name, default, sql_type = nil, null = true)
28
+ @name, @sql_type, @null = name, sql_type, null
29
+ @limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type)
30
+ @type = simplified_type(sql_type)
31
+ @default = extract_default(default)
32
+
33
+ @primary = nil
34
+ end
35
+
36
+ # Returns +true+ if the column is either of type string or text.
37
+ def text?
38
+ type == :string || type == :text
39
+ end
40
+
41
+ # Returns +true+ if the column is either of type integer, float or decimal.
42
+ def number?
43
+ type == :integer || type == :float || type == :decimal
44
+ end
45
+
46
+ def has_default?
47
+ !default.nil?
48
+ end
49
+
50
+ # Returns the Ruby class that corresponds to the abstract data type.
51
+ def klass
52
+ case type
53
+ when :integer then Fixnum
54
+ when :float then Float
55
+ when :decimal then BigDecimal
56
+ when :datetime then Time
57
+ when :date then Date
58
+ when :timestamp then Time
59
+ when :time then Time
60
+ when :text, :string then String
61
+ when :binary then String
62
+ when :boolean then Object
63
+ end
64
+ end
65
+
66
+ # Casts value (which is a String) to an appropriate instance.
67
+ def type_cast(value)
68
+ return nil if value.nil?
69
+ case type
70
+ when :string then value
71
+ when :text then value
72
+ when :integer then value.to_i rescue value ? 1 : 0
73
+ when :float then value.to_f
74
+ when :decimal then self.class.value_to_decimal(value)
75
+ when :datetime then self.class.string_to_time(value)
76
+ when :timestamp then self.class.string_to_time(value)
77
+ when :time then self.class.string_to_dummy_time(value)
78
+ when :date then self.class.string_to_date(value)
79
+ when :binary then self.class.binary_to_string(value)
80
+ when :boolean then self.class.value_to_boolean(value)
81
+ else value
82
+ end
83
+ end
84
+
85
+ def type_cast_code(var_name)
86
+ case type
87
+ when :string then nil
88
+ when :text then nil
89
+ when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
90
+ when :float then "#{var_name}.to_f"
91
+ when :decimal then "#{self.class.name}.value_to_decimal(#{var_name})"
92
+ when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
93
+ when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
94
+ when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})"
95
+ when :date then "#{self.class.name}.string_to_date(#{var_name})"
96
+ when :binary then "#{self.class.name}.binary_to_string(#{var_name})"
97
+ when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
98
+ else nil
99
+ end
100
+ end
101
+
102
+ # Returns the human name of the column name.
103
+ #
104
+ # ===== Examples
105
+ # Column.new('sales_stage', ...).human_name # => 'Sales stage'
106
+ def human_name
107
+ Base.human_attribute_name(@name)
108
+ end
109
+
110
+ def extract_default(default)
111
+ type_cast(default)
112
+ end
113
+
114
+ class << self
115
+ # Used to convert from Strings to BLOBs
116
+ def string_to_binary(value)
117
+ value
118
+ end
119
+
120
+ # Used to convert from BLOBs to Strings
121
+ def binary_to_string(value)
122
+ value
123
+ end
124
+
125
+ def string_to_date(string)
126
+ return string unless string.is_a?(String)
127
+ return nil if string.empty?
128
+
129
+ fast_string_to_date(string) || fallback_string_to_date(string)
130
+ end
131
+
132
+ def string_to_time(string)
133
+ return string unless string.is_a?(String)
134
+ return nil if string.empty?
135
+
136
+ fast_string_to_time(string) || fallback_string_to_time(string)
137
+ end
138
+
139
+ def string_to_dummy_time(string)
140
+ return string unless string.is_a?(String)
141
+ return nil if string.empty?
142
+
143
+ string_to_time "2000-01-01 #{string}"
144
+ end
145
+
146
+ # convert something to a boolean
147
+ def value_to_boolean(value)
148
+ if value.is_a?(String) && value.blank?
149
+ nil
150
+ else
151
+ TRUE_VALUES.include?(value)
152
+ end
153
+ end
154
+
155
+ # convert something to a BigDecimal
156
+ def value_to_decimal(value)
157
+ # Using .class is faster than .is_a? and
158
+ # subclasses of BigDecimal will be handled
159
+ # in the else clause
160
+ if value.class == BigDecimal
161
+ value
162
+ elsif value.respond_to?(:to_d)
163
+ value.to_d
164
+ else
165
+ value.to_s.to_d
166
+ end
167
+ end
168
+
169
+ protected
170
+ # '0.123456' -> 123456
171
+ # '1.123456' -> 123456
172
+ def microseconds(time)
173
+ ((time[:sec_fraction].to_f % 1) * 1_000_000).to_i
174
+ end
175
+
176
+ def new_date(year, mon, mday)
177
+ if year && year != 0
178
+ Date.new(year, mon, mday) rescue nil
179
+ end
180
+ end
181
+
182
+ def new_time(year, mon, mday, hour, min, sec, microsec)
183
+ # Treat 0000-00-00 00:00:00 as nil.
184
+ return nil if year.nil? || year == 0
185
+
186
+ Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
187
+ end
188
+
189
+ def fast_string_to_date(string)
190
+ if string =~ Format::ISO_DATE
191
+ new_date $1.to_i, $2.to_i, $3.to_i
192
+ end
193
+ end
194
+
195
+ # Doesn't handle time zones.
196
+ def fast_string_to_time(string)
197
+ if string =~ Format::ISO_DATETIME
198
+ microsec = ($7.to_f * 1_000_000).to_i
199
+ new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
200
+ end
201
+ end
202
+
203
+ def fallback_string_to_date(string)
204
+ new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
205
+ end
206
+
207
+ def fallback_string_to_time(string)
208
+ time_hash = Date._parse(string)
209
+ time_hash[:sec_fraction] = microseconds(time_hash)
210
+
211
+ new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
212
+ end
213
+ end
214
+
215
+ private
216
+ def extract_limit(sql_type)
217
+ $1.to_i if sql_type =~ /\((.*)\)/
218
+ end
219
+
220
+ def extract_precision(sql_type)
221
+ $2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
222
+ end
223
+
224
+ def extract_scale(sql_type)
225
+ case sql_type
226
+ when /^(numeric|decimal|number)\((\d+)\)/i then 0
227
+ when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then $4.to_i
228
+ end
229
+ end
230
+
231
+ def simplified_type(field_type)
232
+ case field_type
233
+ when /int/i
234
+ :integer
235
+ when /float|double/i
236
+ :float
237
+ when /decimal|numeric|number/i
238
+ extract_scale(field_type) == 0 ? :integer : :decimal
239
+ when /datetime/i
240
+ :datetime
241
+ when /timestamp/i
242
+ :timestamp
243
+ when /time/i
244
+ :time
245
+ when /date/i
246
+ :date
247
+ when /clob/i, /text/i
248
+ :text
249
+ when /blob/i, /binary/i
250
+ :binary
251
+ when /char/i, /string/i
252
+ :string
253
+ when /boolean/i
254
+ :boolean
255
+ end
256
+ end
257
+ end
258
+
259
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
260
+ end
261
+
262
+ # Abstract representation of a column definition. Instances of this type
263
+ # are typically created by methods in TableDefinition, and added to the
264
+ # +columns+ attribute of said TableDefinition object, in order to be used
265
+ # for generating a number of table creation or table changing SQL statements.
266
+ class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
267
+
268
+ def sql_type
269
+ base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
270
+ end
271
+
272
+ def to_sql
273
+ column_sql = "#{base.quote_column_name(name)} #{sql_type}"
274
+ column_options = {}
275
+ column_options[:null] = null unless null.nil?
276
+ column_options[:default] = default unless default.nil?
277
+ add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
278
+ column_sql
279
+ end
280
+
281
+ private
282
+
283
+ def add_column_options!(sql, options)
284
+ base.add_column_options!(sql, options.merge(:column => self))
285
+ end
286
+ end
287
+
288
+ # Represents the schema of an SQL table in an abstract way. This class
289
+ # provides methods for manipulating the schema representation.
290
+ #
291
+ # Inside migration files, the +t+ object in +create_table+ and
292
+ # +change_table+ is actually of this type:
293
+ #
294
+ # class SomeMigration < ActiveRecord::Migration
295
+ # def self.up
296
+ # create_table :foo do |t|
297
+ # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
298
+ # end
299
+ # end
300
+ #
301
+ # def self.down
302
+ # ...
303
+ # end
304
+ # end
305
+ #
306
+ # The table definitions
307
+ # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
308
+ class TableDefinition
309
+ # An array of ColumnDefinition objects, representing the column changes
310
+ # that have been defined.
311
+ attr_accessor :columns
312
+
313
+ def initialize(base)
314
+ @columns = []
315
+ @base = base
316
+ end
317
+
318
+ #Handles non supported datatypes - e.g. XML
319
+ def method_missing(symbol, *args)
320
+ if symbol.to_s == 'xml'
321
+ xml_column_fallback(args)
322
+ end
323
+ end
324
+
325
+ def xml_column_fallback(*args)
326
+ case @base.adapter_name.downcase
327
+ when 'sqlite', 'mysql'
328
+ options = args.extract_options!
329
+ column(args[0], :text, options)
330
+ end
331
+ end
332
+ # Appends a primary key definition to the table definition.
333
+ # Can be called multiple times, but this is probably not a good idea.
334
+ def primary_key(name)
335
+ column(name, :primary_key)
336
+ end
337
+
338
+ # Returns a ColumnDefinition for the column with name +name+.
339
+ def [](name)
340
+ @columns.find {|column| column.name.to_s == name.to_s}
341
+ end
342
+
343
+ # Instantiates a new column for the table.
344
+ # The +type+ parameter is normally one of the migrations native types,
345
+ # which is one of the following:
346
+ # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
347
+ # <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
348
+ # <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>,
349
+ # <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.
350
+ #
351
+ # You may use a type not in this list as long as it is supported by your
352
+ # database (for example, "polygon" in MySQL), but this will not be database
353
+ # agnostic and should usually be avoided.
354
+ #
355
+ # Available options are (none of these exists by default):
356
+ # * <tt>:limit</tt> -
357
+ # Requests a maximum column length. This is number of characters for <tt>:string</tt> and <tt>:text</tt> columns and number of bytes for :binary and :integer columns.
358
+ # * <tt>:default</tt> -
359
+ # The column's default value. Use nil for NULL.
360
+ # * <tt>:null</tt> -
361
+ # Allows or disallows +NULL+ values in the column. This option could
362
+ # have been named <tt>:null_allowed</tt>.
363
+ # * <tt>:precision</tt> -
364
+ # Specifies the precision for a <tt>:decimal</tt> column.
365
+ # * <tt>:scale</tt> -
366
+ # Specifies the scale for a <tt>:decimal</tt> column.
367
+ #
368
+ # For clarity's sake: the precision is the number of significant digits,
369
+ # while the scale is the number of digits that can be stored following
370
+ # the decimal point. For example, the number 123.45 has a precision of 5
371
+ # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
372
+ # range from -999.99 to 999.99.
373
+ #
374
+ # Please be aware of different RDBMS implementations behavior with
375
+ # <tt>:decimal</tt> columns:
376
+ # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
377
+ # <tt>:precision</tt>, and makes no comments about the requirements of
378
+ # <tt>:precision</tt>.
379
+ # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
380
+ # Default is (10,0).
381
+ # * PostgreSQL: <tt>:precision</tt> [1..infinity],
382
+ # <tt>:scale</tt> [0..infinity]. No default.
383
+ # * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
384
+ # Internal storage as strings. No default.
385
+ # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
386
+ # but the maximum supported <tt>:precision</tt> is 16. No default.
387
+ # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
388
+ # Default is (38,0).
389
+ # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
390
+ # Default unknown.
391
+ # * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
392
+ # Default (9,0). Internal types NUMERIC and DECIMAL have different
393
+ # storage rules, decimal being better.
394
+ # * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
395
+ # Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
396
+ # NUMERIC is 19, and DECIMAL is 38.
397
+ # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
398
+ # Default (38,0).
399
+ # * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
400
+ # Default (38,0).
401
+ # * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
402
+ #
403
+ # This method returns <tt>self</tt>.
404
+ #
405
+ # == Examples
406
+ # # Assuming td is an instance of TableDefinition
407
+ # td.column(:granted, :boolean)
408
+ # # granted BOOLEAN
409
+ #
410
+ # td.column(:picture, :binary, :limit => 2.megabytes)
411
+ # # => picture BLOB(2097152)
412
+ #
413
+ # td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false)
414
+ # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
415
+ #
416
+ # td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
417
+ # # => bill_gates_money DECIMAL(15,2)
418
+ #
419
+ # td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)
420
+ # # => sensor_reading DECIMAL(30,20)
421
+ #
422
+ # # While <tt>:scale</tt> defaults to zero on most databases, it
423
+ # # probably wouldn't hurt to include it.
424
+ # td.column(:huge_integer, :decimal, :precision => 30)
425
+ # # => huge_integer DECIMAL(30)
426
+ #
427
+ # # Defines a column with a database-specific type.
428
+ # td.column(:foo, 'polygon')
429
+ # # => foo polygon
430
+ #
431
+ # == Short-hand examples
432
+ #
433
+ # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
434
+ # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
435
+ # in a single statement.
436
+ #
437
+ # What can be written like this with the regular calls to column:
438
+ #
439
+ # create_table "products", :force => true do |t|
440
+ # t.column "shop_id", :integer
441
+ # t.column "creator_id", :integer
442
+ # t.column "name", :string, :default => "Untitled"
443
+ # t.column "value", :string, :default => "Untitled"
444
+ # t.column "created_at", :datetime
445
+ # t.column "updated_at", :datetime
446
+ # end
447
+ #
448
+ # Can also be written as follows using the short-hand:
449
+ #
450
+ # create_table :products do |t|
451
+ # t.integer :shop_id, :creator_id
452
+ # t.string :name, :value, :default => "Untitled"
453
+ # t.timestamps
454
+ # end
455
+ #
456
+ # There's a short-hand method for each of the type values declared at the top. And then there's
457
+ # TableDefinition#timestamps that'll add created_at and +updated_at+ as datetimes.
458
+ #
459
+ # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
460
+ # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of options, these will be
461
+ # used when creating the <tt>_type</tt> column. So what can be written like this:
462
+ #
463
+ # create_table :taggings do |t|
464
+ # t.integer :tag_id, :tagger_id, :taggable_id
465
+ # t.string :tagger_type
466
+ # t.string :taggable_type, :default => 'Photo'
467
+ # end
468
+ #
469
+ # Can also be written as follows using references:
470
+ #
471
+ # create_table :taggings do |t|
472
+ # t.references :tag
473
+ # t.references :tagger, :polymorphic => true
474
+ # t.references :taggable, :polymorphic => { :default => 'Photo' }
475
+ # end
476
+ def column(name, type, options = {})
477
+ column = self[name] || ColumnDefinition.new(@base, name, type)
478
+ if options[:limit]
479
+ column.limit = options[:limit]
480
+ elsif native[type.to_sym].is_a?(Hash)
481
+ column.limit = native[type.to_sym][:limit]
482
+ end
483
+ column.precision = options[:precision]
484
+ column.scale = options[:scale]
485
+ column.default = options[:default]
486
+ column.null = options[:null]
487
+ @columns << column unless @columns.include? column
488
+ self
489
+ end
490
+
491
+ %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
492
+ class_eval <<-EOV
493
+ def #{column_type}(*args) # def string(*args)
494
+ options = args.extract_options! # options = args.extract_options!
495
+ column_names = args # column_names = args
496
+ #
497
+ column_names.each { |name| column(name, '#{column_type}', options) } # column_names.each { |name| column(name, 'string', options) }
498
+ end # end
499
+ EOV
500
+ end
501
+
502
+ # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
503
+ # <tt>:updated_at</tt> to the table.
504
+ def timestamps(*args)
505
+ options = args.extract_options!
506
+ column(:created_at, :datetime, options)
507
+ column(:updated_at, :datetime, options)
508
+ end
509
+
510
+ def references(*args)
511
+ options = args.extract_options!
512
+ polymorphic = options.delete(:polymorphic)
513
+ args.each do |col|
514
+ column("#{col}_id", :integer, options)
515
+ column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
516
+ end
517
+ end
518
+ alias :belongs_to :references
519
+
520
+ # Returns a String whose contents are the column definitions
521
+ # concatenated together. This string can then be prepended and appended to
522
+ # to generate the final SQL to create the table.
523
+ def to_sql
524
+ @columns.map(&:to_sql) * ', '
525
+ end
526
+
527
+ private
528
+ def native
529
+ @base.native_database_types
530
+ end
531
+ end
532
+
533
+ # Represents a SQL table in an abstract way for updating a table.
534
+ # Also see TableDefinition and SchemaStatements#create_table
535
+ #
536
+ # Available transformations are:
537
+ #
538
+ # change_table :table do |t|
539
+ # t.column
540
+ # t.index
541
+ # t.timestamps
542
+ # t.change
543
+ # t.change_default
544
+ # t.rename
545
+ # t.references
546
+ # t.belongs_to
547
+ # t.string
548
+ # t.text
549
+ # t.integer
550
+ # t.float
551
+ # t.decimal
552
+ # t.datetime
553
+ # t.timestamp
554
+ # t.time
555
+ # t.date
556
+ # t.binary
557
+ # t.boolean
558
+ # t.remove
559
+ # t.remove_references
560
+ # t.remove_belongs_to
561
+ # t.remove_index
562
+ # t.remove_timestamps
563
+ # end
564
+ #
565
+ class Table
566
+ def initialize(table_name, base)
567
+ @table_name = table_name
568
+ @base = base
569
+ end
570
+
571
+ # Adds a new column to the named table.
572
+ # See TableDefinition#column for details of the options you can use.
573
+ # ===== Example
574
+ # ====== Creating a simple column
575
+ # t.column(:name, :string)
576
+ def column(column_name, type, options = {})
577
+ @base.add_column(@table_name, column_name, type, options)
578
+ end
579
+
580
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
581
+ # an Array of Symbols. See SchemaStatements#add_index
582
+ #
583
+ # ===== Examples
584
+ # ====== Creating a simple index
585
+ # t.index(:name)
586
+ # ====== Creating a unique index
587
+ # t.index([:branch_id, :party_id], :unique => true)
588
+ # ====== Creating a named index
589
+ # t.index([:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
590
+ def index(column_name, options = {})
591
+ @base.add_index(@table_name, column_name, options)
592
+ end
593
+
594
+ # Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#add_timestamps
595
+ # ===== Example
596
+ # t.timestamps
597
+ def timestamps
598
+ @base.add_timestamps(@table_name)
599
+ end
600
+
601
+ # Changes the column's definition according to the new options.
602
+ # See TableDefinition#column for details of the options you can use.
603
+ # ===== Examples
604
+ # t.change(:name, :string, :limit => 80)
605
+ # t.change(:description, :text)
606
+ def change(column_name, type, options = {})
607
+ @base.change_column(@table_name, column_name, type, options)
608
+ end
609
+
610
+ # Sets a new default value for a column. See SchemaStatements#change_column_default
611
+ # ===== Examples
612
+ # t.change_default(:qualification, 'new')
613
+ # t.change_default(:authorized, 1)
614
+ def change_default(column_name, default)
615
+ @base.change_column_default(@table_name, column_name, default)
616
+ end
617
+
618
+ # Removes the column(s) from the table definition.
619
+ # ===== Examples
620
+ # t.remove(:qualification)
621
+ # t.remove(:qualification, :experience)
622
+ def remove(*column_names)
623
+ @base.remove_column(@table_name, column_names)
624
+ end
625
+
626
+ # Removes the given index from the table.
627
+ #
628
+ # ===== Examples
629
+ # ====== Remove the suppliers_name_index in the suppliers table
630
+ # t.remove_index :name
631
+ # ====== Remove the index named accounts_branch_id_index in the accounts table
632
+ # t.remove_index :column => :branch_id
633
+ # ====== Remove the index named accounts_branch_id_party_id_index in the accounts table
634
+ # t.remove_index :column => [:branch_id, :party_id]
635
+ # ====== Remove the index named by_branch_party in the accounts table
636
+ # t.remove_index :name => :by_branch_party
637
+ def remove_index(options = {})
638
+ @base.remove_index(@table_name, options)
639
+ end
640
+
641
+ # Removes the timestamp columns (created_at and updated_at) from the table.
642
+ # ===== Example
643
+ # t.remove_timestamps
644
+ def remove_timestamps
645
+ @base.remove_timestamps(@table_name)
646
+ end
647
+
648
+ # Renames a column.
649
+ # ===== Example
650
+ # t.rename(:description, :name)
651
+ def rename(column_name, new_column_name)
652
+ @base.rename_column(@table_name, column_name, new_column_name)
653
+ end
654
+
655
+ # Adds a reference. Optionally adds a +type+ column.
656
+ # <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
657
+ # ===== Examples
658
+ # t.references(:goat)
659
+ # t.references(:goat, :polymorphic => true)
660
+ # t.belongs_to(:goat)
661
+ def references(*args)
662
+ options = args.extract_options!
663
+ polymorphic = options.delete(:polymorphic)
664
+ args.each do |col|
665
+ @base.add_column(@table_name, "#{col}_id", :integer, options)
666
+ @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
667
+ end
668
+ end
669
+ alias :belongs_to :references
670
+
671
+ # Removes a reference. Optionally removes a +type+ column.
672
+ # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
673
+ # ===== Examples
674
+ # t.remove_references(:goat)
675
+ # t.remove_references(:goat, :polymorphic => true)
676
+ # t.remove_belongs_to(:goat)
677
+ def remove_references(*args)
678
+ options = args.extract_options!
679
+ polymorphic = options.delete(:polymorphic)
680
+ args.each do |col|
681
+ @base.remove_column(@table_name, "#{col}_id")
682
+ @base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
683
+ end
684
+ end
685
+ alias :remove_belongs_to :remove_references
686
+
687
+ # Adds a column or columns of a specified type
688
+ # ===== Examples
689
+ # t.string(:goat)
690
+ # t.string(:goat, :sheep)
691
+ %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
692
+ class_eval <<-EOV
693
+ def #{column_type}(*args) # def string(*args)
694
+ options = args.extract_options! # options = args.extract_options!
695
+ column_names = args # column_names = args
696
+ #
697
+ column_names.each do |name| # column_names.each do |name|
698
+ column = ColumnDefinition.new(@base, name, '#{column_type}') # column = ColumnDefinition.new(@base, name, 'string')
699
+ if options[:limit] # if options[:limit]
700
+ column.limit = options[:limit] # column.limit = options[:limit]
701
+ elsif native['#{column_type}'.to_sym].is_a?(Hash) # elsif native['string'.to_sym].is_a?(Hash)
702
+ column.limit = native['#{column_type}'.to_sym][:limit] # column.limit = native['string'.to_sym][:limit]
703
+ end # end
704
+ column.precision = options[:precision] # column.precision = options[:precision]
705
+ column.scale = options[:scale] # column.scale = options[:scale]
706
+ column.default = options[:default] # column.default = options[:default]
707
+ column.null = options[:null] # column.null = options[:null]
708
+ @base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
709
+ end # end
710
+ end # end
711
+ EOV
712
+ end
713
+
714
+ private
715
+ def native
716
+ @base.native_database_types
717
+ end
718
+ end
719
+
720
+ end
721
+ end
722
+