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 @@
1
+ require 'dbagile/command/repo/create.rb'
@@ -0,0 +1,86 @@
1
+ module DbAgile
2
+ class Command
3
+ module Robust
4
+ include DbAgile::Core::IO::Robustness
5
+
6
+ # Raises an OptionParser::InvalidArgument
7
+ def bad_argument_list!(rest, expected_name = nil)
8
+ if rest.empty?
9
+ raise OptionParser::MissingArgument, "#{expected_name}"
10
+ else
11
+ raise OptionParser::InvalidArgument, "#{rest.join(' ')}"
12
+ end
13
+ end
14
+
15
+ # Raises an OptionParser::AmbiguousArgument
16
+ def ambigous_argument_list!
17
+ raise OptionParser::AmbiguousArgument, "Ambiguous options"
18
+ end
19
+
20
+ # Parses pending arguments, assert that it contains exactly
21
+ # types.size arguments, and convert them to types.
22
+ def valid_argument_list!(rest, *types)
23
+ if rest.size == types.size
24
+ result = rest.zip(types).collect do |arg, type|
25
+ if String == type
26
+ arg.to_s
27
+ elsif Symbol == type
28
+ arg.to_sym
29
+ elsif Integer
30
+ arg.to_i
31
+ else
32
+ raise OptionParser::InvalidArgument, arg
33
+ end
34
+ end
35
+ result.size == 1 ? result[0] : result
36
+ elsif rest.size < types.size
37
+ raise OptionParser::MissingArgument
38
+ else
39
+ raise OptionParser::NeedlessArgument, rest
40
+ end
41
+ end
42
+
43
+ # Asserts that an argument matches some candidates or
44
+ # raises a OptionParser::InvalidArgument error.
45
+ def is_in!(name, value, candidates)
46
+ value = valid_argument_list!([ value ], candidates.first.class)
47
+ unless candidates.include?(value)
48
+ raise OptionParser::InvalidArgument, "Expected one of #{candidates.inspect} for #{name}"
49
+ end
50
+ value
51
+ end
52
+
53
+ # Checks that a file exists and can be read or raises an IO error
54
+ def valid_read_file!(file)
55
+ raise IOError, "Unable to read #{file}" unless File.file?(file) and File.readable?(file)
56
+ file
57
+ end
58
+
59
+ #
60
+ # Asserts that a command exists or raises a NoSuchCommandError.
61
+ #
62
+ # @return [DbAgile::Command] the command instance
63
+ #
64
+ def has_command!(name, env)
65
+ cmd = DbAgile::Command.command_for(name, env)
66
+ if cmd.nil?
67
+ DbAgile::Command::CATEGORIES.each{|c|
68
+ cmd = DbAgile::Command.command_for("#{c}:#{name}", env)
69
+ return cmd if cmd
70
+ }
71
+ raise DbAgile::NoSuchCommandError, "No such command #{name.inspect}"
72
+ else
73
+ cmd
74
+ end
75
+ end
76
+
77
+ #
78
+ # Raises a DbAgile::AssumptionFailedError with a specific message
79
+ #
80
+ def assumption_error!(msg)
81
+ raise DbAgile::AssumptionFailedError, msg
82
+ end
83
+
84
+ end # module Robust
85
+ end # class Command
86
+ end # module DbAgile
@@ -0,0 +1,59 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ #
5
+ # Check a database schema
6
+ #
7
+ # Usage: dba #{command_name} [SCHEMA.yaml|announced|effective|physical]
8
+ #
9
+ # This command informs you about bad smells and good practices with relational
10
+ # schemas (i.e. forgetting to create keys, not providing unique constraint
11
+ # names, and so on).
12
+ #
13
+ # dba #{command_name} SCHEMA.yaml
14
+ #
15
+ # Load the schema from file and check it, printing advices and errors on the
16
+ # message console. The command does not connect any database in this mode.
17
+ #
18
+ # dba #{command_name} [announced|effective|physical]
19
+ #
20
+ # Checks a schema of the current database. Announced schema is implicit without
21
+ # any argument. This command uses a fallback chain (announced -> effective ->
22
+ # physical) and has no side-effect on the database itself (read-only).
23
+ #
24
+ class Check < Command
25
+ include Schema::Commons
26
+ Command::build_me(self, __FILE__)
27
+
28
+ # Returns :single
29
+ def kind_of_schema_arguments
30
+ :single
31
+ end
32
+
33
+ # Contribute to options
34
+ def add_options(opt)
35
+ self.check_schemas = false
36
+ end
37
+
38
+ # Executes the command
39
+ def execute_command
40
+ with_schema do |schema|
41
+ errors = schema.check!(false)
42
+ say("\n")
43
+ if errors.empty?
44
+ say("Valid schema (#{schema.schema_identifier.inspect})!", :green)
45
+ say("\n")
46
+ [ schema, errors ]
47
+ else
48
+ say("Invalid schema (#{schema.schema_identifier.inspect}):", :red)
49
+ errors.error_messages.each{|m| say(" * #{m}")}
50
+ say("\n")
51
+ [ schema, errors ]
52
+ end
53
+ end
54
+ end
55
+
56
+ end # class Check
57
+ end # module Schema
58
+ end # class Command
59
+ end # module DbAgile
@@ -0,0 +1,118 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ module Commons
5
+
6
+ # Checks schema(s) first?
7
+ attr_accessor :check_schemas
8
+
9
+ # Schema arguments
10
+ attr_accessor :schema_arguments
11
+
12
+ # Adds --[no-]check option
13
+ def add_check_options(opt)
14
+ self.check_schemas = true
15
+ opt.on('--[no-]check', "Perform/Bypass schema checking") do |value|
16
+ self.check_schemas = value
17
+ end
18
+ end
19
+
20
+ # Normalizes a schema argument
21
+ def normalize_schema_argument(argument)
22
+ if File.exists?(argument) and File.file?(argument)
23
+ argument
24
+ else
25
+ is_in!("schema", argument, [:announced, :effective, :physical])
26
+ end
27
+ end
28
+
29
+ # Normalizes the pending arguments
30
+ def normalize_schema_arguments(arguments)
31
+ @schema_arguments = case kind_of_schema_arguments
32
+ when :single
33
+ if arguments.empty?
34
+ [ :announced ]
35
+ elsif arguments.size == 1
36
+ arguments.collect{|arg| normalize_schema_argument(arg) }
37
+ else
38
+ bad_argument_list!(arguments)
39
+ end
40
+ when :double
41
+ if arguments.empty?
42
+ [ :effective, :announced ]
43
+ elsif arguments.size == 2
44
+ arguments.collect{|arg| normalize_schema_argument(arg) }
45
+ else
46
+ bad_argument_list!(arguments)
47
+ end
48
+ when :multiple
49
+ if arguments.size >= 2
50
+ arguments.collect{|arg| normalize_schema_argument(arg) }
51
+ else
52
+ bad_argument_list!(arguments)
53
+ end
54
+ else
55
+ assumption_error!("Unexpected kind of schema argument #{kind_of_schema_arguments}")
56
+ end
57
+ end
58
+
59
+ # Normalizes the pending arguments
60
+ def normalize_pending_arguments(arguments)
61
+ normalize_schema_arguments(arguments)
62
+ end
63
+
64
+ # Loads a given schema from a schema argument
65
+ def load_schema(schema_argument, check = self.check_schemas)
66
+ schema = case schema_argument
67
+ when Symbol
68
+ with_current_database do |database|
69
+ case schema_argument
70
+ when :announced
71
+ database.announced_schema(true)
72
+ when :effective
73
+ database.effective_schema(true)
74
+ when :physical
75
+ database.physical_schema
76
+ end
77
+ end
78
+ when String
79
+ s = DbAgile::Core::Schema::yaml_file_load(schema_argument)
80
+ s.schema_identifier = schema_argument
81
+ s
82
+ end
83
+
84
+ # A small check, to be sure
85
+ if schema.nil?
86
+ assumption_error!("Unexpected schema argument kind #{schema_argument}")
87
+ end
88
+
89
+ # Check schema if requested
90
+ if check
91
+ schema.check!
92
+ end
93
+
94
+ # Return schema now
95
+ schema
96
+ end
97
+
98
+ # Yields the block, passing schemas as an array, according to
99
+ # kind_of_schema_arguments
100
+ def with_schemas(check = self.check_schemas)
101
+ schemas = schema_arguments.collect{|arg| load_schema(arg, check)}
102
+ case kind_of_schema_arguments
103
+ when :single
104
+ yield(schemas.first)
105
+ when :double
106
+ yield(schemas[0], schemas[1])
107
+ when :multiple
108
+ yield(schemas)
109
+ else
110
+ assumption_error!("Unexpected kind of schema argument #{kind_of_schema_arguments}")
111
+ end
112
+ end
113
+ alias :with_schema :with_schemas
114
+
115
+ end # module Commons
116
+ end # module Schema
117
+ end # class Command
118
+ end # module DbAgile
@@ -0,0 +1,101 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ #
5
+ # Show differences between database schemas
6
+ #
7
+ # Usage: dba #{command_name} [schema1 schema2]
8
+ #
9
+ # This command is a diff for database schemas, helping database staging
10
+ # and migrations by showing objects to create/drop/alter.
11
+ #
12
+ # dba #{command_name}
13
+ #
14
+ # Shortcut for 'dba schema:diff announced effective'
15
+ #
16
+ # dba #{command_name} schema1 schema2
17
+ #
18
+ # Show differences between two particular schemas, being either installed
19
+ # schemas [announced|effective|physical] or schema files. This command
20
+ # uses a fallback chain (announced -> effective -> physical) and has no
21
+ # side-effect on the database itself (read-only).
22
+ #
23
+ # NOTE: Schema-checking is on by default, which may lead to checking errors,
24
+ # typically when reverse engineering poorly designed databases. Doing so
25
+ # immediately informs you about a potential problem.
26
+ #
27
+ # Use --no-check to bypass schema checking. See also schema:check.
28
+ #
29
+ class Diff < Command
30
+ include Schema::Commons
31
+ Command::build_me(self, __FILE__)
32
+
33
+ # Output options
34
+ attr_reader :output_options
35
+
36
+ # Sets the default options
37
+ def set_default_options
38
+ @output_options = {:skip_unchanged => false}
39
+ end
40
+
41
+ # Contribute to options
42
+ def add_options(opt)
43
+ opt.separator nil
44
+ opt.separator "Options:"
45
+ add_check_options(opt)
46
+ opt.on("--[no-]skip-unchanged", "-u",
47
+ "Don't show objects that did'nt change") do |value|
48
+ self.output_options[:skip_unchanged] = value
49
+ end
50
+ end
51
+
52
+ # Returns :single
53
+ def kind_of_schema_arguments
54
+ :double
55
+ end
56
+
57
+ # Executes the command
58
+ def execute_command
59
+ with_schemas do |left, right|
60
+ merged = DbAgile::Core::Schema::merge(left, right)
61
+ show_diff(left, right, merged, environment, output_options)
62
+ merged
63
+ end
64
+ end
65
+
66
+ # Shows difference between left and right
67
+ def show_diff(left, right, merged, environment, output_options)
68
+ # Validity
69
+ if left.looks_valid?
70
+ lv = environment.color("(valid!)", :green)
71
+ else
72
+ lv = environment.color("(INVALID, you'd better run 'dba schema:check --effective')", HighLine::RED + HighLine::BOLD)
73
+ end
74
+ if right.looks_valid?
75
+ rv = environment.color("(valid!)", :green)
76
+ else
77
+ rv = environment.color("(INVALID, you'd better run 'dba schema:check')", HighLine::RED + HighLine::BOLD)
78
+ end
79
+
80
+ # Debug
81
+ ld, rd = left.schema_identifier.inspect, right.schema_identifier.inspect
82
+ ld, rd = "#{ld} #{lv}", "#{rd} #{rv}"
83
+
84
+ # Say
85
+ environment.say '###'
86
+ environment.say "### LEFT: #{ld}"
87
+ environment.say "### RIGHT: #{rd}"
88
+ environment.say '###'
89
+ environment.say "### " + environment.color('Objects to add on LEFT', :green)
90
+ environment.say '### ' + environment.color('Objects to remove on LEFT', :red)
91
+ environment.say '### ' + environment.color('Objects to alter on LEFT', :cyan)
92
+ environment.say '###'
93
+ environment.say "\n"
94
+ merged.yaml_display(environment, output_options)
95
+ environment.say "\n"
96
+ end
97
+
98
+ end # class SchemaDump
99
+ end # module Schema
100
+ end # class Command
101
+ end # module DbAgile
@@ -0,0 +1,48 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ #
5
+ # Dump a schema of the current database
6
+ #
7
+ # Usage: dba #{command_name} [announced|effective|physical]
8
+ #
9
+ # This command dumps the schema of the current database on the output console.
10
+ # Without argument, the announced schema is implicit. This command uses the
11
+ # fallback chain (announced -> effective -> physical) and has no side-effect
12
+ # on the database itself (read-only).
13
+ #
14
+ # NOTE: Schema-checking is on by default, which may lead to checking errors,
15
+ # typically when reverse engineering poorly designed databases. Doing so
16
+ # immediately informs you about a potential problem.
17
+ #
18
+ # Use --no-check to bypass schema checking. See also schema:check.
19
+ #
20
+ class Dump < Command
21
+ include Schema::Commons
22
+ Command::build_me(self, __FILE__)
23
+
24
+ # Contribute to options
25
+ def add_options(opt)
26
+ opt.separator nil
27
+ opt.separator "Options:"
28
+ add_check_options(opt)
29
+ end
30
+
31
+ # Returns :single
32
+ def kind_of_schema_arguments
33
+ :single
34
+ end
35
+
36
+ # Executes the command
37
+ def execute_command
38
+ with_schema do |schema|
39
+ say("# Schema of #{schema.schema_identifier.inspect}", :magenta)
40
+ flush(schema.to_yaml)
41
+ schema
42
+ end
43
+ end
44
+
45
+ end # class SchemaDump
46
+ end # module Schema
47
+ end # class Command
48
+ end # module DbAgile
@@ -0,0 +1,55 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ #
5
+ # Merge a list of schemas
6
+ #
7
+ # Usage: dba #{command_name} SCHEMA_ARG, ...
8
+ #
9
+ # This command merges all schema in arguments into a single schema and dumps the
10
+ # result in YAML on the output console. Schema arguments may be schema files or
11
+ # schemas installed on the current database [announced|effective|physical]. This
12
+ # command uses the fallback chain (announced -> effective -> physical) and has no
13
+ # side-effect on the database itself (read-only).
14
+ #
15
+ # NOTE: Schema-checking is on by default and applied on the resulting schema.
16
+ # This which may lead to checking errors when reverse engineering poorly
17
+ # designed databases. Doing so immediately informs you about a potential
18
+ # problem.
19
+ #
20
+ # Use --no-check to bypass schema checking. See also schema:check.
21
+ #
22
+ class Merge < Command
23
+ include Schema::Commons
24
+ Command::build_me(self, __FILE__)
25
+
26
+ # Contribute to options
27
+ def add_options(opt)
28
+ opt.separator nil
29
+ opt.separator "Options:"
30
+ add_check_options(opt)
31
+ end
32
+
33
+ # Returns :single
34
+ def kind_of_schema_arguments
35
+ :multiple
36
+ end
37
+
38
+ # Executes the command
39
+ def execute_command
40
+ with_schemas(false) do |schemas|
41
+ empty = DbAgile::Core::Schema::EMPTY_SCHEMA
42
+ result = schemas.inject(empty){|memo,schema| memo + schema}
43
+ if self.check_schemas
44
+ result.check!
45
+ say("# And the result is valid!", :green)
46
+ end
47
+ flush(result.to_yaml)
48
+ result
49
+ end
50
+ end
51
+
52
+ end # class SchemaDump
53
+ end # module Schema
54
+ end # class Command
55
+ end # module DbAgile
@@ -0,0 +1,124 @@
1
+ module DbAgile
2
+ class Command
3
+ module Schema
4
+ #
5
+ # Flush a SQL script for a creating/dropping/staging a schema
6
+ #
7
+ # Usage: dba #{command_name} {create, drop, stage} [SCHEMA_ARG, ...]
8
+ #
9
+ # dba #{command_name} create [announced|effective|physical|FILE.yaml]
10
+ #
11
+ # Flush a SQL script for creating a SQL database from a schema. Announced
12
+ # schema of the database is the default. This command uses the fallback chain
13
+ # (announced -> effective -> physical) and has no side-effect on the database
14
+ # itself (read-only).
15
+ #
16
+ # dba #{command_name} drop [announced|effective|physical|FILE.yaml]
17
+ #
18
+ # Flush a SQL script for dropping all objects of a SQL database. Announced
19
+ # schema of the database is the default. This command uses the fallback chain
20
+ # (announced -> effective -> physical) and has no side-effect on the database
21
+ # itself (read-only).
22
+ #
23
+ # dba #{command_name} stage [schema1 schema2]
24
+ #
25
+ # Flush a SQL script for staging a database from schema1 to schema2. Arguments
26
+ # can be installed schemas of the current database or schema files. Effective
27
+ # and announced schema of the current database are respectively used by default.
28
+ # The command uses the fallback chain (announced -> effective -> physical) and
29
+ # has no side-effect on the current database itself (read-only).
30
+ #
31
+ # Schema-checking is on by default, which may lead to checking errors, typically
32
+ # when reverse engineering poorly designed databases. Doing so immediately informs
33
+ # you about a potential problem.
34
+ #
35
+ # Use --no-check to bypass schema checking. See also schema:check.
36
+ #
37
+ class SqlScript < Command
38
+ include Schema::Commons
39
+ Command::build_me(self, __FILE__)
40
+
41
+ # Kinds of script
42
+ SCRIPT_KIND = [:create, :drop, :stage]
43
+
44
+ # Kind of script [:create, :drop, :stage]
45
+ attr_accessor :script_kind
46
+
47
+ # Contribute to options
48
+ def add_options(opt)
49
+ opt.separator nil
50
+ opt.separator "Options:"
51
+ add_check_options(opt)
52
+ end
53
+
54
+ # Returns :single
55
+ def kind_of_schema_arguments
56
+ if script_kind == :stage
57
+ :double
58
+ else
59
+ :single
60
+ end
61
+ end
62
+
63
+ # Normalizes the pending arguments
64
+ def normalize_pending_arguments(arguments)
65
+ case arguments.size
66
+ when 0
67
+ bad_argument_list!(arguments, "script kind")
68
+ else
69
+ self.script_kind = is_in!("script kind", arguments.shift, SCRIPT_KIND)
70
+ normalize_schema_arguments(arguments)
71
+ end
72
+ end
73
+
74
+ # Executes the command
75
+ def execute_command
76
+ case kind_of_schema_arguments
77
+ when :single
78
+ execute_single_command
79
+ when :double
80
+ execute_double_command
81
+ end
82
+ end
83
+
84
+ # Execution for :create and :drop
85
+ def execute_single_command
86
+ script = with_schema{|schema|
87
+ case self.script_kind
88
+ when :create
89
+ DbAgile::Core::Schema::create_script(schema)
90
+ when :drop
91
+ DbAgile::Core::Schema::drop_script(schema)
92
+ else
93
+ raise DbAgile::AssumptionFailedError, "Unknown script kind #{self.script_kind}"
94
+ end
95
+ }
96
+ with_current_connection{|conn|
97
+ conn.script2sql(script, environment.output_buffer)
98
+ }
99
+ end
100
+
101
+ # Execution for :stage
102
+ def execute_double_command
103
+ script = with_schemas{|left, right|
104
+ case self.script_kind
105
+ when :stage
106
+ merged = left + right
107
+ script = DbAgile::Core::Schema::stage_script(merged)
108
+ if merged.status == DbAgile::Core::Schema::NO_CHANGE
109
+ say("Nothing to stage", :magenta)
110
+ end
111
+ script
112
+ else
113
+ raise DbAgile::AssumptionFailedError, "Unknown script kind #{self.script_kind}"
114
+ end
115
+ }
116
+ with_current_connection{|conn|
117
+ conn.script2sql(script, environment.output_buffer)
118
+ }
119
+ end
120
+
121
+ end # class CreateScript
122
+ end # module Schema
123
+ end # class Command
124
+ end # module DbAgile
@@ -0,0 +1,6 @@
1
+ require 'dbagile/command/schema/commons'
2
+ require 'dbagile/command/schema/dump'
3
+ require 'dbagile/command/schema/check'
4
+ require 'dbagile/command/schema/diff'
5
+ require 'dbagile/command/schema/merge'
6
+ require 'dbagile/command/schema/sql_script'
@@ -0,0 +1,40 @@
1
+ module DbAgile
2
+ class Command
3
+ module SQL
4
+ #
5
+ # Drop a table from a SQL database
6
+ #
7
+ # Usage: dba #{command_name} TABLE
8
+ #
9
+ # This command issues a "DROP TABLE ..." in the DbAgile's command chain, therefore
10
+ # targetting the schema of the physical SQL database and bypassing other schemas if
11
+ # present (announced and effectice schemas in particular).
12
+ #
13
+ # As it may lead to divergences between schemas, and between effective and physical
14
+ # schemas in particular, you should consider using schema:* commands instead, when
15
+ # possible.
16
+ #
17
+ class Drop < Command
18
+ Command::build_me(self, __FILE__)
19
+
20
+ # Table which must be dropped
21
+ attr_accessor :table
22
+
23
+ # Normalizes the pending arguments
24
+ def normalize_pending_arguments(arguments)
25
+ self.table = valid_argument_list!(arguments, Symbol)
26
+ end
27
+
28
+ # Executes the command
29
+ def execute_command
30
+ with_current_connection do |connection|
31
+ connection.transaction do |t|
32
+ t.drop_table(self.table)
33
+ end
34
+ end
35
+ end
36
+
37
+ end # class Drop
38
+ end # module SQL
39
+ end # class Command
40
+ end # module DbAgile
@@ -0,0 +1,34 @@
1
+ module DbAgile
2
+ class Command
3
+ module SQL
4
+ #
5
+ # Show the heading of a table
6
+ #
7
+ # Usage: dba #{command_name} TABLE
8
+ #
9
+ # This commands shows a list with columns names and types for a given table
10
+ # of the current SQL database.
11
+ #
12
+ class Heading < Command
13
+ Command::build_me(self, __FILE__)
14
+
15
+ # Table whose heading must be displayed
16
+ attr_accessor :dataset
17
+
18
+ # Normalizes the pending arguments
19
+ def normalize_pending_arguments(arguments)
20
+ self.dataset = valid_argument_list!(arguments, Symbol)
21
+ end
22
+
23
+ # Executes the command
24
+ def execute_command
25
+ with_current_connection do |connection|
26
+ heading = connection.heading(self.dataset)
27
+ flush("{\n" + heading.collect{|pair| " #{pair[0]}: #{pair[1]}"}.join(",\n") + "\n}\n")
28
+ heading
29
+ end
30
+ end
31
+ end # class Heading
32
+ end # # module SQL
33
+ end # class Command
34
+ end # module DbAgile