ramen 0.4.0

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 (40) hide show
  1. data/doc/doc_resources/MetaData_Class_Diagram.gif +0 -0
  2. data/doc/doc_resources/MetaData_Class_Diagram.png +0 -0
  3. data/doc/doc_resources/Thumbs.db +0 -0
  4. data/lib/ramen/core.rb +75 -0
  5. data/lib/ramen/default_logger.rb +29 -0
  6. data/lib/ramen/engine/engine.rb +34 -0
  7. data/lib/ramen/engine/mysql.rb +225 -0
  8. data/lib/ramen/engine/sql2005.rb +377 -0
  9. data/lib/ramen/home.rb +162 -0
  10. data/lib/ramen/metadata/column.rb +38 -0
  11. data/lib/ramen/metadata/database.rb +137 -0
  12. data/lib/ramen/metadata/foreign_key.rb +71 -0
  13. data/lib/ramen/metadata/foreign_key_column.rb +51 -0
  14. data/lib/ramen/metadata/index.rb +71 -0
  15. data/lib/ramen/metadata/index_column.rb +49 -0
  16. data/lib/ramen/metadata/key_constraint.rb +56 -0
  17. data/lib/ramen/metadata/metadata.rb +10 -0
  18. data/lib/ramen/metadata/primary_key.rb +71 -0
  19. data/lib/ramen/metadata/primary_key_column.rb +49 -0
  20. data/lib/ramen/metadata/schema.rb +86 -0
  21. data/lib/ramen/metadata/table.rb +202 -0
  22. data/lib/ramen/ramen_error.rb +16 -0
  23. data/lib/ramen/ramen_hash.rb +143 -0
  24. data/lib/ramen/ramen_module.rb +52 -0
  25. data/lib/ramen/row_data_gateway.rb +89 -0
  26. data/lib/ramen/version.rb +16 -0
  27. data/lib/ramen.rb +62 -0
  28. data/readme.txt +159 -0
  29. data/test/config/config.yml +19 -0
  30. data/test/helper.rb +18 -0
  31. data/test/mysql_create_test_db.sql +47 -0
  32. data/test/sql2005_create_test_db.sql +45 -0
  33. data/test/test_bugs.rb +32 -0
  34. data/test/test_core.rb +63 -0
  35. data/test/test_default_logger.rb +38 -0
  36. data/test/test_home.rb +33 -0
  37. data/test/test_ramen.rb +274 -0
  38. data/test/test_ramen_hash.rb +78 -0
  39. data/test/test_ramen_module.rb +21 -0
  40. metadata +99 -0
