dddbl 0.0.1.alpha

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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ *~
4
+ *#
5
+ .bundle
6
+ Gemfile.lock
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2011, André Gawron
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ - Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ - Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ - The names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
24
+ OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.rdoc ADDED
@@ -0,0 +1,188 @@
1
+ = DDDBL - Definition Driven Database Layer
2
+
3
+ == What?
4
+
5
+ DDDBL is a library to simplify the use of (different) databases and splits up
6
+ application's and database's (e.g: SQL queries) code through an easy
7
+ and unified API. The SQL is defined in files outside of the application's source
8
+ to easiliy port the SQL to diffrent applications - or even programming languages.
9
+ Refering to the written queries using an alias makes it even more clearer and
10
+ better to understand for newcomers, who then don't have to waste time figuring out
11
+ what the query does.
12
+
13
+ == Why?
14
+
15
+ Many applications interacting with databases have the sql code directly written
16
+ in the its source. Reading, reviewing and understanding that
17
+ unfimiliar code can be hard, even more for non sql-pros. Most of the time -
18
+ to optimize the queries and the database performance in general - DBAs are hired
19
+ who are probably not familiar with the programming language used. So they have
20
+ to dig into the code and try to optimize it without breaking anything.
21
+
22
+ == Supported databases
23
+
24
+ Common RDMS like MySQL, PostgreSQL and SQLite are supported. The DDDBL uses another
25
+ gem called RDBI which simplifies the handling of several databases. For a full
26
+ list please of supported drivers please check the RDBI's github page
27
+ (https://github.com/RDBI/).
28
+
29
+ == It's a port, isn't it?
30
+
31
+ Yes. The DDDBL was orginally written in PHP and is a creation of Torsten Zühlsdorff.
32
+ For more information on the PHP version, go to http://www.dddbl.de (German only).
33
+ The ruby version will also be featured there in the near future.
34
+
35
+ === Any differences?
36
+
37
+ Yes. As of writing, the ruby port does not include every functionality the
38
+ PHP version offers. For example:
39
+
40
+ * not as much freedom regarding manipulating query-parameter pre-execution besides
41
+ casting the binded parameters to any value extendable through TypeLib
42
+ * caching of prepared statements
43
+
44
+ == Dependecies
45
+
46
+ The database handling and querying is handled by the RDBI library. For more
47
+ information please see their README (https://github.com/RDBI/rdbi/blob/master/README.txt)
48
+ or visit the project's page on https://github.com/RDBI/ .
49
+
50
+ == Getting started
51
+
52
+ === Database definitions
53
+
54
+ Every database the DDDBL should connect to has to be defined in a configuration
55
+ file using the ini-format. Example:
56
+
57
+ [TEST-DB]
58
+ HOST = localhost
59
+ DBNAME = test
60
+ TYPE = PostgreSQL
61
+ USER = root
62
+ PASS =
63
+ DEFAULT = true
64
+
65
+ * [TEST-DB]: alias of the database connection. It's used if the DDDBL shall
66
+ execute the query to another database
67
+ * HOST: host of the database
68
+ * DBNAME: database to select
69
+ * TYPE: driver to use
70
+ * USER: user who will be used to connect to the database
71
+ * PASS: user's password
72
+ * DEFAULT: normally, the DDDBL needs to know which database shall be used
73
+ to execute the query. If the DEFAULT flag is set to true, this connection
74
+ will be used at first - no explit connection selection needed. DEFAULT is optional.
75
+
76
+ Now the file has to be added to the database pool:
77
+
78
+ DDDBL::Pool::DB << DDDBL::Config.parse_dbs('/path/to/db/definitions.def')
79
+
80
+ The database has to be added before any queries. Adding a file with database
81
+ definitions results in establishing a connection to every defined database.
82
+
83
+ ==== Selecting (another) database
84
+
85
+ If only one connection is used, the following is just "good-to-know".
86
+ To select (another) database but the default is done by calling
87
+
88
+ DDDBL::select_db('TEST-DB')
89
+
90
+ Now every query executed after #select_db will be using the database connection
91
+ defined through the alias 'TEST-DB'.
92
+
93
+ === Query definitions
94
+
95
+ The query definition file also uses the ini-format and has to be configurated
96
+ seperately from the application (that's what the DDDBL is all about, isn't it?)
97
+
98
+ As for now, the query definitions of the PHP and ruby versions are interchangable:
99
+
100
+ [QUERY-ALIAS]
101
+ QUERY = "SELECT * FROM table"
102
+ HANDLER = MULTI
103
+
104
+ [QUERY-MULTILINE]
105
+ QUERY = "SELECT *
106
+ FROM table
107
+ WHERE foo = ?"
108
+ HANDLER = MULTI
109
+
110
+ [CREATE-TABLE]
111
+ QUERY = "CREATE TABLE foobar ( id SERIAL, name VARCHAR(50) )"
112
+
113
+ * [QUERY-ALIAS]: as with the database definition, the alias is used to
114
+ refer to the query inside of the application.
115
+ * QUERY: the sql query. It can be enclosed by " but it's optional as long
116
+ as the query fits into one line. ? is used to define parameters which will
117
+ be binded later on. No ; needed.
118
+ * HANDLER: the handler is in charge of transforming the query's result set.
119
+ There's own section devoted to that topic. HANDLER is optional (since a
120
+ result set can be empty).
121
+
122
+ As the database definitions, the query definitions also have to be added to the pool:
123
+
124
+ DDDBL::Pool << DDDBL::Config.parse_queries('/path/to/query/definitions.sql')
125
+
126
+ ==== Querying
127
+
128
+ To execute a query which was be added to the pool is straight forward:
129
+
130
+ formated_result = DDDBL::get('QUERY-ALIAS')
131
+
132
+ # binds 'bar'
133
+ formated_result = DDDBL::get('QUERY-MULTILINE', 'bar')
134
+
135
+ # without a result set
136
+ DDDBL::get('CREATE-TABLE')
137
+
138
+ === Transactions
139
+
140
+ DDDBL also supports transaction. More information on the implementation details
141
+ has to be looked up in the RDBI::Database documentation
142
+
143
+ DDDBL::transaction do
144
+ DDDBL::get('CREATE-TABLE')
145
+
146
+ # will fail because QUERY-MULTILINE expects a parameter
147
+ DDDBL::get('QUERY-MULTILINE')
148
+ end
149
+
150
+ Since the QUERY-MULTLINE will fail, the whole transaction will be rolled back
151
+ and no table will be created.
152
+
153
+ === Creating your own result handler
154
+
155
+ As you may know or guess by now, RDBI supports transforming the query's result
156
+ set to any datastructure you want. It's as straight forward as adding a query
157
+ file to the pool, just extend the RDBI's RDBI::Result::Driver class and
158
+ implement at least #fetch. The name of the new result driver is then the name
159
+ which has to be used in the query's HANDLER configuration field.
160
+
161
+ It's also possible to pass a configuration to the result driver defined in the
162
+ query definition:
163
+
164
+ [QUERY-ALIAS]
165
+ QUERY = "SELECT bar FROM foo;"
166
+ HANDLER = MULTI INT::bar
167
+
168
+ MULTI, as in the other examples, is the name of the result driver. If there's
169
+ a whitespace following with more text, this additional text will be passed to
170
+ the result driver's constructor. The example definition will explitictly cast
171
+ every row's bar-column value to an Integer.
172
+
173
+ For more information on creating a result driver, please read the documentation
174
+ of RDBI::Result::Driver. If you want to overwrite a default result driver,
175
+ just override the class.
176
+
177
+ == Bughunting was successful!
178
+
179
+ Just report the bug through github's tracker: https://github.com/melkon/dddbl/issues
180
+
181
+ == I'd like to patch and / or help maintain DDDBL. How can I?
182
+
183
+ * Fork the project: http://github.com/melkon/dddbl
184
+ * Make your feature addition or bug fix.
185
+
186
+ == Copyright
187
+
188
+ Copyright (c) 2011 André Gawron. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/dddbl.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "dddbl/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "dddbl"
6
+ s.version = DDDBL::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["André Gawron"]
9
+ s.email = ["andre@ziemek.de"]
10
+ s.homepage = "https://github.com/melkon/dddbl"
11
+ s.summary = %q{A Definition Driven Database Layer}
12
+ s.description = %q{A Definition Driven Database Layer. First developed in php, see: http://www.dddbl.de}
13
+
14
+ s.rubyforge_project = "dddbl"
15
+
16
+ s.add_dependency "inifile", ">= 0.4.1"
17
+ s.add_dependency "rdbi"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.require_paths = ["lib"]
21
+ end
data/example/dbdef.def ADDED
@@ -0,0 +1,9 @@
1
+ [TEST-DB]
2
+ HOST = localhost
3
+ DBNAME = trackadev
4
+ TYPE = PostgreSQL
5
+ USER = trackadev
6
+ PASS =
7
+ BIND = true
8
+ DEFAULT = true
9
+
data/example/demo.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'rdbi'
2
+ require 'rdbi-driver-postgresql'
3
+
4
+ require 'inifile'
5
+ require 'dddbl'
6
+
7
+ class RDBI::Result::Driver::YAL < RDBI::Result::Driver
8
+ def initialize(result, *args)
9
+ super
10
+ RDBI::Util.optional_require('yaml')
11
+ end
12
+
13
+ def format_single_row(raw)
14
+ ::Hash[column_names.zip(raw)].to_yaml
15
+ end
16
+
17
+ def format_multiple_rows(raw_rows)
18
+ raw_rows.collect { |row| ::Hash[column_names.zip(row)] }.to_yaml
19
+ end
20
+
21
+ private
22
+ def column_names
23
+ @column_names ||= @result.schema.columns.map(&:name)
24
+ end
25
+ end
26
+
27
+
28
+ DDDBL::Pool::DB << DDDBL::Config.parse_dbs('dbdef.def')
29
+ DDDBL::Pool << DDDBL::Config.parse_queries('test.sql')
30
+
31
+ DDDBL::get('TEST-QUERY')
32
+
33
+ DDDBL::get('TEST-INSERT', 'andre')
34
+ DDDBL::get('TEST-INSERT', 'melkon')
35
+
36
+ before = DDDBL::get('TEST-SELECT') ; p before
37
+
38
+ begin
39
+ DDDBL::transaction do
40
+
41
+ DDDBL::get('TEST-UPDATE', 'thorny', 2)
42
+
43
+ # raises an exception
44
+ # rollback initiated
45
+ # throws an exception
46
+ DDDBL::get('TEST-INSERT')
47
+
48
+ end ; rescue => e ; end
49
+
50
+ after = DDDBL::get('TEST-SELECT') ; p after
51
+
52
+
53
+ if before.to_s == after.to_s
54
+ p "transaction rollbacked"
55
+ else
56
+ p "transaction commited"
57
+ end
58
+
59
+ DDDBL::get('TEST-DROP')
data/example/test.sql ADDED
@@ -0,0 +1,12 @@
1
+ [TEST-QUERY]
2
+ QUERY = "CREATE TABLE muff (id SERIAL, name VARCHAR(255))"
3
+
4
+ [TEST-INSERT]
5
+ QUERY = "INSERT INTO muff (name) VALUES(?)"
6
+
7
+ [TEST-SELECT]
8
+ QUERY = "SELECT * FROM muff"
9
+ HANDLER = YAML
10
+
11
+ [TEST-DROP]
12
+ QUERY = "DROP TABLE IF EXISTS muff"
data/lib/dddbl.rb ADDED
@@ -0,0 +1,152 @@
1
+ #
2
+ # DDDBL - Definition Driven Database Layer
3
+ # Copyright (c) 2011 André Gawron. See LICENSE and README for details.
4
+ #
5
+ # @example Executing Query
6
+ # result = DDDBL::get('QUERY-ALIAS', 'foo', 'bar')
7
+ #
8
+ # @example Simple Transaction
9
+ # DDDBL::transaction do
10
+ # DDDBL::get('QUERY-ALIAS', 'foo', 'bar')
11
+ # DDDBL::get('CREATE-TABLE')
12
+ # end
13
+ #
14
+ # @example Select another database
15
+ # DDDBL::select_db('DATABASE-ALIAS')
16
+ #
17
+ class DDDBL
18
+
19
+ #
20
+ # a query can be associated with a specific
21
+ # database driver but if none is given, it will
22
+ # be safed in GLOBAL_POOL so every database connection
23
+ # can execute the defined query.
24
+ #
25
+ GLOBAL_POOL = :default
26
+
27
+ class << self
28
+
29
+ #
30
+ # selects an database connection which will then
31
+ # be used to execute queries. if the connection
32
+ # is not yet established, it will be after calling
33
+ # this method.
34
+ #
35
+ # @param [String] database_name databse alias which was defined in the config file
36
+ #
37
+ def select_db(database_name)
38
+ if @dbh == nil || @database != database_name
39
+ @dbh = RDBI::pool(database_name).get_dbh
40
+ end
41
+ end
42
+
43
+ #
44
+ # executes a defined alias and returns its result set which is
45
+ # transformed by an optionally defined result hanlder before.
46
+ #
47
+ # #get uses the current database connection set by #select_db
48
+ # if none was explicity selected but a default database was set
49
+ # using the configuration files, the default connection
50
+ # will be used.
51
+ #
52
+ # @param [String] query_alias querie's alias defined in the config file
53
+ # @param [Array] *binds the parameters which shall be binded to the query
54
+ #
55
+ # @return the result set transformed by the defined handler
56
+ #
57
+ def get(query_alias, *binds)
58
+ query = DDDBL::Pool[@dbh.driver, query_alias]
59
+ res = @dbh.execute(query[:query], *binds)
60
+ res.as(query[:handler]).fetch(:all) if !query[:handler].empty?
61
+ end
62
+
63
+ #
64
+ # delegates method calls to RDBI::Database
65
+ # DDDBL::transaction is currently implemented this way.
66
+ #
67
+ # @param [String] method valid RDBI::Database method
68
+ # @param [Array] *args RDBI::Database method's arguments
69
+ # @param [Proc] &block and finally the optional block
70
+ #
71
+ # @return everything that the RDBI::Datbase method calls will return
72
+ # @return [Boolean] false if no database connection is set
73
+ #
74
+ # @raise [ArgumentError] if RDBI::Database does not implement given method
75
+ #
76
+ def method_missing(method, *args, &block)
77
+ return false if !@dbh.is_a? RDBI::Database
78
+ raise ArgumentError, "RDBI::Database doesnt have #{method}" if !@dbh.respond_to?(method)
79
+
80
+ @dbh.send(method, *args, &block)
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ #
88
+ # DDDBL::Utils provides methods for validation of queries
89
+ # and database definitions.
90
+ #
91
+ # @see DDDBL::Pool for implementation examples
92
+ # @see DDDBL::Pool::DB for implementation examples
93
+ #
94
+ module DDDBL::Utils
95
+
96
+ #
97
+ # sets the mandatory fiels of a configuration
98
+ #
99
+ # @param [#each] fields which are mandatory, has to implement `#each`
100
+ #
101
+ # @raise [ArgumentError] if fields does not respond to #each
102
+ #
103
+ def mandatory(fields)
104
+ raise ArgumentError, 'parameter has to implement #each' if !fields.respond_to?('each')
105
+
106
+ @mandatory = fields
107
+ end
108
+
109
+ #
110
+ # sets the optional fiels of a configuration
111
+ #
112
+ # @param [#each] fields which are optional, has to implement #each
113
+ #
114
+ # @raise [ArgumentError] if fields does not respond to #each
115
+ #
116
+ def optional(fields)
117
+ raise ArgumentError, 'parameter has to implement #each' if !fields.respond_to?('each')
118
+
119
+ @optional = fields
120
+ end
121
+
122
+ #
123
+ # checks check for the defined mandatory and optional values
124
+ #
125
+ # @param [#each] check data structure which implements #each
126
+ #
127
+ # @return [Boolean] true if validation was successful
128
+ # @return [Boolean] false if not
129
+ #
130
+ # @raise [ArgumentError] if check does not respond to #has_key?
131
+ # @raise [ArgumentError] if check does not respond to #empty?
132
+ #
133
+ def valid?(check)
134
+ raise ArgumentError, 'parameter has to implement has_key?' if !check.respond_to?('has_key?')
135
+ raise ArgumentError, 'parameter has to implement empty?' if !check.respond_to?('empty?')
136
+
137
+ @mandatory.each do |key|
138
+ return false if !check.has_key?(key) || check[key].empty?
139
+ end
140
+
141
+ @optional.each do |key|
142
+ return false if !check.has_key?(key)
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ require 'dddbl/config'
149
+ require 'dddbl/pool'
150
+
151
+ # result handler
152
+ require 'dddbl/results'
@@ -0,0 +1,119 @@
1
+ #
2
+ # DDDBL - Definition Driven Database Layer
3
+ # Copyright (c) 2011 André Gawron. See LICENSE and README for details.
4
+ #
5
+ # DDDBL::Config parses the configuration files for queries and databases.
6
+ #
7
+ # Feel free to implement another parser (for example YAML-based files)
8
+ # and overwrite or extend DDDBL::Config. DDDBL::Config::Defaults
9
+ # will give you reasonable default values.
10
+ #
11
+ # @example Parse database definitions
12
+ # db_defintions = DDDBL::Config.parse_dbs('/path/to/file')
13
+ #
14
+ # @example Parse query definitions
15
+ # query_definitions = DDDBL::Config.parse_queries('/path/to/file')
16
+ #
17
+ module DDDBL::Config
18
+
19
+ class << self
20
+
21
+ #
22
+ # Offers methods to get default values for a database
23
+ # and query configuration.
24
+ #
25
+ module DDDBL::Config::Defaults
26
+
27
+ #
28
+ # returns the default values for a query configuration
29
+ #
30
+ # @param [String] query_alias the query's alias
31
+ #
32
+ # @return [Hash] the default values for a query configuration
33
+ # @option [String] :alias will contain the query_alias
34
+ # @option [String, Symbol] :type will contain DDDBL::GLOBAL_POOL
35
+ # @option [String] :handler will contain an empty string
36
+ #
37
+ def default_query(query_alias)
38
+ {
39
+ :alias => query_alias,
40
+ :type => DDDBL::GLOBAL_POOL,
41
+ :handler => ''
42
+ }
43
+ end
44
+
45
+ #
46
+ # returns the default values for a database configuration
47
+ #
48
+ # @param [String] db_alias the database's alias
49
+ #
50
+ # @return [Hash] the default values for a database configuration
51
+ # @option [String] :pool_name will contain the db_alias
52
+ # @option [Boolean] :default will contain false
53
+ # @option [String] :pass will contain the user's password
54
+ #
55
+ def default_db(db_alias)
56
+ {
57
+ :pool_name => db_alias,
58
+ :default => false,
59
+ :pass => ''
60
+ }
61
+ end
62
+
63
+ end
64
+
65
+ include DDDBL::Config::Defaults
66
+
67
+ end
68
+
69
+ #
70
+ # parses the queries from given file
71
+ #
72
+ # @param [File] file containing query definitions in IniFile-format
73
+ #
74
+ # @return [Hash<Hash>] parsed queries
75
+ #
76
+ # @raise [ArgumentError] if file does not exist
77
+ #
78
+ # @see [IniFile] for more information on the syntax
79
+ #
80
+ def self.parse_queries(file)
81
+ raise ArgumentError, "#{file} does not exist" if !File.exists?(file)
82
+
83
+ queries = {}
84
+
85
+ IniFile.load(file).each do |query_alias, query_param, query_value|
86
+ queries[query_alias] ||= default_query(query_alias)
87
+ queries[query_alias][query_param.downcase.to_sym] = query_value
88
+ end
89
+
90
+ queries
91
+
92
+ end
93
+
94
+ #
95
+ # parses the databases from given file
96
+ #
97
+ # @param [File] file containing database definitions in IniFile-format
98
+ #
99
+ # @return [Hash<Hash>] parsed databases
100
+ #
101
+ # @raise [ArgumentError] if file does not exist
102
+ #
103
+ # @see [IniFile] for more information on the syntax
104
+ #
105
+ def self.parse_dbs(file)
106
+ raise ArgumentError, "#{file} does not exist" if !File.exists?(file)
107
+
108
+ dbs = {}
109
+
110
+ IniFile.load(file).each do |db_alias, db_param, db_value|
111
+ dbs[db_alias] ||= default_db(db_alias)
112
+ dbs[db_alias][db_param.downcase.to_sym] = db_value
113
+ end
114
+
115
+ dbs
116
+
117
+ end
118
+
119
+ end
data/lib/dddbl/pool.rb ADDED
@@ -0,0 +1,108 @@
1
+ #
2
+ # DDDBL - Definition Driven Database Layer
3
+ # Copyright (c) 2011 André Gawron. See LICENSE and README for details.
4
+ #
5
+ # DDDBL::Pool contains the parsed queries
6
+ #
7
+ class DDDBL::Pool
8
+
9
+ class << self
10
+ include DDDBL::Utils
11
+ end
12
+
13
+ mandatory [:alias, :query, :type]
14
+ optional [:handler]
15
+
16
+ #
17
+ # returns a stored query for given database driver
18
+ # if none is found, the method looks in the global "namespace"
19
+ # if there is also no query stored, it raises an exception.
20
+ #
21
+ # @param [String] dbtype database's driver name (e.g. MySQL or PostgreSQL)
22
+ # @param [String] query_alias the query's alias
23
+ #
24
+ # @return [Hash] the query configuration
25
+ #
26
+ # @raise [StandardError] if no query is stored under given alias and driver
27
+ #
28
+ # @see [DDDBL::Pool::[]=] for hash keys
29
+ # @see [DDDBL::GLOBAL_POOL] for global "namespace"
30
+ #
31
+ def self.[](dbtype, query_alias)
32
+ if @pool.has_key?(dbtype) && @pool[dbtype].has_key?(query_alias)
33
+ @pool[dbtype][query_alias]
34
+ elsif @pool.has_key?(DDDBL::GLOBAL_POOL) && @pool[DDDBL::GLOBAL_POOL].has_key?(query_alias)
35
+ @pool[DDDBL::GLOBAL_POOL][query_alias]
36
+ else
37
+ raise StandardError, "#{query_alias} not a saved query alias"
38
+ end
39
+ end
40
+
41
+ #
42
+ # sets a query configuration for given database pool
43
+ # optional keys have to be set but can be empty.
44
+ #
45
+ # @param [String] dbtype database's driver name (e.g. MySQL or PostgreSQL)
46
+ # @param [Hash] query_config a valid query configuration
47
+ #
48
+ # @raise [StandardError] if the query configuration is not valid
49
+ #
50
+ # @see #mandatory for mandatory query configration keys
51
+ # @see #optional for optional query configuration keys
52
+ #
53
+ def self.[]=(dbtype, query_config)
54
+ raise StandardError, 'query is not properly configured' if !valid?(query_config)
55
+
56
+ @pool ||= Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
57
+ @pool[dbtype][query_config[:alias]] = query_config
58
+ end
59
+
60
+ #
61
+ # shortcut for an array (or hash) of query configurations
62
+ # adds the whole query_configs to their corresponding pools.
63
+ #
64
+ # @param [#each] query_configs a list of query_configs, has to respond to #each(key, query_config)
65
+ #
66
+ def self.<<(query_configs)
67
+ query_configs.each do |key, query_config|
68
+ DDDBL::Pool[query_config[:type]] = query_config
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ #
75
+ # DDDBL - Definition Driven Database Layer
76
+ # Copyright (c) 2011 André Gawron. See LICENSE and README for details.
77
+ #
78
+ # DDDBL::Pool::DB contains the parsed database definitions
79
+ #
80
+ class DDDBL::Pool::DB
81
+
82
+ class << self
83
+ include DDDBL::Utils
84
+ end
85
+
86
+ mandatory [:type, :pool_name, :host, :dbname, :user]
87
+ optional [:default, :pass]
88
+
89
+ #
90
+ # adds the whole db_configs to the pool,
91
+ # establishs a connection to each of them,
92
+ # and selects the default database connection
93
+ # if no connection is already set.
94
+ #
95
+ # @param [#each] query_configs a list of query_configs, has to respond to #each(key, query_config)
96
+ #
97
+ # @raise [StandardError] if the configration file is not valid
98
+ #
99
+ def self.<<(db_configs)
100
+ db_configs.each do |key, db_config|
101
+ raise StandardError, 'db_config is not valid' if !valid?(db_config)
102
+
103
+ RDBI::connect_cached(db_config[:type], db_config);
104
+ DDDBL::select_db(db_config[:pool_name]) if db_config[:default] && !DDDBL::connected?
105
+ end
106
+ end
107
+
108
+ end
@@ -0,0 +1,5 @@
1
+ # the php-library makes use of MULTI as result handler
2
+ # RDBI provides with Struct the same functionality
3
+ # for portability reasons of the query config files
4
+ # a MULTI handler is introduced which is an alias for Struct
5
+ class RDBI::Result::Driver::MULTI < RDBI::Result::Driver::Struct ; end
@@ -0,0 +1,3 @@
1
+ class DDDBL
2
+ VERSION = "0.0.1.alpha"
3
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dddbl
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 6
5
+ version: 0.0.1.alpha
6
+ platform: ruby
7
+ authors:
8
+ - "Andr\xC3\xA9 Gawron"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-08-31 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: inifile
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.1
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rdbi
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ description: "A Definition Driven Database Layer. First developed in php, see: http://www.dddbl.de"
38
+ email:
39
+ - andre@ziemek.de
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - LICENSE
49
+ - README.rdoc
50
+ - Rakefile
51
+ - dddbl.gemspec
52
+ - example/dbdef.def
53
+ - example/demo.rb
54
+ - example/test.sql
55
+ - lib/dddbl.rb
56
+ - lib/dddbl/config.rb
57
+ - lib/dddbl/pool.rb
58
+ - lib/dddbl/results.rb
59
+ - lib/dddbl/version.rb
60
+ homepage: https://github.com/melkon/dddbl
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">"
78
+ - !ruby/object:Gem::Version
79
+ version: 1.3.1
80
+ requirements: []
81
+
82
+ rubyforge_project: dddbl
83
+ rubygems_version: 1.8.5
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: A Definition Driven Database Layer
87
+ test_files: []
88
+