dbagile 0.0.1

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 (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