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
@@ -0,0 +1,103 @@
1
+ module DbAgile
2
+ class Command
3
+ module ClassMethods
4
+
5
+ # The command summary
6
+ attr_reader :summary
7
+
8
+ # The command banner
9
+ attr_reader :usage
10
+
11
+ # Command description
12
+ attr_reader :description
13
+
14
+ # Helper to generate command classes
15
+ def build_me(command_class, file)
16
+ rdoc = DbAgile::RubyTools::rdoc_file_paragraphs(file)
17
+ summary, usage, description = rdoc.shift, rdoc.shift, rdoc.join("\n")
18
+ command_class.instance_eval{
19
+ @summary = summary
20
+ @usage = usage.gsub('#{command_name}', command_class.command_name)
21
+ @description = description.gsub('#{command_name}', command_class.command_name)
22
+ }
23
+ end
24
+
25
+ # Tracks subclasses for maintaining subcommand list
26
+ def inherited(subclass)
27
+ super
28
+ @subclasses ||= []
29
+ @subclasses << subclass
30
+ end
31
+
32
+ # Returns the array of known command sub-classes
33
+ def subclasses
34
+ @subclasses
35
+ end
36
+
37
+ # Yields the block with each subclass in turn
38
+ def each_subclass(&block)
39
+ subclasses.each(&block)
40
+ end
41
+
42
+ # Returns the command name of a given class
43
+ def command_name_of(clazz)
44
+ name = DbAgile::RubyTools::unqualified_class_name(clazz)
45
+ name = name.gsub(/[A-Z]/){|x| "-#{x.downcase}"}[1..-1]
46
+ parent_module = DbAgile::RubyTools::parent_module(clazz)
47
+ if parent_module == DbAgile::Command
48
+ name
49
+ else
50
+ parent_name = DbAgile::RubyTools::unqualified_class_name(parent_module)
51
+ "#{parent_name.downcase}:#{name}"
52
+ end
53
+ end
54
+
55
+ # Returns command category
56
+ def category
57
+ parent = DbAgile::RubyTools::parent_module(self)
58
+ if parent == DbAgile::Command
59
+ :dba
60
+ else
61
+ DbAgile::RubyTools::unqualified_class_name(parent).to_s.downcase.to_sym
62
+ end
63
+ end
64
+
65
+ # Returns command name
66
+ def command_name
67
+ command_name_of(self)
68
+ end
69
+
70
+ # Returns the ruby name of a given class
71
+ def ruby_method_for(clazz)
72
+ command_name_of(clazz).gsub(/[:\-]/, '_').to_sym
73
+ end
74
+
75
+ # Returns a command instance for a given name and environment,
76
+ # returns nil if it cannot be found
77
+ def command_for(name_symbol_or_class, env)
78
+ subclass = case name_symbol_or_class
79
+ when String
80
+ subclasses.find{|subclass| command_name_of(subclass) == name_symbol_or_class}
81
+ when Symbol
82
+ subclasses.find{|subclass| ruby_method_for(subclass) == name_symbol_or_class}
83
+ when Class
84
+ name_symbol_or_class
85
+ end
86
+ subclass.nil? ? nil : subclass.new(env)
87
+ end
88
+
89
+ # Builds command options
90
+ def build_command_options(options)
91
+ case options
92
+ when Array
93
+ options
94
+ when String
95
+ options.split
96
+ else
97
+ raise ArgumentError, "Invalid options #{options}"
98
+ end
99
+ end
100
+
101
+ end # module ClassMethods
102
+ end # class Command
103
+ end # module DbAgile
@@ -0,0 +1,94 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # Add a new database configuration
6
+ #
7
+ # Usage: dba #{command_name} NAME URI
8
+ #
9
+ class Add < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ # Database name
13
+ attr_accessor :db_name
14
+
15
+ # Database URI
16
+ attr_accessor :uri
17
+
18
+ # Makes it the current database?
19
+ attr_accessor :current
20
+
21
+ # Sets the default options
22
+ def set_default_options
23
+ @current = true
24
+ end
25
+
26
+ # Contribute to options
27
+ def add_options(opt)
28
+ opt.separator nil
29
+ opt.separator "Options:"
30
+ opt.on("--[no-]current", "Set as current database when created (see use)") do |value|
31
+ self.current = false
32
+ end
33
+ end
34
+
35
+ # Normalizes the pending arguments
36
+ def normalize_pending_arguments(arguments)
37
+ self.db_name, self.uri = valid_argument_list!(arguments, Symbol, String)
38
+ end
39
+
40
+ # Checks command
41
+ def check_command
42
+ valid_database_name!(self.db_name)
43
+ valid_database_uri!(self.uri)
44
+ end
45
+
46
+ #
47
+ # Executes the command.
48
+ #
49
+ # @return [DbAgile::Core::Database] the created database
50
+ #
51
+ def execute_command
52
+ db = nil
53
+ with_repository do |repository|
54
+
55
+ if repository.has_database?(self.db_name)
56
+ raise DatabaseNameConflictError, "Database #{self.db_name} already exists"
57
+ else
58
+ # Create the database and adds it
59
+ name, uri = self.db_name, self.uri
60
+ db = DbAgile::Core::Database.new(name, uri)
61
+ repository << db
62
+ infer_schemas(db) if db.ping?
63
+
64
+ # Makes it the current one if requested
65
+ if self.current
66
+ repository.current_db_name = db.name
67
+ end
68
+
69
+ # Flush the repository file
70
+ repository.save!
71
+ end
72
+
73
+ end
74
+
75
+ # List available databases now
76
+ DbAgile::dba(environment){|dba| dba.db_list %w{}}
77
+
78
+ # Returns created database
79
+ db
80
+ end
81
+
82
+ # Infers database schemas
83
+ def infer_schemas(db)
84
+ schema = db.physical_schema
85
+ db.set_announced_schema(schema)
86
+ db.set_effective_schema(schema)
87
+ rescue => ex
88
+ say("An error occured when infering schema: #{ex.message}\nYou'll have to install them manually. Sorry", :magenta)
89
+ end
90
+
91
+ end # class Add
92
+ end # module Db
93
+ end # class Command
94
+ end # module DbAgile
@@ -0,0 +1,40 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # List available databases in current repository
6
+ #
7
+ # Usage: dba #{command_name}
8
+ #
9
+ class List < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ #
13
+ # Executes the command.
14
+ #
15
+ # @return [DbAgile::Core::Repository] the repository instance
16
+ #
17
+ def execute_command
18
+ with_repository do |repository|
19
+
20
+ unless repository.empty?
21
+ flush("Available databases are (#{repository.friendly_path}):")
22
+ repository.each do |database|
23
+ msg = repository.current?(database) ? " -> " : " "*5
24
+ msg += database.name.to_s.ljust(15)
25
+ msg += " "
26
+ msg += database.uri
27
+ flush(msg)
28
+ end
29
+ else
30
+ say("No database found. Check #{repository.friendly_path}", :magenta)
31
+ end
32
+
33
+ repository
34
+ end
35
+ end
36
+
37
+ end # class List
38
+ end # module Db
39
+ end # class Command
40
+ end # module DbAgile
@@ -0,0 +1,49 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # Ping a database (current one by default)
6
+ #
7
+ # Usage: dba #{command_name} [CONFIG]
8
+ #
9
+ class Ping < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ # Name of the database to ping
13
+ attr_accessor :match
14
+
15
+ # Normalizes the pending arguments
16
+ def normalize_pending_arguments(arguments)
17
+ if arguments.empty?
18
+ self.match = nil
19
+ else
20
+ self.match = valid_argument_list!(arguments, Symbol)
21
+ self.match = valid_database_name!(self.match)
22
+ end
23
+ end
24
+
25
+ # Executes the command
26
+ def execute_command
27
+ cf = with_repository do |repository|
28
+
29
+ db = has_database!(repository, self.match)
30
+
31
+ # Make the job now
32
+ begin
33
+ with_connection(db){|c| c.ping}
34
+ flush("Ping ok (#{db.uri})")
35
+ db
36
+ rescue StandardError => ex
37
+ flush("Ping KO (#{db.uri})", :red)
38
+ flush(ex.message)
39
+ ex
40
+ end
41
+
42
+ end
43
+ cf
44
+ end
45
+
46
+ end # class Ping
47
+ end # module Db
48
+ end # class Command
49
+ end # module DbAgile
@@ -0,0 +1,52 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # Remove a database configuration from the repository
6
+ #
7
+ # Usage: dba #{command_name} CONFIG
8
+ #
9
+ class Rm < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ # Name of the database to remove
13
+ attr_accessor :match
14
+
15
+ # Normalizes the pending arguments
16
+ def normalize_pending_arguments(arguments)
17
+ self.match = valid_argument_list!(arguments, Symbol)
18
+ self.match = valid_database_name!(self.match)
19
+ end
20
+
21
+ #
22
+ # Executes the command.
23
+ #
24
+ # @return [DbAgile::Core::Repository] the repository instance
25
+ #
26
+ def execute_command
27
+ cf = with_repository do |repository|
28
+ db = has_database!(repository, self.match)
29
+
30
+ # Move the current one if it was it
31
+ if repository.current?(db)
32
+ repository.current_db_name = nil
33
+ end
34
+
35
+ # Removes it from file
36
+ repository.remove(db)
37
+
38
+ # Flush the repository file
39
+ repository.save!
40
+ end
41
+
42
+ # List available databases now
43
+ DbAgile::dba(environment){|dba| dba.db_list %w{}}
44
+
45
+ # Returns repository
46
+ cf
47
+ end
48
+
49
+ end # class Rm
50
+ end # module Db
51
+ end # class Command
52
+ end # module DbAgile
@@ -0,0 +1,81 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # Stage the current database
6
+ #
7
+ # Usage: dba #{command_name}
8
+ #
9
+ class Stage < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ #
13
+ # Executes the command.
14
+ #
15
+ # @return [DbAgile::Core::Database] the database
16
+ #
17
+ def execute_command
18
+ with_current_database do |db|
19
+ # left, right and merge
20
+ left = db.effective_schema(true)
21
+ right = db.announced_schema(true)
22
+ merged = left + right
23
+
24
+ # Bypass situations
25
+ if merged.status == DbAgile::Core::Schema::NO_CHANGE
26
+ say("Nothing to stage", :magenta)
27
+ return
28
+ elsif environment.interactive?
29
+ # Show what will be performed
30
+ DbAgile::dba(environment){|dba| dba.schema_diff %w{-u effective announced}}
31
+ say("---")
32
+ DbAgile::dba(environment){|dba| dba.schema_sql_script %w{stage effective announced}}
33
+ say("\n")
34
+
35
+ # Ask confirmation now
36
+ answer = environment.ask("Are you sure?"){|q| q.validate = /^y(es)?|n(o)?|q(uit)?/i}
37
+ return unless answer =~ /^y/i
38
+ end
39
+
40
+ # Everything seems ok now!
41
+ begin
42
+ stage(db, merged)
43
+ rescue => ex
44
+ say("Sorry, staging process failed for some reason.", :red)
45
+ raise
46
+ end
47
+ end
48
+ end
49
+
50
+ # Makes staging itself
51
+ def stage(db, merged)
52
+ script = DbAgile::Core::Schema::stage_script(merged)
53
+ with_connection(db) do |conn|
54
+
55
+ # stage the real database
56
+ sql_script = conn.script2sql(script)
57
+ conn.transaction do |t|
58
+ t.direct_sql(sql_script)
59
+
60
+ # split schemas now
61
+ schemas = merged.split{|obj|
62
+ case obj.status
63
+ when DbAgile::Core::Schema::DROPPED
64
+ :dropped
65
+ else
66
+ :effective
67
+ end
68
+ }
69
+
70
+ # save schemas
71
+ if s = schemas[:effective]
72
+ db.set_effective_schema(s)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ end # class Stage
79
+ end # module Db
80
+ end # class Command
81
+ end # module DbAgile
@@ -0,0 +1,48 @@
1
+ module DbAgile
2
+ class Command
3
+ module Db
4
+ #
5
+ # Set the current database to use
6
+ #
7
+ # Usage: dba #{command_name} CONFIG
8
+ #
9
+ class Use < Command
10
+ Command::build_me(self, __FILE__)
11
+
12
+ # Database name
13
+ attr_accessor :match
14
+
15
+ # Normalizes the pending arguments
16
+ def normalize_pending_arguments(arguments)
17
+ self.match = valid_argument_list!(arguments, Symbol)
18
+ self.match = valid_database_name!(self.match)
19
+ end
20
+
21
+ #
22
+ # Executes the command.
23
+ #
24
+ # @return [DbAgile::Core::Database] the used database
25
+ #
26
+ def execute_command
27
+ db = nil
28
+ with_repository do |repository|
29
+ db = has_database!(repository, self.match)
30
+
31
+ # Makes it the current one
32
+ repository.current_db_name = db.name
33
+
34
+ # Flush the repository file
35
+ repository.save!
36
+ end
37
+
38
+ # List available databases now
39
+ DbAgile::dba(environment){|dba| dba.db_list %w{}}
40
+
41
+ # Return current database
42
+ db
43
+ end
44
+
45
+ end # class Use
46
+ end # module Db
47
+ end # class Command
48
+ end # module DbAgile
@@ -0,0 +1,6 @@
1
+ require 'dbagile/command/db/add'
2
+ require 'dbagile/command/db/rm'
3
+ require 'dbagile/command/db/list'
4
+ require 'dbagile/command/db/use'
5
+ require 'dbagile/command/db/ping'
6
+ require 'dbagile/command/db/stage'
@@ -0,0 +1,121 @@
1
+ module DbAgile
2
+ class Command
3
+ #
4
+ # Agile SQL databases and tools for database administrators
5
+ #
6
+ # Usage: dba [--help] [--version]
7
+ # dba help <subcommand>
8
+ # dba [--repository=DIR] [--use=DB] [--no-interactive] <subcommand> [OPTIONS] [ARGS]
9
+ #
10
+ # DbAgile aims at supporting database administrators and developers of database
11
+ # oriented application. Read more about it on http://blambeau.github.com/dbagile.
12
+ #
13
+ class Dba < Command
14
+ Command::build_me(self, __FILE__)
15
+
16
+ # Continue after my options
17
+ attr_accessor :stop_after_options
18
+
19
+ # Contribute to options
20
+ def add_options(opt)
21
+ opt.separator nil
22
+ opt.separator "Options:"
23
+ opt.on("--repository=DIR",
24
+ "Use a specific repository (current is #{environment.friendly_repository_path})") do |value|
25
+ environment.repository_path = value
26
+ end
27
+ opt.on("--use=DB",
28
+ "Use a specific database") do |value|
29
+ environment.repository.current_db_name = value.to_sym
30
+ end
31
+ opt.on("--[no-]interactive", "[Dis-]allow interactive mode") do |value|
32
+ environment.interactive = value
33
+ end
34
+ opt.on("--[no-]backtrace", "Print a backtrace when an error occurs") do |value|
35
+ environment.show_backtrace = value
36
+ end
37
+ opt.on_tail("--help", "Show list of available subcommands") do
38
+ show_long_help
39
+ self.stop_after_options = true
40
+ end
41
+ opt.on_tail("--version", "Show version") do
42
+ flush("dba" << " " << DbAgile::VERSION << " (c) 2010, Bernard Lambeau")
43
+ self.stop_after_options = true
44
+ end
45
+ end
46
+
47
+ # Returns commands by category
48
+ def commands_by_categ
49
+ return @commands_by_categ if @commands_by_categ
50
+ @commands_by_categ = Hash.new{|h,k| h[k] = []}
51
+ Command.subclasses.each do |subclass|
52
+ next if subclass == Dba
53
+ name = Command::command_name_of(subclass)
54
+ command = Command::command_for(name, environment)
55
+ category = command.category
56
+ raise "Unknown command category #{category}" unless DbAgile::Command::CATEGORIES.include?(category)
57
+ @commands_by_categ[category] << command
58
+ end
59
+ @commands_by_categ
60
+ end
61
+
62
+ # Show command help for a specific category
63
+ def show_commands_help(category)
64
+ commands_by_categ[category].each do |command|
65
+ flush(options.summary_indent + command.command_name.ljust(30) + command.summary.to_s)
66
+ end
67
+ end
68
+
69
+ # Shows the short help
70
+ def show_short_help
71
+ flush banner
72
+ flush options.summarize
73
+ flush "\n"
74
+ end
75
+ alias :show_help :show_short_help
76
+
77
+ # Shows the long help
78
+ def show_long_help
79
+ show_short_help
80
+ DbAgile::Command::CATEGORIES.each{|categ|
81
+ flush DbAgile::Command::CATEGORY_NAMES[categ]
82
+ show_commands_help(categ)
83
+ flush "\n"
84
+ }
85
+ end
86
+
87
+ # Runs the command
88
+ def unsecure_run(requester_file, argv)
89
+ # My own options
90
+ my_args = []
91
+ while argv.first =~ /^--/
92
+ my_args << argv.shift
93
+ end
94
+ options.parse!(my_args)
95
+
96
+ # Invoke sub command
97
+ unless stop_after_options
98
+ invoke_subcommand(requester_file, argv)
99
+ end
100
+ rescue Exception => ex
101
+ environment.on_error(self, ex)
102
+ environment
103
+ end
104
+
105
+ # Invokes the subcommand
106
+ def invoke_subcommand(requester_file, argv)
107
+ # Command execution
108
+ if argv.size >= 1
109
+ DbAgile::Core::Repository::Builder.new(environment).ensure_repository{
110
+ command = has_command!(argv.shift, environment)
111
+ command.run(requester_file, argv)
112
+ }
113
+ else
114
+ show_long_help
115
+ end
116
+ end
117
+
118
+
119
+ end # class DbA
120
+ end # class Command
121
+ end # module DbAgile
@@ -0,0 +1,50 @@
1
+ module DbAgile
2
+ class Command
3
+ #
4
+ # Show help of a given command
5
+ #
6
+ # Usage: dba #{command_name} COMMAND
7
+ #
8
+ class Help < Command
9
+ Command::build_me(self, __FILE__)
10
+
11
+ # Command name
12
+ attr_accessor :command
13
+
14
+ # Normalizes the pending arguments
15
+ def normalize_pending_arguments(arguments)
16
+ self.command = valid_argument_list!(arguments, String)
17
+ self.command = has_command!(self.command, environment)
18
+ end
19
+
20
+ # Executes the command
21
+ def execute_command
22
+ flush(command.usage)
23
+ flush("\n")
24
+ #
25
+ flush("Description:")
26
+ flush("")
27
+ flush(" " + command.summary)
28
+ #
29
+ options = command.options.summarize
30
+ unless options.empty?
31
+ flush(options.join)
32
+ flush("\n")
33
+ else
34
+ flush("\n")
35
+ end
36
+ #
37
+ description = command.description.to_s
38
+ if description.strip.empty?
39
+ flush("Sorry, no more information available yet")
40
+ else
41
+ flush("Detailed documentation:")
42
+ flush("")
43
+ flush(description.gsub(/^/, " "))
44
+ flush("")
45
+ end
46
+ end
47
+
48
+ end # class List
49
+ end # class Command
50
+ end # module DbAgile
@@ -0,0 +1,54 @@
1
+ module DbAgile
2
+ class Command
3
+ module Repo
4
+ #
5
+ # Create a fresh dbagile repository in a specific directory
6
+ #
7
+ # Usage: dba #{command_name} [DIR]
8
+ #
9
+ # This commands creates a dbagile repository in a directory. When
10
+ # none is specified, it will create a repository under 'dbagile'
11
+ # in the current folder.
12
+ #
13
+ class Create < Command
14
+ Command::build_me(self, __FILE__)
15
+
16
+ # Where does the repository must be create?
17
+ attr_accessor :where
18
+
19
+ # Force repository creation?
20
+ attr_accessor :force
21
+
22
+ # Contribute to options
23
+ def add_options(opt)
24
+ self.force = false
25
+ opt.separator nil
26
+ opt.separator "Options:"
27
+ opt.on("--force",
28
+ "Force creation of the repository, removing the folder if it already exists") do |value|
29
+ self.force = true
30
+ end
31
+ end
32
+
33
+ # Normalizes the pending arguments
34
+ def normalize_pending_arguments(arguments)
35
+ if arguments.empty?
36
+ self.where = "dbagile"
37
+ else
38
+ self.where = valid_argument_list!(arguments, String)
39
+ end
40
+ end
41
+
42
+ # Executes the command
43
+ def execute_command
44
+ if File::exists?(self.where) and self.force
45
+ FileUtils::rm_rf(self.where)
46
+ end
47
+ DbAgile::Core::Repository::create!(self.where)
48
+ say("Repository successfully created!", :magenta)
49
+ end
50
+
51
+ end # class Create
52
+ end # module Repo
53
+ end # class Command
54
+ end # module DbAgile