@@ -0,0 +1,377 @@
1
+ #--
2
+ # Copyright (c) 2007 Gregory N. Houston
3
+ # See ramen.rb for license information.
4
+ #++
5
+
6
+ module Ramen
7
+ # Responsible for returning T-SQL statements for various Sql Server 2005 queries.
8
+ #
9
+ # Links: readme.txt[link:files/readme_txt.html]; source[link:rcov/lib-ramen-sql2005_rb.html]
10
+ #
11
+ module Sql2005
12
+ include Ramen::Engine
13
+
14
+ class Sql
15
+ # returns the query for all schemas and their meta-data.
16
+ #
17
+ # the query must include schema_name.
18
+ def Sql.schemas
19
+ <<SQL
20
+ select
21
+ sys.schemas.schema_id,
22
+ sys.schemas.name as schema_name
23
+ from sys.schemas
24
+ SQL
25
+ end
26
+
27
+ # returns the query for all tables and their meta-data.
28
+ #
29
+ # the query must include the table_schema and table_name.
30
+ def Sql.tables
31
+ <<SQL
32
+ select
33
+ sys.tables.schema_id,
34
+ sys.schemas.name as table_schema,
35
+ sys.tables.object_id as table_id,
36
+ sys.tables.name as table_name,
37
+ sys.tables.principal_id,
38
+ sys.tables.parent_object_id,
39
+ sys.tables.type as table_type,
40
+ sys.tables.type_desc,
41
+ sys.tables.create_date,
42
+ sys.tables.modify_date,
43
+ sys.tables.is_ms_shipped,
44
+ sys.tables.is_published,
45
+ sys.tables.is_schema_published,
46
+ sys.tables.lob_data_space_id,
47
+ sys.tables.filestream_data_space_id,
48
+ sys.tables.max_column_id_used,
49
+ sys.tables.lock_on_bulk_load,
50
+ sys.tables.uses_ansi_nulls,
51
+ sys.tables.is_replicated,
52
+ sys.tables.has_replication_filter,
53
+ sys.tables.is_merge_published,
54
+ sys.tables.is_sync_tran_subscribed,
55
+ sys.tables.has_unchecked_assembly_data,
56
+ sys.tables.text_in_row_limit,
57
+ sys.tables.large_value_types_out_of_row
58
+ from sys.tables
59
+ inner join sys.schemas on sys.tables.schema_id = sys.schemas.schema_id
60
+ SQL
61
+ end
62
+
63
+ # selects all tables, via a different query. used for testing only.
64
+ #
65
+ # returns table_schema (e.g. schema_name) and table_name for every table.
66
+ def Sql.list_tables
67
+ <<SQL
68
+ select
69
+ sys.schemas.name as table_schema,
70
+ sys.tables.name as table_name
71
+ from sys.tables
72
+ inner join sys.schemas on sys.tables.schema_id = sys.schemas.schema_id
73
+ SQL
74
+ end
75
+
76
+ # returns the query for all columns and their meta-data.
77
+ #
78
+ # the query must include the table_schema, table_name and column_name.
79
+ def Sql.columns
80
+ <<SQL
81
+ select
82
+ sys.schemas.schema_id as schema_id,
83
+ sys.schemas.name as table_schema,
84
+ sys.columns.object_id as table_id,
85
+ sys.tables.name as table_name,
86
+ sys.columns.name as column_name,
87
+ sys.columns.column_id,
88
+ sys_type.name as system_type_name,
89
+ user_type.name as user_type_name,
90
+ sys.columns.max_length,
91
+ sys.columns.precision,
92
+ sys.columns.scale,
93
+ sys.columns.collation_name,
94
+ sys.columns.is_nullable,
95
+ sys.columns.is_ansi_padded,
96
+ sys.columns.is_rowguidcol,
97
+ sys.columns.is_identity,
98
+ sys.columns.is_computed,
99
+ sys.columns.is_filestream,
100
+ sys.columns.is_replicated,
101
+ sys.columns.is_non_sql_subscribed,
102
+ sys.columns.is_merge_published,
103
+ sys.columns.is_dts_replicated,
104
+ sys.columns.is_xml_document,
105
+ sys.columns.xml_collection_id,
106
+ sys.columns.default_object_id,
107
+ sys.columns.rule_object_id
108
+ from sys.columns
109
+ inner join sys.tables on
110
+ sys.columns.object_id = sys.tables.object_id
111
+ inner join sys.schemas on
112
+ sys.tables.schema_id = sys.schemas.schema_id
113
+ inner join sys.types sys_type on
114
+ sys.columns.system_type_id = sys_type.user_type_id
115
+ inner join sys.types user_type on
116
+ sys.columns.user_type_id = user_type.user_type_id
117
+ SQL
118
+ end
119
+
120
+ # returns the query for all foreign keys and their meta-data.
121
+ #
122
+ # the query must include the table_schema, table_name and foreign_key_name.
123
+ def Sql.foreign_keys
124
+ <<SQL
125
+ select
126
+ sys.foreign_keys.schema_id,
127
+ sys.schemas.name as table_schema,
128
+ sys.foreign_keys.parent_object_id as table_id,
129
+ sys.tables.name as table_name,
130
+ sys.foreign_keys.object_id as foreign_key_id,
131
+ sys.foreign_keys.name as foreign_key_name,
132
+ sys.foreign_keys.principal_id,
133
+ sys.foreign_keys.type as key_type,
134
+ sys.foreign_keys.type_desc,
135
+ sys.foreign_keys.create_date,
136
+ sys.foreign_keys.modify_date,
137
+ sys.foreign_keys.is_ms_shipped,
138
+ sys.foreign_keys.is_published,
139
+ sys.foreign_keys.is_schema_published,
140
+ sys.foreign_keys.referenced_object_id,
141
+ sys.foreign_keys.key_index_id,
142
+ sys.foreign_keys.is_disabled,
143
+ sys.foreign_keys.is_not_for_replication,
144
+ sys.foreign_keys.is_not_trusted,
145
+ sys.foreign_keys.delete_referential_action,
146
+ sys.foreign_keys.delete_referential_action_desc,
147
+ sys.foreign_keys.update_referential_action,
148
+ sys.foreign_keys.update_referential_action_desc,
149
+ sys.foreign_keys.is_system_named
150
+ from sys.foreign_keys
151
+ inner join sys.tables on
152
+ sys.foreign_keys.parent_object_id = sys.tables.object_id
153
+ inner join sys.schemas on
154
+ sys.tables.schema_id = sys.schemas.schema_id
155
+ SQL
156
+ end
157
+
158
+ # returns the query for all foreign key columns and their meta-data.
159
+ #
160
+ # the query must include foreign_key_name, table_schema, table_name,
161
+ # column_name, referenced_table_schema, referenced_table_name,
162
+ # referenced_column_name.
163
+ def Sql.foreign_key_columns
164
+ <<SQL
165
+ select
166
+ sys.schemas.schema_id,
167
+ sys.schemas.name as table_schema,
168
+ sys.foreign_key_columns.parent_object_id as table_id,
169
+ sys.tables.name as table_name,
170
+ sys.foreign_key_columns.constraint_object_id as foreign_key_id,
171
+ sys.foreign_keys.name as foreign_key_name,
172
+ parent_columns.name as column_name,
173
+ parent_column_id as column_id,
174
+ referenced_schema.name as referenced_table_schema,
175
+ referenced_table.name as referenced_table_name,
176
+ referenced_columns.name as referenced_column_name,
177
+ referenced_column_id,
178
+ referenced_columns.is_nullable
179
+ from sys.foreign_key_columns
180
+ inner join sys.tables on
181
+ sys.foreign_key_columns.parent_object_id = sys.tables.object_id
182
+ inner join sys.schemas on
183
+ sys.tables.schema_id = sys.schemas.schema_id
184
+ inner join sys.foreign_keys on
185
+ sys.foreign_key_columns.constraint_object_id = sys.foreign_keys.object_id
186
+ inner join sys.columns parent_columns on
187
+ sys.foreign_key_columns.parent_object_id = parent_columns.object_id
188
+ and sys.foreign_key_columns.parent_column_id = parent_columns.column_id
189
+ inner join sys.tables referenced_table on
190
+ sys.foreign_key_columns.referenced_object_id = referenced_table.object_id
191
+ inner join sys.columns referenced_columns on
192
+ referenced_table.object_id = referenced_columns.object_id
193
+ and referenced_column_id = referenced_columns.column_id
194
+ inner join sys.schemas referenced_schema on
195
+ referenced_table.schema_id = referenced_schema.schema_id
196
+ SQL
197
+ end
198
+
199
+ # returns the query for all primary keys and their meta-data.
200
+ #
201
+ # the query must include the table_schema, table_name and
202
+ # primary_key_name.
203
+ def Sql.primary_keys
204
+ <<SQL
205
+ select
206
+ sys.schemas.schema_id,
207
+ sys.schemas.name as table_schema,
208
+ sys.indexes.object_id as table_id,
209
+ sys.tables.name as table_name,
210
+ sys.indexes.index_id as primary_key_id,
211
+ sys.indexes.name as primary_key_name,
212
+ sys.indexes.type as index_type,
213
+ sys.indexes.type_desc,
214
+ sys.indexes.is_unique,
215
+ sys.indexes.data_space_id,
216
+ sys.indexes.ignore_dup_key,
217
+ sys.indexes.is_primary_key,
218
+ sys.indexes.is_unique_constraint,
219
+ sys.indexes.fill_factor,
220
+ sys.indexes.is_padded,
221
+ sys.indexes.is_disabled,
222
+ sys.indexes.is_hypothetical,
223
+ sys.indexes.allow_row_locks,
224
+ sys.indexes.allow_page_locks
225
+ from sys.indexes
226
+ inner join sys.tables on
227
+ sys.indexes.object_id = sys.tables.object_id
228
+ inner join sys.schemas on
229
+ sys.tables.schema_id = sys.schemas.schema_id
230
+ where sys.indexes.is_primary_key = 1
231
+ SQL
232
+ end
233
+
234
+ # returns the query for all primary key columns and their meta-data.
235
+ #
236
+ # the query must include the table_schema, table_name,
237
+ # primary_key_name, column_name and referenced_column_name.
238
+ def Sql.primary_key_columns
239
+ <<SQL
240
+ select
241
+ sys.schemas.schema_id,
242
+ sys.schemas.name as table_schema,
243
+ sys.index_columns.object_id as table_id,
244
+ sys.tables.name as table_name,
245
+ sys.index_columns.index_id as primary_key_id,
246
+ sys.indexes.name as primary_key_name,
247
+ sys.index_columns.column_id,
248
+ sys.columns.name as column_name,
249
+ sys.index_columns.index_column_id as primary_key_column_id,
250
+ sys.index_columns.key_ordinal,
251
+ sys.index_columns.partition_ordinal,
252
+ sys.index_columns.is_descending_key,
253
+ sys.index_columns.is_included_column
254
+ from sys.index_columns
255
+ inner join sys.tables
256
+ on sys.index_columns.object_id = sys.tables.object_id
257
+ inner join sys.schemas
258
+ on sys.tables.schema_id = sys.schemas.schema_id
259
+ inner join sys.indexes
260
+ on sys.index_columns.index_id = sys.indexes.index_id
261
+ and sys.indexes.object_id = sys.tables.object_id
262
+ inner join sys.columns
263
+ on sys.indexes.object_id = sys.columns.object_id
264
+ and sys.index_columns.column_id = sys.columns.column_id
265
+ where sys.indexes.is_primary_key = 1
266
+ SQL
267
+ end
268
+
269
+ # returns the query for all indexes (except primary keys) and their meta-data.
270
+ #
271
+ # the query must include the schema_id, table_id,
272
+ # index_id and index_name.
273
+ def Sql.indexes
274
+ <<SQL
275
+ select
276
+ sys.schemas.schema_id,
277
+ sys.schemas.name as table_schema,
278
+ sys.indexes.object_id as table_id,
279
+ sys.tables.name as table_name,
280
+ sys.indexes.index_id,
281
+ sys.indexes.name as index_name,
282
+ sys.indexes.type as index_type,
283
+ sys.indexes.type_desc,
284
+ sys.indexes.is_unique,
285
+ sys.indexes.data_space_id,
286
+ sys.indexes.ignore_dup_key,
287
+ sys.indexes.is_primary_key,
288
+ sys.indexes.is_unique_constraint,
289
+ sys.indexes.fill_factor,
290
+ sys.indexes.is_padded,
291
+ sys.indexes.is_disabled,
292
+ sys.indexes.is_hypothetical,
293
+ sys.indexes.allow_row_locks,
294
+ sys.indexes.allow_page_locks
295
+ from sys.indexes
296
+ inner join sys.tables on
297
+ sys.indexes.object_id = sys.tables.object_id
298
+ inner join sys.schemas on
299
+ sys.tables.schema_id = sys.schemas.schema_id
300
+ where sys.indexes.is_primary_key = 0
301
+ SQL
302
+ end
303
+
304
+ # returns the query for all index columns and their meta-data.
305
+ #
306
+ # the query must include the schema_id, table_id,
307
+ # index_id, column_name, column_id.
308
+ def Sql.index_columns
309
+ <<SQL
310
+ select
311
+ sys.schemas.schema_id,
312
+ sys.schemas.name as table_schema,
313
+ sys.index_columns.object_id as table_id,
314
+ sys.tables.name as table_name,
315
+ sys.index_columns.index_id,
316
+ sys.indexes.name as index_name,
317
+ sys.index_columns.column_id,
318
+ sys.columns.name as column_name,
319
+ sys.index_columns.index_column_id,
320
+ sys.index_columns.key_ordinal,
321
+ sys.index_columns.partition_ordinal,
322
+ sys.index_columns.is_descending_key,
323
+ sys.index_columns.is_included_column
324
+ from sys.index_columns
325
+ inner join sys.tables
326
+ on sys.index_columns.object_id = sys.tables.object_id
327
+ inner join sys.schemas
328
+ on sys.tables.schema_id = sys.schemas.schema_id
329
+ inner join sys.indexes
330
+ on sys.index_columns.index_id = sys.indexes.index_id
331
+ and sys.indexes.object_id = sys.tables.object_id
332
+ inner join sys.columns
333
+ on sys.indexes.object_id = sys.columns.object_id
334
+ and sys.index_columns.column_id = sys.columns.column_id
335
+ where sys.indexes.is_primary_key = 0
336
+ SQL
337
+ end
338
+
339
+ # returns the query for all key constraints and their meta-data.
340
+ #
341
+ # the query must include the schema_id, table_id,
342
+ # key_id, key_name, and index_id.
343
+ =begin
344
+ def Sql.key_constraints
345
+ <<SQL
346
+ select
347
+ sys.key_constraints.schema_id,
348
+ sys.schemas.name as table_schema,
349
+ sys.key_constraints.parent_object_id as table_id,
350
+ sys.tables.name as table_name,
351
+ sys.key_constraints.object_id as key_id,
352
+ sys.key_constraints.name as key_name,
353
+ sys.key_constraints.type as key_type,
354
+ sys.key_constraints.type_desc,
355
+ sys.key_constraints.create_date,
356
+ sys.key_constraints.modify_date,
357
+ sys.key_constraints.is_ms_shipped,
358
+ sys.key_constraints.is_published,
359
+ sys.key_constraints.is_schema_published,
360
+ sys.key_constraints.unique_index_id,
361
+ sys.key_constraints.unique_index_id as index_id, -- alias
362
+ sys.indexes.name as index_name,
363
+ sys.key_constraints.is_system_named
364
+ from sys.key_constraints
365
+ inner join sys.tables on
366
+ sys.key_constraints.parent_object_id = sys.tables.object_id
367
+ inner join sys.schemas on
368
+ sys.tables.schema_id = sys.schemas.schema_id
369
+ inner join sys.indexes on
370
+ sys.key_constraints.parent_object_id = sys.indexes.object_id
371
+ and sys.key_constraints.unique_index_id = sys.indexes.index_id
372
+ SQL
373
+ end
374
+ =end
375
+ end
376
+ end
377
+ end
data/lib/ramen/home.rb ADDED
@@ -0,0 +1,162 @@
1
+ #--
2
+ # Copyright (c) 2007 Gregory N. Houston
3
+ # See ramen.rb for license information.
4
+ #++
5
+
6
+ module Ramen
7
+
8
+ # Home - noun. Synonyms: Environment, Context
9
+ #
10
+ # Home contains the environmental stuff that
11
+ # is shared or used by many parts of Ramen.
12
+ #
13
+ # home.sql = module with details for database engine used. see Sql2005 for an example.
14
+ #
15
+ # home.log = logger
16
+ #
17
+ # Home also contains common database
18
+ # access functions. (in the future, these
19
+ # might move a a data access layer.)
20
+ #
21
+ # Links: readme.txt[link:files/readme_txt.html]; source[link:rcov/lib-ramen-home_rb.html]
22
+ #
23
+ class Home
24
+ attr_reader :log, :sql
25
+
26
+ # :section: External Methods
27
+ # The following methods are intended for use by Ramen's clients.
28
+
29
+ # Home.new( configuration ) #=> instance of Home
30
+ #
31
+ # database = Database.new( Home.new( :sql => Sql2005 ), DBI.connection(...) )
32
+ #
33
+ # Ramen.create is a short-cut for the statement above. e.g.
34
+ #
35
+ # database = Ramen.create( :connection => DBI.connect(...), :sql = Sql2005.new )
36
+ #
37
+ # Note that Home.new doesn't accepts a :connection, only Ramen#create. The
38
+ # connection is not stored, it is only used during the call to Ramen#create.
39
+ #
40
+ # The configuration hash can include the following options:
41
+ #
42
+ # :logger => a logger, see DefaultLogger for an example;
43
+ # default = DefaultLogger
44
+ #
45
+ # :sql => class which provides the sql statments;
46
+ # default = Sql2005
47
+ #
48
+ # An alternative way to specify the configuration is to override
49
+ # the methods which create the defaults: new_logger, new_sql. For example:
50
+ #
51
+ # module Ramen
52
+ # class Home
53
+ # def new_logger
54
+ # get_logger_from_configuration_file()
55
+ # end
56
+ # end
57
+ # end
58
+ #
59
+ def initialize( configuration = {} )
60
+ @log = configuration[:logger] || new_logger
61
+ @sql = configuration[:sql] || new_sql
62
+ end
63
+
64
+ # :section: Internal Helper Methods
65
+ # The following are helper methods for Ramen's internal use. They
66
+ # are not intended for clients of Ramen to use.
67
+
68
+ =begin
69
+ THE FOLLOWING IS NOT USED, BUT I'M KEEPING THIS CODE SINCE IT IS LIKELY TO
70
+ BE USED IN THE FUTURE.
71
+ def select_one( stmt, *args )
72
+ @log.debug "stmt=\"#{stmt}\", args=#{args.inspect}"
73
+ begin
74
+ @dbi.select_one( stmt, *args )
75
+ rescue
76
+ @log.error "--------ERROR------------"
77
+ @log.error "stmt=\"#{stmt}\", args=#{args.inspect}"
78
+ @log.error $!
79
+ raise
80
+ end
81
+ end
82
+ =end
83
+
84
+ # select( connection, sql_statement, args ) #=> rows, columns
85
+ #
86
+ # rows, columns = select( connection, 'select * from some_table' )
87
+ #
88
+ # helper methods to run a sql statement and return
89
+ # the resulting data along with the column names.
90
+ #
91
+ # this wraps dbi.execute with some logging, and other common steps.
92
+ def select( connection, stmt, *args )
93
+ @log.debug "stmt=\"#{stmt}\", args=#{args.inspect}"
94
+ begin
95
+ query = connection.execute( stmt, *args )
96
+ rows = query.fetch_all
97
+ cols = query.column_names
98
+ return rows, cols
99
+ ensure
100
+ query.finish unless query.nil?
101
+ end
102
+ end
103
+
104
+ # execute( connection, sql_statement, args ) { |row| ... }
105
+ #
106
+ # execute( connection, 'select * from some_table' ) do |row|
107
+ # puts row
108
+ # end
109
+ #
110
+ # helper methods to run a sql statement and call
111
+ # a block for each row
112
+ #
113
+ # this wraps dbi.execute with some logging, and other common steps.
114
+ def execute( connection, stmt, *args )
115
+ @log.debug "stmt=\"#{stmt}\", args=#{args.inspect}"
116
+ begin
117
+ query = connection.execute( stmt, *args )
118
+ query.fetch do |row|
119
+ yield row
120
+ end
121
+ rescue
122
+ @log.error "--------ERROR------------"
123
+ @log.error "stmt=\"#{stmt}\", args=#{args.inspect}"
124
+ @log.error $!
125
+ raise
126
+ ensure
127
+ query.finish unless query.nil?
128
+ end
129
+ end
130
+
131
+ # :section: Internal Factory Methods
132
+ # The following are methods for Ramen's internal use. They
133
+ # are not intended for clients of Ramen to call. Clients may
134
+ # redefine these methods to change their behavior.
135
+
136
+ # new_logger() #=> logger
137
+ #
138
+ # factory method, called by Home.new to get the default logger.
139
+ #
140
+ # returns an instance of DefaultLogger.
141
+ #
142
+ # To change the logger, either provide a logger (Log4Ruby will work)
143
+ # when calling Home.new( :logger=> log ), or redefine this method.
144
+ def new_logger
145
+ DefaultLogger.new
146
+ end
147
+
148
+ # new_sql #=> sql
149
+ #
150
+ # factory method, called by Home.new to get the default
151
+ # sql catalog.
152
+ #
153
+ # returns an instance of Sql2005 by default.
154
+ #
155
+ # To support different database engines, either provide a sql catalog
156
+ # when calling Home.new( :sql => sql_for_my_database ), or redefine this
157
+ # method.
158
+ def new_sql
159
+ Sql2005
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,38 @@
1
+ #--
2
+ # Copyright (c) 2007 Gregory N. Houston
3
+ # See ramen.rb for license information.
4
+ #++
5
+
6
+ module Ramen::Metadata
7
+ # Column contains meta-data about columns within a Table. The attributes are
8
+ # database engine specific. Only column_name and column_id are required by
9
+ # Ramen.
10
+ # See RowDataGateway for more information.
11
+ #
12
+ # See Database for a description of how Column fits in the Ramen collection
13
+ # hierarchy.
14
+ #
15
+ # Links: readme.txt[link:files/readme_txt.html]; source[link:rcov/lib-ramen-column_rb.html]
16
+ #
17
+ class Column < Ramen::RowDataGateway
18
+ # :section: External Methods
19
+ # The following methods are intended for use by Ramen's clients.
20
+
21
+ # Comparison, returns -1,0,+1, compares column_name
22
+ def <=> other
23
+ Ramen::RowDataGateway.compare( column_name, other )
24
+ end
25
+
26
+ # :section: Internal Methods
27
+ # The following methods are for Ramen's internal use. They
28
+ # are not intended for clients of Ramen to use.
29
+
30
+ # add_to( database )
31
+ #
32
+ # Add self to the given database. (Choosing Message; Double Dispatch pattern)
33
+ # (Kent Beck. Smalltalk Best Practices Patterns. Perntice Hall PTR, Upper Saddle River, NJ 1997)
34
+ def add_to( database )
35
+ database.schema[ self.table_schema ].table[ self.table_name ].add_column( self )
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,137 @@
1
+ #--
2
+ # Copyright (c) 2007 Gregory N. Houston
3
+ # See ramen.rb for license information.
4
+ #++
5
+
6
+ module Ramen::Metadata
7
+ # Database is the top of a tree of collections and classes that
8
+ # contain the reflected information about the schema.
9
+ #
10
+ # Database is synonymous with Catalog on some database engines.
11
+ #
12
+ # link:doc_resources/MetaData_Class_Diagram.png
13
+ #
14
+ # Database contains many Schema objects, which are accessable through the
15
+ # schema attribute. Schema contains many Table objects, which are accessable
16
+ # through Schema#table. Table contains many Column, ForeignKey, Index and
17
+ # KeyConstraint objects. ForeignKey contains ForeignKeyColumn objects; which
18
+ # reference the appropriate Column. Index contains IndexColumn objects; which
19
+ # reference the appropriate Column. KeyConstraint objects refernece their
20
+ # Index.
21
+ #
22
+ # For more details see: http://ramen.rubyforge.org or readme.txt[link:files/readme_txt.html]
23
+ #
24
+ # usage:
25
+ # db = Ramen.create( configuration ) # a short-cut for Database.new
26
+ # schema = db.schema['HumanResources']
27
+ #
28
+ # Links: readme.txt[link:files/readme_txt.html]; source[link:rcov/lib-ramen-database_rb.html]
29
+ #
30
+ class Database
31
+ # :section: External Methods
32
+ # The following methods are intended for use by Ramen's clients.
33
+
34
+ # Database.new( connection, home ) #=> instance of Database
35
+ #
36
+ # db = Database.new( DBI.connect(...), Home.new( :sql => Sql2005.new ) )
37
+ #
38
+ # Creates a database and loads all the objects (Schema, Table, Column, etc).
39
+ # To get the best performance for typical usage, Database.new will load
40
+ # all objects. Loading all objects during Database.new
41
+ # makes the fewest queries to the database server.
42
+ #
43
+ # Ramen does not hold on to the connection. After this method returns, it
44
+ # is safe to close the connection or use it for other queries.
45
+ #
46
+ # see Home.new for configuration options.
47
+ #
48
+ # Ramen.create in an alternative method to calling Database.new
49
+ def initialize( connection, home )
50
+ @home = home
51
+ load_all_objects( connection )
52
+ end
53
+
54
+ # schema() #=> RamenHash reference
55
+ #
56
+ # This attribute provides access to a RamenHash of all Schema in the
57
+ # Database. The hash is indexed by schema_name and schema_id.
58
+ #
59
+ # usage:
60
+ # require 'lib/ramen'
61
+ # db = Ramen.create( configuration )
62
+ # db.schema['Sales'] #=> #<Schema schema_name='Sales', schema_id='1234567' ...>
63
+ # db.schema[1234567] #=> #<Schema schema_name='Sales', schema_id='1234567' ...>
64
+ #
65
+ def schema
66
+ @schemas
67
+ end
68
+
69
+ # inspect() #=> string
70
+ #
71
+ # Returns a nice and brief output of the database and it's schema. This
72
+ # was redefined since the default inspect would typically output many
73
+ # pages of details.
74
+ #
75
+ # Each schema is listed by id:name.
76
+ #
77
+ # usage:
78
+ # db = Ramen.create()
79
+ # db.inspect #=> "#<Ramen::Database:0x2da0668 schema=[1:dbo, 2:guest,..."
80
+ #
81
+ def inspect
82
+ children = []
83
+ @schemas.each_by_id do |id,schema|
84
+ children << (id.to_s+':'+schema.schema_name)
85
+ end
86
+ to_s[0..-2]+' schema=['+children.join(', ')+']>'
87
+ end
88
+
89
+ # :section: Internal Methods
90
+ # The following methods are for Ramen's internal use. They
91
+ # are not intended for clients of Ramen to use.
92
+
93
+ # add_schema( obj ) #=> obj
94
+ #
95
+ # Adds the given schema to this database. Throws a RamenError if the obj
96
+ # is not a Schema.
97
+ def add_schema( obj )
98
+ @schemas.add( obj )
99
+ end
100
+
101
+ # list_tables() #=> Array of Array containing table_name, table_id,
102
+ # schema_name, schema_id
103
+ #
104
+ # Intended for use by testing. This lists all tables in the database using
105
+ # a call which is different than the one used to load_all_objects.
106
+ def list_tables( connection )
107
+ result = Array.new
108
+ @home.execute( connection, @home.sql::Sql.list_tables ) do |row|
109
+ result << [row['table_schema'], row['table_name']]
110
+ end
111
+ result
112
+ end
113
+
114
+ private
115
+ def load_all_objects( connection )
116
+ @schemas = Ramen::RamenHash.new( Schema )
117
+ sql = @home.sql::Sql
118
+ engine = @home.sql
119
+ load( engine::Schema, sql.schemas, connection )
120
+ load( engine::Table, sql.tables, connection )
121
+ load( engine::Column, sql.columns, connection )
122
+ load( engine::ForeignKey, sql.foreign_keys, connection )
123
+ load( engine::ForeignKeyColumn, sql.foreign_key_columns, connection )
124
+ load( engine::Index, sql.indexes, connection )
125
+ load( engine::IndexColumn, sql.index_columns, connection )
126
+ load( engine::PrimaryKey, sql.primary_keys, connection )
127
+ load( engine::PrimaryKeyColumn, sql.primary_key_columns, connection )
128
+ #load( engine::KeyConstraint, sql.key_constraints, connection )
129
+ end
130
+
131
+ def load( clazz, sql, connection )
132
+ data, columns = @home.select( connection, sql )
133
+ clazz.add_attributes( columns )
134
+ data.each { |record| clazz.new(record, self).add_to(self) }
135
+ end
136
+ end
137
+ end