dbagile 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (305) hide show
  1. data/LICENCE.textile +12 -0
  2. data/README.textile +89 -0
  3. data/bin/dba +22 -0
  4. data/lib/dbagile/adapter/sequel/class_methods.rb +18 -0
  5. data/lib/dbagile/adapter/sequel/connection.rb +38 -0
  6. data/lib/dbagile/adapter/sequel/data/table_driven.rb +30 -0
  7. data/lib/dbagile/adapter/sequel/data/transaction_driven.rb +43 -0
  8. data/lib/dbagile/adapter/sequel/schema/concrete_script.rb +135 -0
  9. data/lib/dbagile/adapter/sequel/schema/physical_dump.rb +106 -0
  10. data/lib/dbagile/adapter/sequel/schema/schema2sequel_args.rb +71 -0
  11. data/lib/dbagile/adapter/sequel/schema/table_driven.rb +52 -0
  12. data/lib/dbagile/adapter/sequel/schema/transaction_driven.rb +46 -0
  13. data/lib/dbagile/adapter/sequel/sequel_tracer.rb +144 -0
  14. data/lib/dbagile/adapter/sequel.rb +46 -0
  15. data/lib/dbagile/adapter.rb +15 -0
  16. data/lib/dbagile/command/api.rb +49 -0
  17. data/lib/dbagile/command/bulk/commons.rb +130 -0
  18. data/lib/dbagile/command/bulk/export.rb +99 -0
  19. data/lib/dbagile/command/bulk/import.rb +147 -0
  20. data/lib/dbagile/command/bulk.rb +3 -0
  21. data/lib/dbagile/command/class_methods.rb +103 -0
  22. data/lib/dbagile/command/db/add.rb +94 -0
  23. data/lib/dbagile/command/db/list.rb +40 -0
  24. data/lib/dbagile/command/db/ping.rb +49 -0
  25. data/lib/dbagile/command/db/rm.rb +52 -0
  26. data/lib/dbagile/command/db/stage.rb +81 -0
  27. data/lib/dbagile/command/db/use.rb +48 -0
  28. data/lib/dbagile/command/db.rb +6 -0
  29. data/lib/dbagile/command/dba.rb +121 -0
  30. data/lib/dbagile/command/help.rb +50 -0
  31. data/lib/dbagile/command/repo/create.rb +54 -0
  32. data/lib/dbagile/command/repo.rb +1 -0
  33. data/lib/dbagile/command/robust.rb +86 -0
  34. data/lib/dbagile/command/schema/check.rb +59 -0
  35. data/lib/dbagile/command/schema/commons.rb +118 -0
  36. data/lib/dbagile/command/schema/diff.rb +101 -0
  37. data/lib/dbagile/command/schema/dump.rb +48 -0
  38. data/lib/dbagile/command/schema/merge.rb +55 -0
  39. data/lib/dbagile/command/schema/sql_script.rb +124 -0
  40. data/lib/dbagile/command/schema.rb +6 -0
  41. data/lib/dbagile/command/sql/drop.rb +40 -0
  42. data/lib/dbagile/command/sql/heading.rb +34 -0
  43. data/lib/dbagile/command/sql/send.rb +67 -0
  44. data/lib/dbagile/command/sql/show.rb +42 -0
  45. data/lib/dbagile/command/sql.rb +4 -0
  46. data/lib/dbagile/command/web/tools.rb +23 -0
  47. data/lib/dbagile/command/web.rb +1 -0
  48. data/lib/dbagile/command.rb +158 -0
  49. data/lib/dbagile/contract/connection.rb +66 -0
  50. data/lib/dbagile/contract/data/dataset.rb +69 -0
  51. data/lib/dbagile/contract/data/table_driven.rb +49 -0
  52. data/lib/dbagile/contract/data/transaction_driven.rb +74 -0
  53. data/lib/dbagile/contract/data.rb +3 -0
  54. data/lib/dbagile/contract/robust/helpers.rb +19 -0
  55. data/lib/dbagile/contract/robust/optimistic/data/table_driven.rb +31 -0
  56. data/lib/dbagile/contract/robust/optimistic/data/transaction_driven.rb +45 -0
  57. data/lib/dbagile/contract/robust/optimistic/schema/table_driven.rb +53 -0
  58. data/lib/dbagile/contract/robust/optimistic/schema/transaction_driven.rb +45 -0
  59. data/lib/dbagile/contract/robust/optimistic.rb +18 -0
  60. data/lib/dbagile/contract/robust.rb +20 -0
  61. data/lib/dbagile/contract/schema/table_driven.rb +89 -0
  62. data/lib/dbagile/contract/schema/transaction_driven.rb +68 -0
  63. data/lib/dbagile/contract/schema.rb +2 -0
  64. data/lib/dbagile/contract/utils/delegate.rb +17 -0
  65. data/lib/dbagile/contract/utils/full.rb +13 -0
  66. data/lib/dbagile/contract/utils.rb +2 -0
  67. data/lib/dbagile/contract.rb +5 -0
  68. data/lib/dbagile/core/chain.rb +92 -0
  69. data/lib/dbagile/core/connection.rb +51 -0
  70. data/lib/dbagile/core/database.rb +221 -0
  71. data/lib/dbagile/core/io/dsl.rb +95 -0
  72. data/lib/dbagile/core/io/robustness.rb +82 -0
  73. data/lib/dbagile/core/io.rb +2 -0
  74. data/lib/dbagile/core/repository/builder.rb +67 -0
  75. data/lib/dbagile/core/repository/yaml_methods.rb +82 -0
  76. data/lib/dbagile/core/repository.rb +211 -0
  77. data/lib/dbagile/core/schema/builder/coercion.rb +210 -0
  78. data/lib/dbagile/core/schema/builder/concept_factory.rb +61 -0
  79. data/lib/dbagile/core/schema/builder.rb +187 -0
  80. data/lib/dbagile/core/schema/composite.rb +239 -0
  81. data/lib/dbagile/core/schema/computations/filter.rb +40 -0
  82. data/lib/dbagile/core/schema/computations/merge.rb +55 -0
  83. data/lib/dbagile/core/schema/computations/minus.rb +44 -0
  84. data/lib/dbagile/core/schema/computations/split.rb +37 -0
  85. data/lib/dbagile/core/schema/computations.rb +4 -0
  86. data/lib/dbagile/core/schema/database_schema.rb +129 -0
  87. data/lib/dbagile/core/schema/errors.rb +173 -0
  88. data/lib/dbagile/core/schema/logical/attribute.rb +68 -0
  89. data/lib/dbagile/core/schema/logical/constraint/candidate_key.rb +70 -0
  90. data/lib/dbagile/core/schema/logical/constraint/foreign_key.rb +121 -0
  91. data/lib/dbagile/core/schema/logical/constraint.rb +58 -0
  92. data/lib/dbagile/core/schema/logical/constraints.rb +28 -0
  93. data/lib/dbagile/core/schema/logical/heading.rb +47 -0
  94. data/lib/dbagile/core/schema/logical/relvar.rb +81 -0
  95. data/lib/dbagile/core/schema/logical.rb +24 -0
  96. data/lib/dbagile/core/schema/migrate/abstract_script.rb +35 -0
  97. data/lib/dbagile/core/schema/migrate/collapse_table.rb +15 -0
  98. data/lib/dbagile/core/schema/migrate/create_table.rb +15 -0
  99. data/lib/dbagile/core/schema/migrate/drop_table.rb +15 -0
  100. data/lib/dbagile/core/schema/migrate/expand_table.rb +15 -0
  101. data/lib/dbagile/core/schema/migrate/operation.rb +141 -0
  102. data/lib/dbagile/core/schema/migrate/stager.rb +282 -0
  103. data/lib/dbagile/core/schema/migrate.rb +2 -0
  104. data/lib/dbagile/core/schema/part.rb +114 -0
  105. data/lib/dbagile/core/schema/physical/index.rb +64 -0
  106. data/lib/dbagile/core/schema/physical/indexes.rb +12 -0
  107. data/lib/dbagile/core/schema/physical.rb +26 -0
  108. data/lib/dbagile/core/schema/robustness.rb +39 -0
  109. data/lib/dbagile/core/schema/schema_object.rb +94 -0
  110. data/lib/dbagile/core/schema.rb +254 -0
  111. data/lib/dbagile/core/transaction.rb +74 -0
  112. data/lib/dbagile/core.rb +7 -0
  113. data/lib/dbagile/environment/buffering.rb +45 -0
  114. data/lib/dbagile/environment/delegator.rb +59 -0
  115. data/lib/dbagile/environment/interactions.rb +208 -0
  116. data/lib/dbagile/environment/on_error.rb +47 -0
  117. data/lib/dbagile/environment/repository.rb +161 -0
  118. data/lib/dbagile/environment/robustness.rb +7 -0
  119. data/lib/dbagile/environment/testing.rb +23 -0
  120. data/lib/dbagile/environment.rb +122 -0
  121. data/lib/dbagile/errors.rb +30 -0
  122. data/lib/dbagile/io/csv.rb +99 -0
  123. data/lib/dbagile/io/json.rb +41 -0
  124. data/lib/dbagile/io/pretty_table.rb +128 -0
  125. data/lib/dbagile/io/ruby.rb +62 -0
  126. data/lib/dbagile/io/text.rb +18 -0
  127. data/lib/dbagile/io/type_safe.rb +65 -0
  128. data/lib/dbagile/io/xml.rb +35 -0
  129. data/lib/dbagile/io/yaml.rb +30 -0
  130. data/lib/dbagile/io.rb +94 -0
  131. data/lib/dbagile/loader.rb +16 -0
  132. data/lib/dbagile/plugin.rb +29 -0
  133. data/lib/dbagile/restful/client/delete.rb +22 -0
  134. data/lib/dbagile/restful/client/get.rb +24 -0
  135. data/lib/dbagile/restful/client/post.rb +22 -0
  136. data/lib/dbagile/restful/client/utils.rb +16 -0
  137. data/lib/dbagile/restful/client.rb +41 -0
  138. data/lib/dbagile/restful/middleware/delete.rb +22 -0
  139. data/lib/dbagile/restful/middleware/get.rb +27 -0
  140. data/lib/dbagile/restful/middleware/one_database.rb +82 -0
  141. data/lib/dbagile/restful/middleware/post.rb +23 -0
  142. data/lib/dbagile/restful/middleware/utils.rb +65 -0
  143. data/lib/dbagile/restful/middleware.rb +54 -0
  144. data/lib/dbagile/restful/server.rb +65 -0
  145. data/lib/dbagile/restful.rb +9 -0
  146. data/lib/dbagile/robustness/dependencies.rb +36 -0
  147. data/lib/dbagile/robustness/file_system.rb +53 -0
  148. data/lib/dbagile/robustness.rb +14 -0
  149. data/lib/dbagile/tools/file_system.rb +24 -0
  150. data/lib/dbagile/tools/math.rb +11 -0
  151. data/lib/dbagile/tools/ordered_hash.rb +39 -0
  152. data/lib/dbagile/tools/ruby.rb +78 -0
  153. data/lib/dbagile/tools/string.rb +6 -0
  154. data/lib/dbagile/tools/tuple.rb +49 -0
  155. data/lib/dbagile/tools.rb +6 -0
  156. data/lib/dbagile.rb +66 -0
  157. data/test/assumptions/equality.spec +11 -0
  158. data/test/assumptions/fixtures.rb +39 -0
  159. data/test/assumptions/inheritance.spec +17 -0
  160. data/test/assumptions/sequel/autonumber.spec +19 -0
  161. data/test/assumptions/sequel/connect.spec +29 -0
  162. data/test/assumptions/sequel/test.db +0 -0
  163. data/test/assumptions/stdlib/pathname.spec +13 -0
  164. data/test/assumptions/yaml/fixtures.rb +25 -0
  165. data/test/assumptions/yaml/to_yaml.spec +10 -0
  166. data/test/assumptions.spec +2 -0
  167. data/test/commands/bulk/export.spec +100 -0
  168. data/test/commands/bulk/import.spec +49 -0
  169. data/test/commands/db/add.spec +31 -0
  170. data/test/commands/db/list.spec +29 -0
  171. data/test/commands/db/ping.spec +21 -0
  172. data/test/commands/db/rm.spec +18 -0
  173. data/test/commands/db/use.spec +18 -0
  174. data/test/commands/dba.spec +54 -0
  175. data/test/commands/repo/create.spec +30 -0
  176. data/test/commands/schema/check.spec +25 -0
  177. data/test/commands/schema/diff.spec +30 -0
  178. data/test/commands/schema/dump.spec +23 -0
  179. data/test/commands/schema/fixtures/add_constraint.yaml +30 -0
  180. data/test/commands/schema/fixtures/announced.yaml +28 -0
  181. data/test/commands/schema/fixtures/effective.yaml +20 -0
  182. data/test/commands/schema/fixtures/invalid.yaml +6 -0
  183. data/test/commands/schema/sql_script.spec +56 -0
  184. data/test/commands/sql/drop.spec +25 -0
  185. data/test/commands/sql/heading.spec +7 -0
  186. data/test/commands/sql/scripts/delete.sql +1 -0
  187. data/test/commands/sql/scripts/insert.sql +2 -0
  188. data/test/commands/sql/send.spec +29 -0
  189. data/test/commands/sql/show.spec +17 -0
  190. data/test/commands.spec +138 -0
  191. data/test/contract/connection/transaction.ex +11 -0
  192. data/test/contract/connection.spec +9 -0
  193. data/test/contract/data/dataset/columns.ex +5 -0
  194. data/test/contract/data/dataset/count.ex +5 -0
  195. data/test/contract/data/dataset.spec +9 -0
  196. data/test/contract/data/table_driven/dataset.ex +31 -0
  197. data/test/contract/data/table_driven/exists_q.ex +27 -0
  198. data/test/contract/data/table_driven.spec +9 -0
  199. data/test/contract/data/transaction_driven/delete.ex +29 -0
  200. data/test/contract/data/transaction_driven/direct_sql.ex +19 -0
  201. data/test/contract/data/transaction_driven/insert.ex +8 -0
  202. data/test/contract/data/transaction_driven/update.ex +19 -0
  203. data/test/contract/data/transaction_driven.spec +18 -0
  204. data/test/contract/robust/data/table_driven.spec +15 -0
  205. data/test/contract/robust/data/transaction_driven.spec +21 -0
  206. data/test/contract/robust/schema/table_driven.spec +21 -0
  207. data/test/contract/robust/schema/transaction_driven.spec +19 -0
  208. data/test/contract/schema/table_driven/column_names.ex +5 -0
  209. data/test/contract/schema/table_driven/has_column_q.ex +13 -0
  210. data/test/contract/schema/table_driven/has_table_q.ex +11 -0
  211. data/test/contract/schema/table_driven/heading.ex +5 -0
  212. data/test/contract/schema/table_driven.spec +9 -0
  213. data/test/contract/schema/transaction_driven/create_table.ex +10 -0
  214. data/test/contract/schema/transaction_driven/drop_table.ex +10 -0
  215. data/test/contract/schema/transaction_driven.spec +18 -0
  216. data/test/contract.spec +66 -0
  217. data/test/fixtures/basics/data/basic_values.rb +13 -0
  218. data/test/fixtures/basics/data/empty_table.rb +3 -0
  219. data/test/fixtures/basics/data/non_empty_table.rb +4 -0
  220. data/test/fixtures/basics/data/parts.rb +8 -0
  221. data/test/fixtures/basics/data/suppliers.rb +7 -0
  222. data/test/fixtures/basics/data/supplies.rb +14 -0
  223. data/test/fixtures/basics/dbagile.idx +20 -0
  224. data/test/fixtures/basics/fixtures.yaml +28 -0
  225. data/test/fixtures/basics/robust.db +0 -0
  226. data/test/fixtures/basics/suppliers.yaml +30 -0
  227. data/test/fixtures/basics/test.db +0 -0
  228. data/test/fixtures/empty/dbagile.idx +5 -0
  229. data/test/fixtures.rb +152 -0
  230. data/test/restful/delete/no_format.ex +32 -0
  231. data/test/restful/delete.spec +8 -0
  232. data/test/restful/get/csv_format.ex +12 -0
  233. data/test/restful/get/json_format.ex +19 -0
  234. data/test/restful/get/query_string.ex +11 -0
  235. data/test/restful/get/text_format.ex +12 -0
  236. data/test/restful/get/yaml_format.ex +14 -0
  237. data/test/restful/get.spec +5 -0
  238. data/test/restful/post/no_format.ex +22 -0
  239. data/test/restful/post.spec +8 -0
  240. data/test/restful.spec +32 -0
  241. data/test/run_all_suite.rb +51 -0
  242. data/test/spec_helper.rb +26 -0
  243. data/test/support/be_a_valid_json_string.rb +19 -0
  244. data/test/support/be_a_valid_yaml_string.rb +18 -0
  245. data/test/unit/adapter/factor.spec +13 -0
  246. data/test/unit/adapter/sequel/new.spec +19 -0
  247. data/test/unit/command/api.spec +12 -0
  248. data/test/unit/command/command_for.spec +36 -0
  249. data/test/unit/command/command_name_of.spec +21 -0
  250. data/test/unit/command/ruby_method_for.spec +21 -0
  251. data/test/unit/command/sanity.spec +34 -0
  252. data/test/unit/contract/utils/delegate/delegate.spec +23 -0
  253. data/test/unit/core/chain/chain.spec +57 -0
  254. data/test/unit/core/chain/connect.spec +22 -0
  255. data/test/unit/core/chain/delegate_chain.spec +16 -0
  256. data/test/unit/core/chain/initialize.spec +19 -0
  257. data/test/unit/core/chain/plug.spec +31 -0
  258. data/test/unit/core/io/dsl/scope.spec +9 -0
  259. data/test/unit/core/repository/create_bang.spec +31 -0
  260. data/test/unit/core/repository/current.spec +31 -0
  261. data/test/unit/core/repository/database.spec +47 -0
  262. data/test/unit/core/repository/fixtures/corrupted/dbagile.idx +1 -0
  263. data/test/unit/core/repository/fixtures/test_and_prod/dbagile.idx +21 -0
  264. data/test/unit/core/repository/fixtures.rb +25 -0
  265. data/test/unit/core/repository/has_database_q.spec +16 -0
  266. data/test/unit/core/repository/load.spec +51 -0
  267. data/test/unit/core/repository/to_yaml.spec +17 -0
  268. data/test/unit/core/schema/check.spec +32 -0
  269. data/test/unit/core/schema/empty_q.spec +18 -0
  270. data/test/unit/core/schema/filter.spec +42 -0
  271. data/test/unit/core/schema/fixtures/dbagile.yaml +7 -0
  272. data/test/unit/core/schema/fixtures/empty.yaml +11 -0
  273. data/test/unit/core/schema/fixtures/invalid.yaml +54 -0
  274. data/test/unit/core/schema/fixtures/left.yaml +46 -0
  275. data/test/unit/core/schema/fixtures/left_minus_right.yaml +31 -0
  276. data/test/unit/core/schema/fixtures/right.yaml +46 -0
  277. data/test/unit/core/schema/fixtures/right_minus_left.yaml +31 -0
  278. data/test/unit/core/schema/fixtures/suppliers_and_parts.yaml +30 -0
  279. data/test/unit/core/schema/fixtures.rb +32 -0
  280. data/test/unit/core/schema/merge.spec +72 -0
  281. data/test/unit/core/schema/minus.spec +26 -0
  282. data/test/unit/core/schema/sanity.spec +39 -0
  283. data/test/unit/core/schema/split.spec +58 -0
  284. data/test/unit/core/schema/stage_script.spec +26 -0
  285. data/test/unit/core/schema/to_yaml.spec +13 -0
  286. data/test/unit/core/schema/yaml_display.spec +14 -0
  287. data/test/unit/core/schema/yaml_load.spec +20 -0
  288. data/test/unit/core/transaction/transaction.spec +10 -0
  289. data/test/unit/fixtures.rb +67 -0
  290. data/test/unit/io/to_xxx.spec +52 -0
  291. data/test/unit/plugin/options.spec +21 -0
  292. data/test/unit/plugin/tuple_heading.spec +11 -0
  293. data/test/unit/plugin/with_options.spec +12 -0
  294. data/test/unit/tools/ruby/class_unqualified_name.spec +26 -0
  295. data/test/unit/tools/ruby/extract_file_rdoc.spec +10 -0
  296. data/test/unit/tools/ruby/fixtures/rdoc.txt +12 -0
  297. data/test/unit/tools/ruby/fixtures.rb +19 -0
  298. data/test/unit/tools/ruby/optional_args_block_call.spec +35 -0
  299. data/test/unit/tools/ruby/parent_module.spec +21 -0
  300. data/test/unit/tools/ruby/rdoc_file_paragraphs.spec +13 -0
  301. data/test/unit/tools/tuple/tuple_heading.spec +11 -0
  302. data/test/unit/tools/tuple/tuple_key.spec +27 -0
  303. data/test/unit/tools/tuple/tuple_project.spec +23 -0
  304. data/test/unit.spec +3 -0
  305. metadata +422 -0
