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,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'