sequel 3.21.0 → 3.39.0

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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
data/MIT-LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  Copyright (c) 2007-2008 Sharon Rosner
2
- Copyright (c) 2008-2011 Jeremy Evans
2
+ Copyright (c) 2008-2012 Jeremy Evans
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to
data/README.rdoc CHANGED
@@ -12,15 +12,15 @@ toolkit for Ruby.
12
12
  two-phase commit, transaction isolation, master/slave
13
13
  configurations, and database sharding.
14
14
  * Sequel currently has adapters for ADO, Amalgalite, DataObjects,
15
- DB2, DBI, Firebird, Informix, JDBC, MySQL, Mysql2, ODBC, OpenBase,
16
- Oracle, PostgreSQL, SQLite3, Swift, and TinyTDS.
15
+ DB2, DBI, Firebird, IBM_DB, Informix, JDBC, MySQL, Mysql2, ODBC,
16
+ OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and TinyTDS.
17
17
 
18
18
  == Resources
19
19
 
20
20
  * {Website}[http://sequel.rubyforge.org]
21
21
  * {Blog}[http://sequel.heroku.com]
22
22
  * {Source code}[http://github.com/jeremyevans/sequel]
23
- * {Bug tracking}[http://code.google.com/p/ruby-sequel/issues/list]
23
+ * {Bug tracking}[http://github.com/jeremyevans/sequel/issues]
24
24
  * {Google group}[http://groups.google.com/group/sequel-talk]
25
25
  * {RDoc}[http://sequel.rubyforge.org/rdoc]
26
26
 
@@ -64,12 +64,14 @@ If you have any comments or suggestions please post to the Google group.
64
64
 
65
65
  == The Sequel Console
66
66
 
67
- Sequel includes an IRB console for quick access to databases. You can use it like this:
67
+ Sequel includes an IRB console for quick access to databases (usually referred to as <tt>bin/sequel</tt>). You can use it like this:
68
68
 
69
69
  sequel sqlite://test.db # test.db in current directory
70
70
 
71
71
  You get an IRB session with the database object stored in DB.
72
72
 
73
+ In addition to providing an IRB shell (the default behavior), bin/sequel also has support for migrating databases (-m and -M), dumping schema migrations (-d and -D), and copying databases (-C).
74
+
73
75
  == An Introduction
74
76
 
75
77
  Sequel is designed to take the hassle away from connecting to databases and manipulating them. Sequel deals with all the boring stuff like maintaining connections, formatting SQL correctly and fetching records so you can concentrate on your application.
@@ -91,11 +93,11 @@ Since datasets retrieve records only when needed, they can be stored and later r
91
93
 
92
94
  Sequel also offers convenience methods for extracting data from Datasets, such as an extended +map+ method:
93
95
 
94
- middle_east.map(:name) #=> ['Egypt', 'Greece', 'Israel', ...]
96
+ middle_east.map(:name) #=> ['Egypt', 'Turkey', 'Israel', ...]
95
97
 
96
98
  Or getting results as a hash via +to_hash+, with one column as key and another as value:
97
99
 
98
- middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Greece' => 120000, ...}
100
+ middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Turkey' => 120000, ...}
99
101
 
100
102
  == Getting Started
101
103
 
@@ -169,7 +171,7 @@ You can also iterate through records one at a time using +each+:
169
171
 
170
172
  Or perform more advanced stuff:
171
173
 
172
- names_and_dates = posts.map{|r| [r[:name], r[:date]]}
174
+ names_and_dates = posts.map([:name, :date])
173
175
  old_posts, recent_posts = posts.partition{|r| r[:date] < Date.today - 7}
174
176
 
175
177
  You can also retrieve the first record in a dataset:
@@ -189,29 +191,29 @@ If the dataset is ordered, you can also ask for the last record:
189
191
 
190
192
  === Filtering Records
191
193
 
192
- An easy way to filter records is to provide a hash of values to match to +filter+:
194
+ An easy way to filter records is to provide a hash of values to match to +where+:
193
195
 
194
- my_posts = posts.filter(:category => 'ruby', :author => 'david')
196
+ my_posts = posts.where(:category => 'ruby', :author => 'david')
195
197
  # WHERE category = 'ruby' AND author = 'david'
196
198
 
197
199
  You can also specify ranges:
198
200
 
199
- my_posts = posts.filter(:stamp => (Date.today - 14)..(Date.today - 7))
201
+ my_posts = posts.where(:stamp => (Date.today - 14)..(Date.today - 7))
200
202
  # WHERE stamp >= '2010-06-30' AND stamp <= '2010-07-07'
201
203
 
202
204
  Or arrays of values:
203
205
 
204
- my_posts = posts.filter(:category => ['ruby', 'postgres', 'linux'])
206
+ my_posts = posts.where(:category => ['ruby', 'postgres', 'linux'])
205
207
  # WHERE category IN ('ruby', 'postgres', 'linux')
206
208
 
207
209
  Sequel also accepts expressions:
208
210
 
209
- my_posts = posts.filter{stamp > Date.today << 1}
211
+ my_posts = posts.where{stamp > Date.today << 1}
210
212
  # WHERE stamp > '2010-06-14'
211
213
 
212
214
  Some adapters will also let you specify Regexps:
213
215
 
214
- my_posts = posts.filter(:category => /ruby/i)
216
+ my_posts = posts.where(:category => /ruby/i)
215
217
  # WHERE category ~* 'ruby'
216
218
 
217
219
  You can also use an inverse filter via +exclude+:
@@ -221,22 +223,21 @@ You can also use an inverse filter via +exclude+:
221
223
 
222
224
  You can also specify a custom WHERE clause using a string:
223
225
 
224
- posts.filter('stamp IS NOT NULL')
226
+ posts.where('stamp IS NOT NULL')
225
227
  # WHERE stamp IS NOT NULL
226
228
 
227
229
  You can use parameters in your string, as well:
228
230
 
229
231
  author_name = 'JKR'
230
- posts.filter('(stamp < ?) AND (author != ?)', Date.today - 3, author_name)
232
+ posts.where('(stamp < ?) AND (author != ?)', Date.today - 3, author_name)
231
233
  # WHERE (stamp < '2010-07-11') AND (author != 'JKR')
232
- posts.filter{(stamp < Date.today - 3) & ~{:author => author_name}} # same as above
233
234
 
234
235
  Datasets can also be used as subqueries:
235
236
 
236
- DB[:items].filter('price > ?', DB[:items].select{avg(price) + 100})
237
+ DB[:items].where('price > ?', DB[:items].select{avg(price) + 100})
237
238
  # WHERE price > (SELECT avg(price) + 100 FROM items)
238
239
 
239
- After filtering you can retrieve the matching records by using any of the retrieval methods:
240
+ After filtering, you can retrieve the matching records by using any of the retrieval methods:
240
241
 
241
242
  my_posts.each{|row| p row}
242
243
 
@@ -246,7 +247,7 @@ See the doc/dataset_filtering.rdoc file for more details.
246
247
 
247
248
  Counting records is easy using +count+:
248
249
 
249
- posts.filter(:category.like('%ruby%')).count
250
+ posts.where(:category.like('%ruby%')).count
250
251
  # SELECT COUNT(*) FROM posts WHERE category LIKE '%ruby%'
251
252
 
252
253
  And you can also query maximum/minimum values via +max+ and +min+:
@@ -273,7 +274,7 @@ Ordering datasets is simple using +order+:
273
274
  posts.order(:stamp, :name)
274
275
  # ORDER BY stamp, name
275
276
 
276
- Chaining +order+ doesn't work the same as +filter+:
277
+ Chaining +order+ doesn't work the same as +where+:
277
278
 
278
279
  posts.order(:stamp).order(:name)
279
280
  # ORDER BY name
@@ -283,10 +284,27 @@ The +order_append+ method chains this way, though:
283
284
  posts.order(:stamp).order_append(:name)
284
285
  # ORDER BY stamp, name
285
286
 
287
+ The +order_prepend+ method can be used as well:
288
+
289
+ posts.order(:stamp).order_prepend(:name)
290
+ # ORDER BY name, stamp
291
+
286
292
  You can also specify descending order:
287
293
 
288
- posts.order(:stamp.desc)
294
+ posts.reverse_order(:stamp)
289
295
  # ORDER BY stamp DESC
296
+ posts.order(Sequel.desc(:stamp))
297
+ # ORDER BY stamp DESC
298
+
299
+ === Core Extensions
300
+
301
+ Note the use of <tt>Sequel.desc(:stamp)</tt> in the above example. Much of Sequel's DSL uses this style, calling methods on the Sequel module that return SQL expression objects. Sequel also ships with a {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]) that integrates Sequel's DSL better into the ruby language, allowing you to write:
302
+
303
+ :stamp.desc
304
+
305
+ instead of:
306
+
307
+ Sequel.desc(:stamp)
290
308
 
291
309
  === Selecting Columns
292
310
 
@@ -297,7 +315,7 @@ Selecting specific columns to be returned is also simple using +select+:
297
315
  posts.select(:stamp, :name)
298
316
  # SELECT stamp, name FROM posts
299
317
 
300
- Chaining +select+ works like +order+, not +filter+:
318
+ Chaining +select+ works like +order+, not +where+:
301
319
 
302
320
  posts.select(:stamp).select(:name)
303
321
  # SELECT name FROM posts
@@ -311,16 +329,16 @@ As you might expect, there is an +order_append+ equivalent for +select+ called +
311
329
 
312
330
  Deleting records from the table is done with +delete+:
313
331
 
314
- posts.filter('stamp < ?', Date.today - 3).delete
332
+ posts.where('stamp < ?', Date.today - 3).delete
315
333
  # DELETE FROM posts WHERE stamp < '2010-07-11'
316
334
 
317
335
  Be very careful when deleting, as +delete+ affects all rows in the dataset.
318
- +filter+ first, +delete+ second, unless you want to empty the table:
336
+ Call +where+ first and +delete+ second:
319
337
 
320
338
  # DO THIS:
321
- posts.filter('stamp < ?', Date.today - 7).delete
339
+ posts.where('stamp < ?', Date.today - 7).delete
322
340
  # NOT THIS:
323
- posts.delete.filter('stamp < ?', Date.today - 7)
341
+ posts.delete.where('stamp < ?', Date.today - 7)
324
342
 
325
343
  === Inserting Records
326
344
 
@@ -333,21 +351,21 @@ Inserting records into the table is done with +insert+:
333
351
 
334
352
  Updating records in the table is done with +update+:
335
353
 
336
- posts.filter('stamp < ?', Date.today - 7).update(:state => 'archived')
354
+ posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
337
355
  # UPDATE posts SET state = 'archived' WHERE stamp < '2010-07-07'
338
356
 
339
357
  You can reference table columns when choosing what values to set:
340
358
 
341
- posts.filter{|o| o.stamp < Date.today - 7}.update(:backup_number => :backup_number + 1)
359
+ posts.where{|o| o.stamp < Date.today - 7}.update(:backup_number => :backup_number + 1)
342
360
  # UPDATE posts SET backup_number = backup_number + 1 WHERE stamp < '2010-07-07'
343
361
 
344
- As with +delete+, +update+ affects all rows in the dataset, so +filter+ first,
345
- +update+ second, unless you want to update all rows:
362
+ As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
363
+ +update+ second:
346
364
 
347
365
  # DO THIS:
348
- posts.filter('stamp < ?', Date.today - 7).update(:state => 'archived')
366
+ posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
349
367
  # NOT THIS:
350
- posts.update(:state => 'archived').filter('stamp < ?', Date.today - 7)
368
+ posts.update(:state => 'archived').where('stamp < ?', Date.today - 7)
351
369
 
352
370
  === Transactions
353
371
 
@@ -355,7 +373,7 @@ You can wrap some code in a database transaction using the <tt>Database#transact
355
373
 
356
374
  DB.transaction do
357
375
  posts.insert(:category => 'ruby', :author => 'david')
358
- posts.filter('stamp < ?', Date.today - 7).update(:state => 'archived')
376
+ posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
359
377
  end
360
378
 
361
379
  If the block does not raise an exception, the transaction will be committed.
@@ -376,11 +394,15 @@ and not raise an exception outside the block, you can raise the
376
394
  Sequel makes it easy to join tables:
377
395
 
378
396
  order_items = DB[:items].join(:order_items, :item_id => :id).
379
- filter(:order_items__order_id => 1234)
397
+ where(:order_items__order_id => 1234)
380
398
  # SELECT * FROM items INNER JOIN order_items
381
399
  # ON order_items.item_id = items.id
382
400
  # WHERE order_items.order_id = 1234
383
401
 
402
+ The important thing to note here is that item_id is automatically qualified with
403
+ the table being joined, and id is automatically qualified with the last table
404
+ joined.
405
+
384
406
  You can then do anything you like with the dataset:
385
407
 
386
408
  order_total = order_items.sum(:price)
@@ -404,14 +426,14 @@ Using +graph+, you can split the result hashes into subhashes, one per join:
404
426
 
405
427
  Sequel expects column names to be specified using symbols. In addition, returned hashes always use symbols as their keys. This allows you to freely mix literal values and column references in many cases. For example, the two following lines produce equivalent SQL:
406
428
 
407
- items.filter(:x => 1)
429
+ items.where(:x => 1)
408
430
  # SELECT * FROM items WHERE (x = 1)
409
- items.filter(1 => :x)
431
+ items.where(1 => :x)
410
432
  # SELECT * FROM items WHERE (1 = x)"
411
433
 
412
434
  Ruby strings are generally treated as SQL strings:
413
435
 
414
- items.filter(:x => 'x')
436
+ items.where(:x => 'x')
415
437
  # SELECT * FROM items WHERE (x = 'x')
416
438
 
417
439
  === Qualifying column names
@@ -421,9 +443,9 @@ Column references can be qualified by using the double underscore special notati
421
443
  items.literal(:items__price)
422
444
  # items.price
423
445
 
424
- Another way to qualify columns is to use the +qualify+ method:
446
+ Another way to qualify columns is to use the <tt>Sequel.qualify</tt> method:
425
447
 
426
- items.literal(:price.qualify(:items))
448
+ items.literal(Sequel.qualify(:items, :price))
427
449
  # items.price
428
450
 
429
451
  === Column aliases
@@ -435,9 +457,9 @@ You can also alias columns by using the triple undersecore special notation <tt>
435
457
  items.literal(:items__price___p)
436
458
  # items.price AS p
437
459
 
438
- Another way to alias columns is to use the +as+ method:
460
+ Another way to alias columns is to use the <tt>Sequel.as</tt> method:
439
461
 
440
- items.literal(:price.as(:p))
462
+ items.literal(Sequel.as(:price, :p))
441
463
  # price AS p
442
464
 
443
465
  == Sequel Models
@@ -463,7 +485,7 @@ You can explicitly set the table name or even the dataset used:
463
485
 
464
486
  If you call +set_dataset+ with a symbol, it assumes you are referring to the table with the same name. You can also call it with a dataset, which will set the defaults for all retrievals for that model:
465
487
 
466
- Post.set_dataset DB[:my_posts].filter(:category => 'ruby')
488
+ Post.set_dataset DB[:my_posts].where(:category => 'ruby')
467
489
  Post.set_dataset DB[:my_posts].select(:id, :name).order(:date)
468
490
 
469
491
  === Model instances
@@ -498,12 +520,12 @@ A single model instance can also be fetched by specifying a condition:
498
520
 
499
521
  A model class lets you iterate over subsets of records by proxying many methods to the underlying dataset. This means that you can use most of the +Dataset+ API to create customized queries that return model instances, e.g.:
500
522
 
501
- Post.filter(:category => 'ruby').each{|post| p post}
523
+ Post.where(:category => 'ruby').each{|post| p post}
502
524
 
503
525
  You can also manipulate the records in the dataset:
504
526
 
505
- Post.filter{num_comments < 7}.delete
506
- Post.filter(:title.like(/ruby/)).update(:category => 'ruby')
527
+ Post.where{num_comments < 7}.delete
528
+ Post.where(Sequel.like(:title, /ruby/)).update(:category => 'ruby')
507
529
 
508
530
  === Accessing record values
509
531
 
@@ -521,10 +543,12 @@ If the record's attributes names are not valid columns in the model's dataset (m
521
543
  post[:id] #=> 123
522
544
  post[:title] #=> 'hello world'
523
545
 
524
- You can also modify record values using attribute setters or the +set+ method:
546
+ You can also modify record values using attribute setters, the <tt>[]=</tt> method, or the +set+ method:
525
547
 
526
548
  post.title = 'hey there'
527
549
  # or
550
+ post[:title] = 'hey there'
551
+ # or
528
552
  post.set(:title=>'hey there')
529
553
 
530
554
  That will just change the value for the object, it will not update the row in the database. To update the database row, call the +save+ method:
@@ -573,7 +597,7 @@ You can execute custom code when creating, updating, or deleting records by defi
573
597
 
574
598
  Note the use of +super+ if you define your own hook methods. Almost all <tt>Sequel::Model</tt> class and instance methods (not just hook methods) can be overridden safely, but you have to make sure to call +super+ when doing so, otherwise you risk breaking things.
575
599
 
576
- For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances. If you plan on allowing any other access to the database, it's best to use database triggers for data integrity.
600
+ For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances, and even then they are often subject to race conditions. It's best to use database triggers and constraints to enforce data integrity.
577
601
 
578
602
  === Deleting records
579
603
 
@@ -584,8 +608,8 @@ You can delete individual records by calling +delete+ or +destroy+. The only dif
584
608
 
585
609
  Records can also be deleted en-masse by calling <tt>Model.delete</tt> and <tt>Model.destroy</tt>. As stated above, you can specify filters for the deleted records:
586
610
 
587
- Post.filter(:category => 32).delete # => bypasses hooks
588
- Post.filter(:category => 32).destroy # => runs hooks
611
+ Post.where(:category => 32).delete # => bypasses hooks
612
+ Post.where(:category => 32).destroy # => runs hooks
589
613
 
590
614
  Please note that if <tt>Model.destroy</tt> is called, each record is deleted
591
615
  separately, but <tt>Model.delete</tt> deletes all matching records with a single
@@ -630,7 +654,7 @@ All associations add a dataset method that can be used to further filter or reor
630
654
  post.comments_dataset.destroy
631
655
 
632
656
  # Return all tags related to this post with no subscribers, ordered by the tag's name
633
- post.tags_dataset.filter(:subscribers=>0).order(:name).all
657
+ post.tags_dataset.where(:subscribers=>0).order(:name).all
634
658
 
635
659
  === Eager Loading
636
660
 
@@ -661,7 +685,7 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
661
685
  Post.eager(:person).all
662
686
 
663
687
  # eager is a dataset method, so it works with filters/orders/limits/etc.
664
- Post.filter{topic > 'M'}.order(:date).limit(5).eager(:person).all
688
+ Post.where{topic > 'M'}.order(:date).limit(5).eager(:person).all
665
689
 
666
690
  person = Person.first
667
691
  # Eager loading via :eager (will eagerly load the tags for this person's posts)
@@ -681,9 +705,23 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
681
705
  # Loads all people, their posts, their posts' tags, replies to those posts,
682
706
  # the person for each reply, the tag for each reply, and all posts and
683
707
  # replies that have that tag. Uses a total of 8 queries.
684
- Person.eager(:posts=>{:replies=>[:person, {:tags=>{:posts, :replies}}]}).all
708
+ Person.eager(:posts=>{:replies=>[:person, {:tags=>[:posts, :replies]}]}).all
709
+
710
+ In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the API is very similar. Note that using +eager_graph+ to eagerly load multiple <tt>*_to_many</tt> associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
711
+
712
+ You can dynamically customize the eagerly loaded dataset by using using a proc. This proc is passed the dataset used for eager loading, and should return a modified copy of that dataset:
713
+
714
+ # Eagerly load only replies containing 'foo'
715
+ Post.eager(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
716
+
717
+ This also works when using +eager_graph+, in which case the proc is called with dataset to graph into the current dataset:
685
718
 
686
- In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the syntax is exactly the same. Note that using eager_graph to eagerly load multiple *_to_many associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
719
+ Post.eager_graph(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
720
+
721
+ You can dynamically customize eager loads for both +eager+ and +eager_graph+ while also cascading, by making the value a single entry hash with the proc as a key, and the cascaded associations as the value:
722
+
723
+ # Eagerly load only replies containing 'foo', and the person and tags for those replies
724
+ Post.eager(:replies=>{proc{|ds| ds.where(Sequel.like(text, '%foo%'))}=>[:person, :tags]}).all
687
725
 
688
726
  === Extending the underlying dataset
689
727
 
@@ -691,7 +729,7 @@ The obvious way to add table-wide logic is to define class methods to the model
691
729
 
692
730
  class Post < Sequel::Model
693
731
  def self.posts_with_few_comments
694
- filter{num_comments < 30}
732
+ where{num_comments < 30}
695
733
  end
696
734
 
697
735
  def self.clean_posts_with_few_comments
@@ -699,27 +737,29 @@ The obvious way to add table-wide logic is to define class methods to the model
699
737
  end
700
738
  end
701
739
 
702
- You can also implement table-wide logic by defining methods on the dataset using +def_dataset_method+:
740
+ You can also implement table-wide logic by defining methods on the dataset using +dataset_module+:
703
741
 
704
742
  class Post < Sequel::Model
705
- def_dataset_method(:posts_with_few_comments) do
706
- filter{num_comments < 30}
707
- end
708
-
709
- def_dataset_method(:clean_posts_with_few_comments) do
710
- posts_with_few_comments.delete
743
+ dataset_module do
744
+ def posts_with_few_comments
745
+ where{num_comments < 30}
746
+ end
747
+
748
+ def clean_posts_with_few_comments
749
+ posts_with_few_comments.delete
750
+ end
711
751
  end
712
752
  end
713
753
 
714
754
  This is the recommended way of implementing table-wide operations, and allows you to have access to your model API from filtered datasets as well:
715
755
 
716
- Post.filter(:category => 'ruby').clean_posts_with_few_comments
756
+ Post.where(:category => 'ruby').clean_posts_with_few_comments
717
757
 
718
758
  Sequel models also provide a +subset+ class method that creates a dataset method with a simple filter:
719
759
 
720
760
  class Post < Sequel::Model
721
761
  subset(:posts_with_few_comments){num_comments < 30}
722
- subset :invisible, ~:visible
762
+ subset :invisible, Sequel.~(:visible)
723
763
  end
724
764
 
725
765
  === Model Validations
data/Rakefile CHANGED
@@ -1,11 +1,5 @@
1
1
  require "rake"
2
2
  require "rake/clean"
3
- require "rake/gempackagetask"
4
- begin
5
- require "hanna/rdoctask"
6
- rescue LoadError
7
- require "rake/rdoctask"
8
- end
9
3
 
10
4
  NAME = 'sequel'
11
5
  VERS = lambda do
@@ -13,34 +7,47 @@ VERS = lambda do
13
7
  Sequel.version
14
8
  end
15
9
  CLEAN.include ["**/.*.sw?", "sequel-*.gem", ".config", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*", '**/*.rbc']
16
- RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Sequel: The Database Toolkit for Ruby']
17
- RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
10
+ SUDO = ENV['SUDO'] || 'sudo'
18
11
 
19
12
  # Gem Packaging and Release
20
13
 
21
14
  desc "Packages sequel"
22
15
  task :package=>[:clean] do |p|
23
- sh %{gem build sequel.gemspec}
16
+ load './sequel.gemspec'
17
+ Gem::Builder.new(SEQUEL_GEMSPEC).build
24
18
  end
25
19
 
26
20
  desc "Install sequel gem"
27
21
  task :install=>[:package] do
28
- sh %{sudo gem install ./#{NAME}-#{VERS.call} --local}
22
+ sh %{#{SUDO} gem install ./#{NAME}-#{VERS.call} --local}
29
23
  end
30
24
 
31
25
  desc "Uninstall sequel gem"
32
26
  task :uninstall=>[:clean] do
33
- sh %{sudo gem uninstall #{NAME}}
27
+ sh %{#{SUDO} gem uninstall #{NAME}}
34
28
  end
35
29
 
36
30
  desc "Upload sequel gem to gemcutter"
37
31
  task :release=>[:package] do
38
- sh %{gem push ./#{NAME}-#{VERS.call}.gem}
32
+ sh %{gem push ./#{NAME}-#{VERS.call}.gem}
39
33
  end
40
34
 
41
35
  ### RDoc
42
36
 
43
- Rake::RDocTask.new do |rdoc|
37
+ RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Sequel: The Database Toolkit for Ruby']
38
+
39
+ rdoc_task_class = begin
40
+ require "rdoc/task"
41
+ RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
42
+ RDoc::Task
43
+ rescue LoadError
44
+ require "rake/rdoctask"
45
+ Rake::RDocTask
46
+ end
47
+
48
+ RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
49
+
50
+ rdoc_task_class.new do |rdoc|
44
51
  rdoc.rdoc_dir = "rdoc"
45
52
  rdoc.options += RDOC_OPTS
46
53
  rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb doc/*.rdoc doc/release_notes/*.txt"
@@ -50,25 +57,25 @@ end
50
57
 
51
58
  desc "Make local version of website"
52
59
  task :website do
53
- sh %{www/make_www.rb}
60
+ sh %{#{FileUtils::RUBY} www/make_www.rb}
54
61
  end
55
62
 
56
63
  desc "Make rdoc for website"
57
64
  task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_plugins]
58
65
 
59
- Rake::RDocTask.new(:website_rdoc_main) do |rdoc|
66
+ rdoc_task_class.new(:website_rdoc_main) do |rdoc|
60
67
  rdoc.rdoc_dir = "www/public/rdoc"
61
68
  rdoc.options += RDOC_OPTS
62
69
  rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
63
70
  end
64
71
 
65
- Rake::RDocTask.new(:website_rdoc_adapters) do |rdoc|
72
+ rdoc_task_class.new(:website_rdoc_adapters) do |rdoc|
66
73
  rdoc.rdoc_dir = "www/public/rdoc-adapters"
67
74
  rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
68
75
  rdoc.rdoc_files.add %w"lib/sequel/adapters/**/*.rb"
69
76
  end
70
77
 
71
- Rake::RDocTask.new(:website_rdoc_plugins) do |rdoc|
78
+ rdoc_task_class.new(:website_rdoc_plugins) do |rdoc|
72
79
  rdoc.rdoc_dir = "www/public/rdoc-plugins"
73
80
  rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
74
81
  rdoc.rdoc_files.add %w"lib/sequel/{extensions,plugins}/**/*.rb"
@@ -92,11 +99,13 @@ begin
92
99
  require "spec/rake/spectask"
93
100
  spec_class = Spec::Rake::SpecTask
94
101
  spec_files_meth = :spec_files=
102
+ spec_opts_meth = :spec_opts=
95
103
  rescue LoadError
96
104
  # RSpec 2
97
105
  require "rspec/core/rake_task"
98
106
  spec_class = RSpec::Core::RakeTask
99
107
  spec_files_meth = :pattern=
108
+ spec_opts_meth = :rspec_opts=
100
109
  end
101
110
 
102
111
  spec = lambda do |name, files, d|
@@ -105,26 +114,49 @@ begin
105
114
  desc d
106
115
  spec_class.new(name) do |t|
107
116
  t.send spec_files_meth, files
108
- t.spec_opts = ENV['SEQUEL_SPEC_OPTS'].split if ENV['SEQUEL_SPEC_OPTS']
117
+ t.send spec_opts_meth, ENV['SEQUEL_SPEC_OPTS'].split if ENV['SEQUEL_SPEC_OPTS']
109
118
  end
110
119
  end
111
120
 
112
- spec_with_cov = lambda do |name, files, d|
121
+ spec_with_cov = lambda do |name, files, d, &b|
113
122
  spec.call(name, files, d)
114
123
  t = spec.call("#{name}_cov", files, "#{d} with coverage")
115
124
  t.rcov = true
116
125
  t.rcov_opts = File.read("spec/rcov.opts").split("\n")
126
+ b.call(t) if b
127
+ t
117
128
  end
118
-
129
+
119
130
  task :default => [:spec]
120
- spec_with_cov.call("spec", Dir["spec/{core,model}/*_spec.rb"], "Run core and model specs")
131
+ spec_with_cov.call("spec", Dir["spec/{core,model}/*_spec.rb"], "Run core and model specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/(adapters/([a-ln-z]|m[a-np-z])|extensions/core_extensions)"')}
121
132
  spec.call("spec_core", Dir["spec/core/*_spec.rb"], "Run core specs")
122
133
  spec.call("spec_model", Dir["spec/model/*_spec.rb"], "Run model specs")
123
- spec_with_cov.call("spec_plugin", Dir["spec/extensions/*_spec.rb"], "Run extension/plugin specs")
134
+ spec.call("_spec_model_no_assoc", Dir["spec/model/*_spec.rb"].delete_if{|f| f =~ /association|eager_loading/}, '')
135
+ spec_with_cov.call("spec_core_ext", ["spec/core_extensions_spec.rb"], "Run core extensions specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|adapters|connection_pool|database|dataset|model)"')}
136
+ spec_with_cov.call("spec_plugin", Dir["spec/extensions/*_spec.rb"], "Run extension/plugin specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|adapters|connection_pool|database|dataset|model)"')}
124
137
  spec_with_cov.call("spec_integration", Dir["spec/integration/*_test.rb"], "Run integration tests")
125
-
126
- %w'postgres sqlite mysql informix oracle firebird mssql'.each do |adapter|
127
- spec_with_cov.call("spec_#{adapter}", ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"], "Run #{adapter} specs")
138
+
139
+ %w'postgres sqlite mysql informix oracle firebird mssql db2'.each do |adapter|
140
+ spec_with_cov.call("spec_#{adapter}", ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"], "Run #{adapter} specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|connection_pool|database|dataset|model|extensions|plugins)"')}
141
+ end
142
+
143
+ task :spec_travis=>[:spec, :spec_plugin, :spec_core_ext, :spec_sqlite] do
144
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
145
+ ENV['SEQUEL_PG_SPEC_DB'] = "jdbc:postgresql://localhost/sequel_test?user=postgres"
146
+ ENV['SEQUEL_MY_SPEC_DB'] = "jdbc:mysql://localhost/sequel_test?user=root"
147
+ else
148
+ ENV['SEQUEL_PG_SPEC_DB'] = "postgres://localhost/sequel_test?user=postgres"
149
+ ENV['SEQUEL_MY_SPEC_DB'] = "mysql2://localhost/sequel_test?user=root"
150
+ end
151
+
152
+ Rake::Task['spec_postgres'].invoke
153
+ Rake::Task['spec_mysql'].invoke
154
+ end
155
+
156
+ desc "Run model specs without the associations code"
157
+ task :spec_model_no_assoc do
158
+ ENV['SEQUEL_NO_ASSOCIATIONS'] = '1'
159
+ Rake::Task['_spec_model_no_assoc'].invoke
128
160
  end
129
161
  rescue LoadError
130
162
  task :default do
@@ -142,7 +174,7 @@ end
142
174
  desc "Report code statistics (KLOCs, etc) from the application"
143
175
  task :stats do
144
176
  STATS_DIRECTORIES = [%w(Code lib/), %w(Spec spec)].map{|name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir)}
145
- require "extra/stats"
177
+ require "./extra/stats"
146
178
  verbose = true
147
179
  CodeStatistics.new(*STATS_DIRECTORIES).to_s
148
180
  end
@@ -154,5 +186,5 @@ end
154
186
 
155
187
  desc "Check syntax of all .rb files"
156
188
  task :check_syntax do
157
- Dir['**/*.rb'].each{|file| print `#{ENV['RUBY'] || :ruby} -c #{file} | fgrep -v "Syntax OK"`}
189
+ Dir['**/*.rb'].each{|file| print `#{FileUtils::RUBY} -c #{file} | fgrep -v "Syntax OK"`}
158
190
  end