data/LICENCE.textile ADDED
@@ -0,0 +1,12 @@
1
+ h1. The MIT License
2
+
3
+ Copyright (c) 2009 Bernard Lambeau and the University of Louvain (Universite Catholique de Louvain, Louvain-la-Neuve, Belgium)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+
data/README.textile ADDED
@@ -0,0 +1,89 @@
1
+ h1. DbAgile - SQL Databases with Agility
2
+
3
+ DbAgile aims at providing agile tools around databases, and relational/sql databases in particular.
4
+
5
+ h2. Motivation
6
+
7
+ Have you ever dreamed of having one central point for keeping your database access infos?
8
+
9
+ <pre class="shell">
10
+ sh$ dba db:list
11
+ sh$ dba db:use my_contacts
12
+ </pre>
13
+
14
+ Or displaying a SQL table (say, 'contacts') in one shell command?
15
+
16
+ <pre class="shell">
17
+ sh$ dba sql:show contacts
18
+ </pre>
19
+
20
+ Or to output the result of any SQL query to yaml, json, csv, ruby, ... or even xml?
21
+
22
+ <pre class="shell">
23
+ sh$ dba bulk:export --yaml "SELECT name, mail FROM contacts"
24
+ </pre>
25
+
26
+ Or to have a Restful server on top of SQL databases?
27
+
28
+ <pre class="shell">
29
+ dba web:tools
30
+ </pre>
31
+
32
+ Making similar things, ... in Ruby?
33
+
34
+ <pre>
35
+ DbAgile::dba do |dba|
36
+ # Override environment default values (~/.dbagile, STDOUT)
37
+ dba.repository_path = ... # your application database repository
38
+ dba.output_buffer = ... # keep output in any IO object
39
+
40
+ # Start using dbagile commands
41
+ dba.bulk_export %w{--yaml contacts} # each line pushed in output_buffer
42
+ end
43
+ </pre>
44
+
45
+ The Rack middleware for the restful server (config.ru):
46
+
47
+ <pre>
48
+ #!/usr/bin/env rackup --require dbagile/restful/middleware -p 8711
49
+ app = DbAgile::Restful::Middleware.new{|env|
50
+ #
51
+ # Set the environment!
52
+ #
53
+ # WARNING: Always use ::File instead of File because constants are
54
+ # resolved in Rack scope, which contains a File class. Not
55
+ # doing this may mead to bugs in certain ruby versions.
56
+ #
57
+ env.repository_path = ::File.expand_path('../dbagile', __FILE__)
58
+ }
59
+ </pre>
60
+
61
+ h2. Pointers
62
+
63
+ * DbAgile developper documentation on "rdoc.info":http://rdoc.info/projects/blambeau/dbagile
64
+
65
+ h2. Installation
66
+
67
+ <pre>
68
+ gem install dbagile (required dependencies are automatically installed)
69
+ dba --help
70
+ </pre>
71
+
72
+ Required dependencies:
73
+
74
+ * sbyc >= 0.1.4
75
+ * sequel >= 3.8.0
76
+ * highline >= 1.5.2
77
+
78
+ Optional dependencies (according to your needs):
79
+
80
+ * mysql, pg, sqlite, ... (according to your sql database needs)
81
+ * json (only if you use json import/export)
82
+ * fastercsv (only if you use csv import/export)
83
+ * yaml (only if you use yaml import/export)
84
+ * builder (only if you use xml export)
85
+ * rack >= 1.1.0 (only if you use the restful server)
86
+
87
+ h2. Credits
88
+
89
+ DbAgile (c) 2010 by Bernard Lambeau and the University of Louvain. DbAgile is distributed under the MIT licence. Please see the LICENCE.textile document for details.
data/bin/dba ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # DbAgile - Agile interface on top of SQL databases
4
+ # (see lib/dbagile/dbagile.rb for more information)
5
+ #
6
+ # Copyright (c) 2010 Bernard Lambeau & University of Louvain,
7
+ # Released under a MIT or Ruby licence
8
+ #
9
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
10
+ require 'dbagile'
11
+
12
+ begin
13
+ r = DbAgile::Command::Dba.new(DbAgile::default_environment).run '.', ARGV
14
+ rescue Interrupt => e
15
+ $stderr.puts
16
+ $stderr.puts "Interrupted"
17
+ raise e
18
+ rescue => e
19
+ $stderr.puts "DbAgile encountered a grave error, please report it to the developers"
20
+ $stderr.puts e.message
21
+ $stderr.puts e.backtrace.join("\n")
22
+ end
@@ -0,0 +1,18 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module ClassMethods
4
+
5
+ #
6
+ # Overrided to add a SequelTracer instance if trace is on
7
+ #
8
+ def new(uri, options = {})
9
+ if options[:trace_sql]
10
+ SequelTracer.new(super(uri), options)
11
+ else
12
+ super(uri, options)
13
+ end
14
+ end
15
+
16
+ end # module ClassMethods
17
+ end # class SequelAdapter
18
+ end # module DbAgile
@@ -0,0 +1,38 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Connection
4
+
5
+ # @see DbAgile::Contract::Connection#ping
6
+ def ping
7
+ db.test_connection
8
+ end
9
+
10
+ # @see DbAgile::Contract::Connection#disconnect
11
+ def disconnect
12
+ @db.disconnect if @db
13
+ true
14
+ end
15
+
16
+ # @see DbAgile::Contract::Connection#physical_schema
17
+ def physical_schema
18
+ SequelAdapter::Schema::PhysicalDump.new.run(db, uri)
19
+ end
20
+
21
+ # @see DbAgile::Contract::Connection#script2sql
22
+ def script2sql(script, buffer = "")
23
+ SequelAdapter::Schema::ConcreteScript::script2sql(db, script, buffer)
24
+ end
25
+
26
+ # @see DbAgile::Contract::Connection#transaction
27
+ def transaction(&block)
28
+ raise ArgumentError, "Missing transaction block" unless block
29
+ begin
30
+ db.transaction{ block.call(self) }
31
+ rescue DbAgile::AbordTransactionError
32
+ nil
33
+ end
34
+ end
35
+
36
+ end # module Connection
37
+ end # class SequelAdapter
38
+ end # module DbAgile
@@ -0,0 +1,30 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Data
4
+ module TableDriven
5
+
6
+ # @see DbAgile::Contract::Data::TableDriven#dataset
7
+ def dataset(table, proj = nil)
8
+ result = case table
9
+ when Symbol
10
+ (proj.nil? or proj.empty?) ? db[table] : db[table].where(proj)
11
+ else
12
+ (proj.nil? or proj.empty?) ? db[table] : db[table].where(proj)
13
+ end
14
+ result.extend(::DbAgile::Contract::Data::Dataset)
15
+ result
16
+ end
17
+
18
+ # @see DbAgile::Contract::Data::TableDriven#exists?
19
+ def exists?(table_or_query, subtuple = {})
20
+ if subtuple.nil? or subtuple.empty?
21
+ !dataset(table_or_query).empty?
22
+ else
23
+ !dataset(table_or_query).where(subtuple).empty?
24
+ end
25
+ end
26
+
27
+ end # module TableDriven
28
+ end # module Data
29
+ end # class SequelAdapter
30
+ end # module DbAgile
@@ -0,0 +1,43 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Data
4
+ module TransactionDriven
5
+
6
+ # @see DbAgile::Contract::Data::TransactionDriven#insert
7
+ def insert(transaction, table, tuple)
8
+ db[table].insert(tuple)
9
+ tuple
10
+ end
11
+
12
+ # @see DbAgile::Contract::Data::TransactionDriven#update
13
+ def update(transaction, table_name, update, proj = {})
14
+ if proj.nil? or proj.empty?
15
+ db[table_name].update(update)
16
+ else
17
+ db[table_name].where(proj).update(update)
18
+ end
19
+ end
20
+
21
+ # @see DbAgile::Contract::Data::TransactionDriven#delete
22
+ def delete(transaction, table_name, proj = {})
23
+ if proj.empty?
24
+ db[table_name].delete
25
+ else
26
+ db[table_name].where(proj).delete
27
+ end
28
+ true
29
+ end
30
+
31
+ # @see DbAgile::Contract::Data::TransactionDriven#direct_sql
32
+ def direct_sql(transaction, sql)
33
+ if /^\s*(select|SELECT)/ =~ sql
34
+ dataset(sql)
35
+ else
36
+ db << sql
37
+ end
38
+ end
39
+
40
+ end # module TransactionDriven
41
+ end # module Data
42
+ end # class SequelAdapter
43
+ end # module DbAgile
@@ -0,0 +1,135 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Schema
4
+ module ConcreteScript
5
+ include Schema::Schema2SequelArgs
6
+
7
+ # Converts an abstract script to a concrete one
8
+ def script2sql(conn, script, buffer)
9
+ script.each{|op| self.send(op.kind, conn, op, buffer)}
10
+ buffer
11
+ end
12
+
13
+ def create_table(conn, op, buffer)
14
+ gen = Sequel::Schema::Generator.new(conn)
15
+ build_sequel_expand_generator(conn, op, gen, "")
16
+ buffer << to_sql(conn, op, gen)
17
+ staged!(op)
18
+ rescue Sequel::Error => ex
19
+ buffer << "-- UNSUPPORTED: #{op.to_sql92}" << "\n"
20
+ unsupported!(op)
21
+ end
22
+
23
+ def expand_table(conn, op, buffer)
24
+ gen = Sequel::Schema::AlterTableGenerator.new(conn)
25
+ build_sequel_expand_generator(conn, op, gen, "add_")
26
+ buffer << to_sql(conn, op, gen)
27
+ staged!(op)
28
+ rescue Sequel::Error => ex
29
+ buffer << "-- UNSUPPORTED: #{op.to_sql92}" << "\n"
30
+ unsupported!(op)
31
+ end
32
+
33
+ def collapse_table(conn, op, buffer)
34
+ gen = Sequel::Schema::AlterTableGenerator.new(conn)
35
+ build_sequel_collapse_generator(conn, op, gen, "drop_")
36
+ buffer << to_sql(conn, op, gen)
37
+ staged!(op)
38
+ rescue Sequel::Error => ex
39
+ buffer << "-- UNSUPPORTED: #{op.to_sql92}" << "\n"
40
+ unsupported!(op)
41
+ end
42
+
43
+ # Drops table
44
+ def drop_table(conn, op, buffer)
45
+ buffer << conn.send(:drop_table_sql, op.table_name) << ";\n"
46
+ op.relvar.visit{|obj,parent| op.staged!(obj)}
47
+ rescue Sequel::Error => ex
48
+ buffer << "-- UNSUPPORTED: #{op.to_sql92}" << "\n"
49
+ unsupported!(op)
50
+ end
51
+
52
+ # Mark objects as staged for an operation
53
+ def staged!(op)
54
+ if op.supports_sub_operation?(nil)
55
+ op.each_sub_operation{|kind, operand| op.staged!(operand)}
56
+ end
57
+ op.staged!(op.relvar)
58
+ end
59
+
60
+ # Mark objects as not staged for an operation
61
+ def unsupported!(op)
62
+ if op.supports_sub_operation?(nil)
63
+ op.each_sub_operation{|kind, operand| op.not_staged!(operand)}
64
+ end
65
+ op.not_staged!(op.relvar)
66
+ end
67
+
68
+ # Builds a sequel expand generator
69
+ def build_sequel_expand_generator(conn, op, generator, prefix)
70
+ op.each_sub_operation{|kind, operand|
71
+ case kind
72
+ when :attribute
73
+ args = attribute2column_args(operand)
74
+ generator.send(:"#{prefix}column", *args)
75
+ when :candidate_key
76
+ if operand.primary?
77
+ args = candidate_key2primary_key_args(operand)
78
+ generator.send(:"#{prefix}primary_key", *args)
79
+ else
80
+ args = candidate_key2unique_args(operand)
81
+ generator.send(:"#{prefix}unique", *args)
82
+ end
83
+ when :foreign_key
84
+ args = foreign_key2foreign_key_args(operand)
85
+ generator.send(:"#{prefix}foreign_key", *args)
86
+ when :index
87
+ args = index2index_args(operand)
88
+ generator.send(:"#{prefix}index", *args)
89
+ else
90
+ raise DbAgile::AssumptionFailedError, "Unknown script operation kind #{kind}"
91
+ end
92
+ }
93
+ end
94
+
95
+ # Builds a sequel collapse generator
96
+ def build_sequel_collapse_generator(conn, op, generator, prefix)
97
+ op.each_sub_operation{|kind, operand|
98
+ case kind
99
+ when :attribute
100
+ args = [ operand.name ]
101
+ generator.send(:"#{prefix}column", *args)
102
+ when :candidate_key, :foreign_key
103
+ args = [ operand.name ]
104
+ generator.send(:"#{prefix}constraint", *args)
105
+ when :index
106
+ column_names = operand.indexed_attributes.collect{|a| a.name}
107
+ args = [ column_names, {:name => operand.name}]
108
+ generator.send(:"#{prefix}index", *args)
109
+ else
110
+ raise DbAgile::AssumptionFailedError, "Unknown script operation kind #{kind}"
111
+ end
112
+ }
113
+ end
114
+
115
+ # Converts a sequel generator to SQL for a given operation
116
+ def to_sql(conn, op, generator)
117
+ case generator
118
+ when Sequel::Schema::Generator
119
+ sql = conn.send(:create_table_sql, op.table_name, generator, {})
120
+ sql = sql + ";\n"
121
+ sql
122
+ when Sequel::Schema::AlterTableGenerator
123
+ sql = conn.send(:alter_table_sql_list, op.table_name, generator.operations)
124
+ sql = sql.flatten.join(";\n")
125
+ sql + ";\n"
126
+ else
127
+ raise DbAgile::AssumptionFailedError, "Unknown generator #{gen.class}"
128
+ end
129
+ end
130
+
131
+ extend(ConcreteScript)
132
+ end # module ConcreteScript
133
+ end # module Schema
134
+ end # class SequelAdapter
135
+ end # module DbAgile
@@ -0,0 +1,106 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Schema
4
+ #
5
+ # Loads a schema from an existing database through Sequel
6
+ #
7
+ class PhysicalDump
8
+
9
+ # Returns the ruby type associated to a given column info
10
+ def dbtype_to_ruby_type(info)
11
+ type = info[:type]
12
+ capitalized = type.to_s.capitalize
13
+ begin
14
+ Kernel.eval(capitalized)
15
+ rescue NameError
16
+ case type
17
+ when :datetime
18
+ Time
19
+ when :boolean
20
+ SByC::TypeSystem::Ruby::Boolean
21
+ else
22
+ Object
23
+ end
24
+ end
25
+ end
26
+
27
+ # Runs the loading process and returns the schema instance
28
+ def run(conn, identifier)
29
+ builder = DbAgile::Core::Schema::builder
30
+ builder.schema(identifier){
31
+ builder.logical{ load_logical_schema(conn, builder) }
32
+ builder.physical{ load_physical_schema(conn, builder) }
33
+ }
34
+ builder._dump
35
+ end
36
+
37
+ def load_logical_schema(conn, builder)
38
+ conn.tables.each{|table|
39
+ load_table_schema(conn, builder, table)
40
+ }
41
+ end
42
+
43
+ # Loads a table schema
44
+ def load_table_schema(conn, builder, table)
45
+ builder.relvar(table){
46
+ primary_key_columns = load_table_heading(conn, builder, table)
47
+ load_table_constraints(conn, builder, table, primary_key_columns)
48
+ }
49
+ end
50
+
51
+ # Loads a table heading. Returns primary key columns
52
+ def load_table_heading(conn, builder, table)
53
+ primary_key_columns = []
54
+ builder.heading{
55
+ columns = conn.schema(table, {:reload => true})
56
+ columns.each do |name, info|
57
+ #puts info.inspect
58
+
59
+ # find attribute definition
60
+ defn = {:domain => dbtype_to_ruby_type(info),
61
+ :mandatory => !info[:allow_null] }
62
+ unless info[:ruby_default].nil?
63
+ defn[:default] = info[:ruby_default]
64
+ end
65
+
66
+ # mark primary key columns
67
+ if primary_key_columns and info[:primary_key]
68
+ primary_key_columns << name
69
+ end
70
+
71
+ # build the attribute
72
+ builder.attribute(name, defn)
73
+ end
74
+ }
75
+ primary_key_columns
76
+ end
77
+
78
+ # Loads table constraint
79
+ def load_table_constraints(conn, builder, table, primary_key_columns = nil)
80
+ builder.constraints{
81
+ unless primary_key_columns.nil? or primary_key_columns.empty?
82
+ builder.constraint(:pk, {:type => :primary_key, :attributes => primary_key_columns})
83
+ end
84
+ conn.indexes(table).each_pair{|name, defn|
85
+ next unless defn[:unique]
86
+ builder.constraint(name, {:type => :candidate_key, :attributes => defn[:columns]})
87
+ }
88
+ }
89
+ end
90
+
91
+ # Loads the physical schema
92
+ def load_physical_schema(conn, builder)
93
+ builder.indexes{
94
+ conn.tables.each{|table|
95
+ conn.indexes(table).each_pair{|name, defn|
96
+ next if defn[:unique]
97
+ builder.index(name, {:relvar => table, :attributes => defn[:columns]})
98
+ }
99
+ }
100
+ }
101
+ end
102
+
103
+ end # class PhysicalDump
104
+ end # module Schema
105
+ end # module Core
106
+ end # module DbAgile
@@ -0,0 +1,71 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Schema
4
+ module Schema2SequelArgs
5
+
6
+ # Converts a Ruby type to a Sequel type
7
+ def ruby_type2sequel_type(type)
8
+ if type == SByC::TypeSystem::Ruby::Boolean
9
+ TrueClass
10
+ else
11
+ type
12
+ end
13
+ end
14
+
15
+ #
16
+ # Returns Sequel's column argument from an Attribute instance
17
+ #
18
+ def attribute2column_args(attribute)
19
+ options = {:null => !attribute.mandatory?}
20
+ unless (defa = attribute.default_value).nil?
21
+ options[:default] = defa
22
+ end
23
+ domain = ruby_type2sequel_type(attribute.domain)
24
+ [attribute.name, domain, options]
25
+ end
26
+
27
+ #
28
+ # Returns Sequel's primary_key arguments from a CandidateKey
29
+ # instance
30
+ #
31
+ def candidate_key2primary_key_args(ckey)
32
+ columns = ckey.key_attributes.collect{|c| c.name}
33
+ options = {:name => ckey.name}
34
+ [ columns, options ]
35
+ end
36
+
37
+ #
38
+ # Returns Sequel's unique arguments from a CandidateKey
39
+ # instance
40
+ #
41
+ def candidate_key2unique_args(ckey)
42
+ columns = ckey.key_attributes.collect{|c| c.name}
43
+ options = {:name => ckey.name}
44
+ [ columns, options ]
45
+ end
46
+
47
+ #
48
+ # Returns Sequel's foreign_key arguments from a ForeignKey
49
+ # instance.
50
+ #
51
+ def foreign_key2foreign_key_args(fkey)
52
+ target_relvar = fkey.target_relvar.name
53
+ source_names = fkey.source_attributes.collect{|a| a.name}
54
+ target_names = fkey.target_key.key_attributes.collect{|a| a.name}
55
+ [source_names, target_relvar, { :key => target_names, :name => fkey.name }]
56
+ end
57
+
58
+ #
59
+ # Returns Sequel's index arguments from an Index instance.
60
+ #
61
+ def index2index_args(index)
62
+ attr_names = index.indexed_attributes.collect{|a| a.name}
63
+ options = {:name => index.name}
64
+ [ attr_names, options ]
65
+ end
66
+
67
+ end # module Schema2SequelArgs
68
+ end # module Schema
69
+ end # class SequelAdapter
70
+ end # module DbAgile
71
+
@@ -0,0 +1,52 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Schema
4
+ module TableDriven
5
+
6
+ # Returns the ruby type associated to a given column info
7
+ def dbtype_to_ruby_type(info)
8
+ type = info[:type]
9
+ capitalized = type.to_s.capitalize
10
+ begin
11
+ Kernel.eval(capitalized)
12
+ rescue NameError
13
+ case type
14
+ when :datetime
15
+ Time
16
+ when :boolean
17
+ SByC::TypeSystem::Ruby::Boolean
18
+ else
19
+ Object
20
+ end
21
+ end
22
+ end
23
+
24
+ # @see DbAgile::Contract::Schema::TableDriven#has_table?
25
+ def has_table?(name)
26
+ db.table_exists?(name)
27
+ end
28
+
29
+ # @see DbAgile::Contract::Schema::TableDriven#heading
30
+ def heading(table_name)
31
+ heading = {}
32
+ db.schema(table_name).each do |pair|
33
+ column_name, info = pair
34
+ heading[column_name] = dbtype_to_ruby_type(info)
35
+ end
36
+ heading
37
+ end
38
+
39
+ # @see DbAgile::Contract::Schema::TableDriven#columns_names
40
+ def column_names(table, sort_it_by_name = false)
41
+ sort_it_by_name ? db[table].columns.sort{|k1,k2| k1.to_s <=> k2.to_s} : db[table].columns
42
+ end
43
+
44
+ # @see DbAgile::Contract::Schema::TableDriven#keys
45
+ def keys(table_name)
46
+ db.indexes(table_name).values.select{|i| i[:unique] == true}.collect{|i| i[:columns]}.sort{|a1, a2| a1.size <=> a2.size}
47
+ end
48
+
49
+ end # module TableDriven
50
+ end # module Schema
51
+ end # class SequelAdapter
52
+ end # module DbAgile
@@ -0,0 +1,46 @@
1
+ module DbAgile
2
+ class SequelAdapter < Adapter
3
+ module Schema
4
+ module TransactionDriven
5
+
6
+ # @see DbAgile::Contract::Schema::TransactionDriven#run_schema_script
7
+ def run_schema_script(transaction, script, options)
8
+ buffer = ""
9
+ SequelAdapter::Schema::Stager.new(db).run(schema, buffer, options)
10
+ unless options[:dry_run]
11
+ db.execute_ddl(buffer)
12
+ end
13
+ buffer
14
+ end
15
+
16
+ # @see DbAgile::Contract::Schema::TransactionDriven#create_table
17
+ def create_table(transaction, name, columns)
18
+ db.create_table(name){
19
+ columns.each_pair{|name, type| column(name, type)}
20
+ }
21
+ columns
22
+ end
23
+
24
+ # @see DbAgile::Contract::Schema::TransactionDriven#drop_table
25
+ def drop_table(transaction, table_name)
26
+ db.drop_table(table_name)
27
+ true
28
+ end
29
+
30
+ # @see DbAgile::Contract::Schema::TransactionDriven#add_columns
31
+ def add_columns(transaction, table, columns)
32
+ db.alter_table(table) do
33
+ columns.each_pair{|name, type| add_column name, type}
34
+ end
35
+ true
36
+ end
37
+
38
+ # @see DbAgile::Contract::Schema::TransactionDriven#key!
39
+ def key!(transaction, table_name, columns)
40
+ db.add_index(table_name, columns, {:unique => true})
41
+ end
42
+
43
+ end # module TransactionDriven
44
+ end # module Schema
45
+ end # class SequelAdapter
46
+ end # module DbAgile