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,144 @@
1
+ module DbAgile
2
+ class SequelAdapter
3
+ class SequelTracer
4
+ include DbAgile::Contract::Utils::Delegate
5
+
6
+ ### INIT AND OPTIONS #########################################################
7
+
8
+ # Default options of this adapter
9
+ DEFAULT_OPTIONS = {
10
+ :trace_sql => false,
11
+ :trace_only => false,
12
+ :trace_buffer => STDERR
13
+ }
14
+
15
+ # Adapter delegate
16
+ attr_reader :delegate
17
+
18
+ # Creates a tracer instance
19
+ def initialize(delegate, options)
20
+ raise ArgumentError, "Connection options should be a Hash" unless options.kind_of?(Hash)
21
+ @delegate = delegate
22
+ @options = DEFAULT_OPTIONS.merge(options)
23
+ end
24
+
25
+ # Tracing is on?
26
+ def trace?
27
+ @trace ||= (@options[:trace_sql] && !trace_buffer.nil?)
28
+ end
29
+
30
+ # Only traces, forget about delegation?
31
+ def trace_only?
32
+ @trace_only ||= @options[:trace_only]
33
+ end
34
+
35
+ # Returns the tracing buffer
36
+ def trace_buffer
37
+ @buffer ||= @options[:trace_buffer]
38
+ end
39
+
40
+ ### UTILS ####################################################################
41
+
42
+ # Returns SQL statement for a given alter table block
43
+ def alter_table_sql(table_name, &block)
44
+ generator = ::Sequel::Schema::AlterTableGenerator.new(self, &block)
45
+ sqls = delegate.db.send(:alter_table_sql_list, table_name, generator.operations).flatten
46
+ sqls.join("\n")
47
+ end
48
+
49
+ ### SCHEMA UPDATES ###########################################################
50
+
51
+ # Creates a table with some columns.
52
+ def create_table(transaction, table_name, columns)
53
+ if trace?
54
+ gen = ::Sequel::Schema::Generator.new(self){
55
+ columns.each_pair{|name, type| column(name, type)}
56
+ }
57
+ sql = delegate.db.send(:create_table_sql, table_name, gen, {})
58
+ trace(sql)
59
+ end
60
+ return super unless trace_only?
61
+ nil
62
+ end
63
+
64
+ # Adds some columns to a table
65
+ def add_columns(transaction, table_name, columns)
66
+ if trace?
67
+ trace(alter_table_sql(table_name){
68
+ columns.each_pair{|name, type| add_column(name, type)}
69
+ })
70
+ end
71
+ return super unless trace_only?
72
+ nil
73
+ end
74
+
75
+ # Make columns be a candidate key for the table.
76
+ def key!(transaction, table_name, columns)
77
+ if trace?
78
+ trace(alter_table_sql(table_name){
79
+ add_index(columns, :unique => true)
80
+ })
81
+ end
82
+ return super unless trace_only?
83
+ nil
84
+ end
85
+
86
+ ### DATA UPDATES #############################################################
87
+
88
+ # Inserts a tuple inside a given table
89
+ def insert(transaction, table_name, record)
90
+ if trace?
91
+ trace(delegate.db[table_name].insert_sql(record))
92
+ end
93
+ return super unless trace_only?
94
+ record
95
+ end
96
+
97
+ # Updates a project of a given table
98
+ def update(transaction, table_name, proj, update)
99
+ if trace?
100
+ trace(delegate.db[table_name].where(proj).update_sql(update))
101
+ end
102
+ return super unless trace_only?
103
+ true
104
+ end
105
+
106
+ # Deletes a projection from a given table
107
+ def delete(transaction, table_name, proj = {})
108
+ if trace?
109
+ if proj.empty?
110
+ trace(delegate.db[table_name].delete_sql)
111
+ else
112
+ trace(delegate.db[table_name].where(proj).delete_sql)
113
+ end
114
+ end
115
+ return super unless trace_only?
116
+ true
117
+ end
118
+
119
+ # Sends SQL directly to the database SQL server.
120
+ def direct_sql(transaction, sql)
121
+ if trace?
122
+ trace(sql)
123
+ end
124
+ return super unless trace_only?
125
+ nil
126
+ end
127
+
128
+ ### ABOUT TRACING ############################################################
129
+
130
+ # Traces a SQL statement. Returns true if trace_only, false
131
+ # otherwise
132
+ def trace(sql)
133
+ case out = trace_buffer
134
+ when Logger
135
+ out.info(sql)
136
+ else
137
+ out << "#{sql}\n"
138
+ end
139
+ sql
140
+ end
141
+
142
+ end # class SequelTracer
143
+ end # class SequelAdapter
144
+ end # module DbAgile
@@ -0,0 +1,46 @@
1
+ require 'dbagile/adapter/sequel/class_methods'
2
+ require 'dbagile/adapter/sequel/connection'
3
+
4
+ require 'dbagile/adapter/sequel/data/table_driven'
5
+ require 'dbagile/adapter/sequel/data/transaction_driven'
6
+
7
+ require 'dbagile/adapter/sequel/schema/physical_dump'
8
+ require 'dbagile/adapter/sequel/schema/schema2sequel_args'
9
+ require 'dbagile/adapter/sequel/schema/concrete_script'
10
+ require 'dbagile/adapter/sequel/schema/table_driven'
11
+ require 'dbagile/adapter/sequel/schema/transaction_driven'
12
+ module DbAgile
13
+ #
14
+ # Implements the Adapter contract using Sequel.
15
+ #
16
+ class SequelAdapter < Adapter
17
+ extend SequelAdapter::ClassMethods
18
+ include SequelAdapter::Connection
19
+ include SequelAdapter::Data::TableDriven
20
+ include SequelAdapter::Data::TransactionDriven
21
+ include SequelAdapter::Schema::TableDriven
22
+ include SequelAdapter::Schema::TransactionDriven
23
+
24
+ # Underlying database URI
25
+ attr_reader :uri
26
+
27
+ # Connection options
28
+ attr_reader :options
29
+
30
+ # Creates an adapter with a given uri
31
+ def initialize(uri, options = {})
32
+ @uri, @options = uri, options
33
+ end
34
+
35
+ # Returns the underlying Sequel::Database instance
36
+ def db
37
+ unless @db
38
+ @db = ::Sequel.connect(uri)
39
+ @db.logger = @options[:sequel_logger]
40
+ end
41
+ @db
42
+ end
43
+
44
+ end # class SequelAdapter
45
+ end # module DbAgile
46
+ require 'dbagile/adapter/sequel/sequel_tracer'
@@ -0,0 +1,15 @@
1
+ module DbAgile
2
+ class Adapter
3
+ include DbAgile::Contract::Robust::Helpers
4
+ include DbAgile::Contract::Utils::Full
5
+
6
+ # Builds an adapter instance from an URI
7
+ def self.factor(uri, options = {})
8
+ return uri if uri.kind_of?(Adapter)
9
+ DbAgile::SequelAdapter.new(uri, options)
10
+ end
11
+ def self.[](*args) factor(*args) end
12
+
13
+ end # class Adapter
14
+ end # module DbAgile
15
+ require 'dbagile/adapter/sequel'
@@ -0,0 +1,49 @@
1
+ module DbAgile
2
+ class Command
3
+ class API
4
+ include DbAgile::Environment::Delegator
5
+
6
+ # Underlying environment
7
+ attr_reader :environment
8
+
9
+ # Creates an API instance for a given environment
10
+ def initialize(environment)
11
+ @environment = environment
12
+ end
13
+
14
+ ##############################################################################
15
+ # Ruby commands
16
+ ##############################################################################
17
+
18
+ # Returns a dataset instance
19
+ def dataset(name)
20
+ environment.with_current_connection{|c|
21
+ c.dataset(name)
22
+ }
23
+ end
24
+
25
+ ##############################################################################
26
+ # Console subcommands mimics
27
+ ##############################################################################
28
+
29
+ # Add API methods to Command class
30
+ DbAgile::Command::each_subclass do |subclass|
31
+ method_name = DbAgile::Command::ruby_method_for(subclass)
32
+ module_eval <<-EOF
33
+ def #{method_name}(*options)
34
+ options = options.flatten
35
+ command = DbAgile::Command::command_for(#{subclass.name}, environment)
36
+ options = DbAgile::Command::build_command_options(options)
37
+ command.unsecure_run(__FILE__, options)
38
+ end
39
+ EOF
40
+ end
41
+
42
+ # Delegates this api on a environment duplication
43
+ def dup
44
+ API.new(environment.dup)
45
+ end
46
+
47
+ end # class API
48
+ end # class Command
49
+ end # module DbAgile
@@ -0,0 +1,130 @@
1
+ module DbAgile
2
+ class Command
3
+ module Bulk
4
+ module Commons
5
+
6
+ # Output/input format [ruby, csv, json]
7
+ attr_accessor :format
8
+
9
+ # Connection options
10
+ attr_accessor :conn_options
11
+
12
+ # Input/output options
13
+ attr_accessor :io_options
14
+
15
+ # Type system to use
16
+ attr_accessor :type_system
17
+
18
+ # Dataset whose contents must be shown
19
+ attr_accessor :dataset
20
+
21
+ # Columns to select
22
+ attr_accessor :select
23
+
24
+ # Columns to allbut
25
+ attr_accessor :allbut
26
+
27
+ # Builds default io options
28
+ def set_default_options
29
+ self.format = :csv
30
+ self.type_system = nil
31
+ self.conn_options = {}
32
+ self.io_options = Hash.new{|h,k| h[k] = {}}
33
+ end
34
+
35
+ # Adds the select/allbut options
36
+ def add_select_options(opt)
37
+ opt.on('--select x,y,z', Array,
38
+ "Select x, y, z columns only") do |value|
39
+ self.select = value.collect{|c| c.to_sym}
40
+ end
41
+ opt.on('--allbut x,y,z', Array,
42
+ "Select all but x, y, z columns") do |value|
43
+ self.allbut = value.collect{|c| c.to_sym}
44
+ end
45
+ end
46
+
47
+ def add_typesafe_options(opt)
48
+ opt.on("--type-safe=[X]", [:ruby],
49
+ "Read/Write type-safe values for (ruby)") do |value|
50
+ case value
51
+ when :ruby, NilClass
52
+ require 'sbyc/type_system/ruby'
53
+ self.type_system = SByC::TypeSystem::Ruby
54
+ else
55
+ raise ArgumentError, "Unknown type system #{value}"
56
+ end
57
+ end
58
+ end
59
+
60
+ # Adds the format options for output
61
+ def add_output_format_options(opt)
62
+ opt.on('--format=X', [:csv, :text, :json, :yaml, :ruby, :xml],
63
+ "Export dataset in (csv, text, json, yaml, ruby, xml)") do |value|
64
+ self.format = value
65
+ end
66
+ opt.on("--csv", "Export dataset in csv (default)"){ self.format = :csv }
67
+ opt.on("--text", "Export dataset as a plain text table"){ self.format = :text }
68
+ opt.on("--json", "Export dataset in json"){ self.format = :json }
69
+ opt.on("--yaml", "Export dataset in yaml"){ self.format = :yaml }
70
+ opt.on("--xml", "Export dataset in xml"){ self.format = :xml }
71
+ opt.on("--ruby", "Export dataset as ruby code"){ self.format = :ruby }
72
+ end
73
+
74
+ # Adds the format options for input
75
+ def add_input_format_options(opt)
76
+ opt.on('--format=X', [:csv, :json, :yaml, :ruby],
77
+ "Import dataset from (csv, json, yaml, ruby)") do |value|
78
+ self.format = value
79
+ end
80
+ opt.on("--csv", "Import dataset from csv (default)"){ self.format = :csv }
81
+ opt.on("--json", "Import dataset from json"){ self.format = :json }
82
+ opt.on("--ruby", "Import dataset from ruby code"){ self.format = :ruby }
83
+ opt.on("--yaml", "Import dataset from yaml"){ self.format = :yaml }
84
+ end
85
+
86
+ # Adds the CSV options
87
+ def add_csv_options(opt)
88
+ opt.on("--headers", "-h", "Read/Write column names on first line") do
89
+ io_options[:csv][:headers] = true
90
+ end
91
+ opt.on("--separator=C", "Use C as column separator character") do |value|
92
+ io_options[:csv][:col_sep] = value
93
+ end
94
+ opt.on("--quote=C", "Use C as quoting character") do |value|
95
+ io_options[:csv][:quote_char] = value
96
+ end
97
+ opt.on("--force-quotes", "Force quoting?") do
98
+ io_options[:csv][:force_quotes] = true
99
+ end
100
+ opt.on("--skip-blanks", "Skip blank lines?") do
101
+ io_options[:csv][:skip_blanks] = true
102
+ end
103
+ end
104
+ alias :add_csv_input_options :add_csv_options
105
+ alias :add_csv_output_options :add_csv_options
106
+
107
+ # Adds output JSON options
108
+ def add_json_output_options(opt)
109
+ opt.on("--[no-]pretty", "Generate a pretty JSON document") do |value|
110
+ io_options[:json][:pretty] = value
111
+ end
112
+ end
113
+
114
+ # Adds output TEXT options
115
+ def add_text_output_options(opt)
116
+ opt.on("--wrap-at=X", Integer,
117
+ "Wraps table after X's character (no wrap by default)") do |x|
118
+ io_options[:text][:wrap_at] = x
119
+ end
120
+ opt.on("--truncate-at=X", Integer,
121
+ "Truncate row lines at X character") do |x|
122
+ io_options[:text][:truncate_at] = x
123
+ io_options[:text][:append_with] = '...'
124
+ end
125
+ end
126
+
127
+ end # module Commons
128
+ end # module Bulk
129
+ end # class Command
130
+ end # module DbAgile
@@ -0,0 +1,99 @@
1
+ module DbAgile
2
+ class Command
3
+ module Bulk
4
+ #
5
+ # Export a table/view/query to (csv, json, yaml, ruby, xml)
6
+ #
7
+ # Usage: dba #{command_name} [OPTIONS] DATASET [FILE]
8
+ #
9
+ # This command helps exporting data in a SQL database to common transfer
10
+ # formats.
11
+ #
12
+ class Export < Command
13
+ include Bulk::Commons
14
+ Command::build_me(self, __FILE__)
15
+
16
+ # Output file to use
17
+ attr_accessor :output_file
18
+
19
+ # Contribute to options
20
+ def add_options(opt)
21
+ # Main output options
22
+ opt.separator "\nOutput options:"
23
+ opt.on("--output=FILE", "-o", "Flush output in FILE (stdout by default)") do |value|
24
+ self.output_file = value
25
+ end
26
+
27
+ opt.separator "\nRelational options:"
28
+ add_select_options(opt)
29
+
30
+ opt.separator "\nRecognized format options:"
31
+ add_output_format_options(opt)
32
+ add_typesafe_options(opt)
33
+
34
+ # CSV output options
35
+ opt.separator "\nCSV options:"
36
+ add_csv_output_options(opt)
37
+
38
+ # CSV output options
39
+ opt.separator "\nTEXT options:"
40
+ add_text_output_options(opt)
41
+
42
+ # JSON output options
43
+ opt.separator "\nJSON options:"
44
+ add_json_output_options(opt)
45
+ end
46
+
47
+ # Normalizes the pending arguments
48
+ def normalize_pending_arguments(arguments)
49
+ case arguments.size
50
+ when 1
51
+ self.dataset = valid_argument_list!(arguments, String)
52
+ when 2
53
+ raise OptionParser::AmbiguousArgument, '--output-file=#{self.output_file}' if self.output_file
54
+ self.dataset, self.output_file = valid_argument_list!(arguments, String, String)
55
+ else
56
+ bad_argument_list!(arguments)
57
+ end
58
+ unless /select|SELECT/ =~ self.dataset
59
+ self.dataset = self.dataset.to_sym
60
+ end
61
+ end
62
+
63
+ # Yields the block with the IO object to use for output
64
+ def with_io(&block)
65
+ if self.output_file
66
+ require 'fileutils'
67
+ FileUtils.mkdir_p(File.dirname(self.output_file))
68
+ File.open(self.output_file, "w", &block)
69
+ else
70
+ block.call(environment.output_buffer)
71
+ end
72
+ end
73
+
74
+ # Executes the command
75
+ def execute_command
76
+ with_current_connection do |connection|
77
+ # Prepare the dataset
78
+ ds = connection.dataset(self.dataset)
79
+ if self.select
80
+ ds = ds.select(*self.select)
81
+ elsif self.allbut
82
+ ds = ds.allbut(*self.allbut)
83
+ end
84
+
85
+ # Export it
86
+ with_io{|io|
87
+ method = "to_#{self.format}".to_sym
88
+ io = environment.output_buffer
89
+ options = io_options[self.format]
90
+ options[:type_system] = self.type_system if self.type_system
91
+ ds.send(method, io, options)
92
+ }
93
+ end
94
+ end
95
+
96
+ end # class Export
97
+ end # module Bulk
98
+ end # class Command
99
+ end # module DbAgile
@@ -0,0 +1,147 @@
1
+ module DbAgile
2
+ class Command
3
+ module Bulk
4
+ #
5
+ # Import a table from (csv, json, yaml, ruby)
6
+ #
7
+ # Usage: dba #{command_name} [OPTIONS] TABLE [FILE]
8
+ #
9
+ class Import < Command
10
+ include Bulk::Commons
11
+ include ::DbAgile::Tools::Tuple
12
+ Command::build_me(self, __FILE__)
13
+
14
+ # Input file to use
15
+ attr_accessor :input_file
16
+
17
+ # Drop table?
18
+ attr_accessor :drop_table
19
+
20
+ # Create table?
21
+ attr_accessor :create_table
22
+
23
+ # Truncate table?
24
+ attr_accessor :truncate_table
25
+
26
+ # Contribute to options
27
+ def add_options(opt)
28
+ # Main output options
29
+ opt.separator "\nInput options:"
30
+ opt.on("--input=FILE", "-i", "Read input from FILE (stdin by default)") do |value|
31
+ self.input_file = value
32
+ end
33
+
34
+ opt.separator "\nSQL options:"
35
+ opt.on("--create-table", "-c", "Create table before inserting values") do |value|
36
+ self.drop_table = true
37
+ self.create_table = true
38
+ self.truncate_table = false
39
+ end
40
+ opt.on("--drop-table", "-d", "Drop table before inserting values") do |value|
41
+ self.drop_table = true
42
+ self.create_table = true
43
+ self.truncate_table = false
44
+ end
45
+ opt.on("--truncate", "-t", "Truncate table before inserting values") do |value|
46
+ self.truncate_table = true
47
+ end
48
+ opt.on('--trace-sql', "Trace SQL statements on STDOUT (but executes them)") do |value|
49
+ self.conn_options[:trace_sql] = true
50
+ end
51
+ opt.on('--dry-run', "Trace SQL statements on STDOUT only, do nothing on the database") do |value|
52
+ self.conn_options[:trace_sql] = true
53
+ self.conn_options[:trace_only] = true
54
+ end
55
+
56
+ opt.separator "\nRecognized format options:"
57
+ add_input_format_options(opt)
58
+ add_typesafe_options(opt)
59
+
60
+ # CSV output options
61
+ opt.separator "\nCSV options:"
62
+ add_csv_input_options(opt)
63
+ end
64
+
65
+ # Normalizes the pending arguments
66
+ def normalize_pending_arguments(arguments)
67
+ case arguments.size
68
+ when 1
69
+ self.dataset = valid_argument_list!(arguments, Symbol)
70
+ when 2
71
+ raise OptionParser::AmbiguousArgument, '--input-file=#{self.input_file}' if self.input_file
72
+ self.dataset, self.input_file = valid_argument_list!(arguments, Symbol, String)
73
+ else
74
+ bad_argument_list!(arguments)
75
+ end
76
+ end
77
+
78
+ # Yields the block with the IO object to use for input
79
+ def with_io(&block)
80
+ if self.input_file
81
+ File.open(self.input_file, "r", &block)
82
+ else
83
+ block.call(environment.input_buffer)
84
+ end
85
+ end
86
+
87
+ # Yields the block with each emitted tuple
88
+ def with_emitter(&block)
89
+ with_io{|io|
90
+ options = io_options[self.format]
91
+ options[:type_system] = self.type_system if self.type_system
92
+ options[:input_file] = self.input_file
93
+ case self.format
94
+ when :csv
95
+ DbAgile::IO::CSV::from_csv(io, options, &block)
96
+ when :json
97
+ DbAgile::IO::JSON::from_json(io, options, &block)
98
+ when :yaml
99
+ DbAgile::IO::YAML::from_yaml(io, options, &block)
100
+ when :ruby
101
+ DbAgile::IO::Ruby::from_ruby(io, options, &block)
102
+ end
103
+ }
104
+ end
105
+
106
+ # Executes the command
107
+ def execute_command
108
+ with_current_connection(conn_options) do |connection|
109
+
110
+ # Make the job now
111
+ connection.transaction do |t|
112
+ first = true
113
+ with_emitter do |tuple|
114
+ make_the_job(t, tuple, first)
115
+ first = false
116
+ end
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ # Makes the insert job
123
+ def make_the_job(t, tuple, first = true)
124
+ handle_schema_modification(t, tuple) if first
125
+ t.insert(self.dataset, tuple)
126
+ end
127
+
128
+ # Handles the schema modifications
129
+ def handle_schema_modification(t, tuple)
130
+ # Handle table creation/deletion/truncation
131
+ if drop_table
132
+ t.drop_table(self.dataset) if t.has_table?(self.dataset)
133
+ end
134
+ if create_table
135
+ heading = tuple_heading(tuple)
136
+ heading = check_tuple_heading(heading, environment)
137
+ t.create_table(self.dataset, heading)
138
+ end
139
+ if truncate_table
140
+ t.delete(self.dataset, {})
141
+ end
142
+ end
143
+
144
+ end # class Import
145
+ end # module Bulk
146
+ end # class Command
147
+ end # module DbAgile
@@ -0,0 +1,3 @@
1
+ require 'dbagile/command/bulk/commons'
2
+ require 'dbagile/command/bulk/import'
3
+ require 'dbagile/command/bulk/export'