fluent-query-sql 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ gem "hash-utils", ">= 0.18.0"
5
+ gem "abstract", ">= 1.0.0"
6
+ gem "fluent-query", ">= 0.9.0"
7
+
8
+ # Add dependencies to develop your gem here.
9
+ # Include everything needed to run rake, tests, features, etc.
10
+ group :development do
11
+ gem "bundler", "~> 1.0.13"
12
+ gem "jeweler", "~> 1.6.0"
13
+ end
14
+
15
+
16
+
17
+ # fluent-query-sql
18
+ # fluent-query-dbh
19
+ # fluent-query-mysql
20
+ # fluent-query-sqlite
21
+ # fluent-query-postgresql
22
+ # native-query
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ fluent-query (0.9.0)
6
+ abstract (>= 1.0.0)
7
+ hash-utils (>= 0.18.0)
8
+ hashie (>= 1.0.0)
9
+ git (1.2.5)
10
+ hash-utils (0.18.0)
11
+ hashie (1.0.0)
12
+ jeweler (1.6.3)
13
+ bundler (~> 1.0)
14
+ git (>= 1.2.5)
15
+ rake
16
+ rake (0.9.2)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ abstract (>= 1.0.0)
23
+ bundler (~> 1.0.13)
24
+ fluent-query (>= 0.9.0)
25
+ hash-utils (>= 0.18.0)
26
+ jeweler (~> 1.6.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 - 2011 Martin Kozák (martinkozak@martinkozak.net)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,33 @@
1
+ Fluent Query SQL Driver
2
+ =======================
3
+
4
+ **Fluent Query** is cool way how to write SQL queries and general way
5
+ how to convert series of method calls to string query in an universal
6
+ and system independent manner.
7
+
8
+ This is **SQL** DBI based driver for *Fluent Query*. It can be used with
9
+ [Fluent Query][4] or [Native Query][5] only, and some specific database
10
+ driver, not standalone.
11
+
12
+
13
+ Contributing
14
+ ------------
15
+
16
+ 1. Fork it.
17
+ 2. Create a branch (`git checkout -b 20101220-my-change`).
18
+ 3. Commit your changes (`git commit -am "Added something"`).
19
+ 4. Push to the branch (`git push origin 20101220-my-change`).
20
+ 5. Create an [Issue][2] with a link to your branch.
21
+ 6. Enjoy a refreshing Diet Coke and wait.
22
+
23
+ Copyright
24
+ ---------
25
+
26
+ Copyright © 2009-2011 [Martin Kozák][3]. See `LICENSE.txt` for
27
+ further details.
28
+
29
+ [2]: http://github.com/martinkozak/fluent-query-sql/issues
30
+ [3]: http://www.martinkozak.net/
31
+ [4]: http://github.com/martinkozak/fluent-query
32
+ [5]: http://github.com/martinkozak/native-query
33
+
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+ require 'jeweler'
16
+
17
+ Jeweler::Tasks.new do |gem|
18
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
+ gem.name = "fluent-query-sql"
20
+ gem.homepage = "http://github.com/martinkozak/fluent-query-sql"
21
+ gem.license = "MIT"
22
+ gem.summary = 'Generic SQL support for the Fluent Query. Fluent Query is cool way how to write SQL queries in Ruby. Contains base libraries used by specific SQL driver.'
23
+ gem.email = "martinkozak@martinkozak.net"
24
+ gem.authors = ["Martin Kozák"]
25
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
26
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
27
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.0
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{fluent-query-sql}
8
+ s.version = "0.9.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Martin Kozák}]
12
+ s.date = %q{2011-07-14}
13
+ s.email = %q{martinkozak@martinkozak.net}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE.txt",
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "fluent-query-sql.gemspec",
27
+ "lib/fluent-query/drivers/shared/tokens/sql.rb",
28
+ "lib/fluent-query/drivers/shared/tokens/sql/delete.rb",
29
+ "lib/fluent-query/drivers/shared/tokens/sql/from.rb",
30
+ "lib/fluent-query/drivers/shared/tokens/sql/groupby.rb",
31
+ "lib/fluent-query/drivers/shared/tokens/sql/having.rb",
32
+ "lib/fluent-query/drivers/shared/tokens/sql/insert.rb",
33
+ "lib/fluent-query/drivers/shared/tokens/sql/join.rb",
34
+ "lib/fluent-query/drivers/shared/tokens/sql/orderby.rb",
35
+ "lib/fluent-query/drivers/shared/tokens/sql/select.rb",
36
+ "lib/fluent-query/drivers/shared/tokens/sql/set.rb",
37
+ "lib/fluent-query/drivers/shared/tokens/sql/truncate.rb",
38
+ "lib/fluent-query/drivers/shared/tokens/sql/union.rb",
39
+ "lib/fluent-query/drivers/shared/tokens/sql/update.rb",
40
+ "lib/fluent-query/drivers/shared/tokens/sql/where.rb",
41
+ "lib/fluent-query/drivers/sql.rb",
42
+ "lib/fluent-query/queries/sql.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/martinkozak/fluent-query-sql}
45
+ s.licenses = [%q{MIT}]
46
+ s.require_paths = [%q{lib}]
47
+ s.rubygems_version = %q{1.8.5}
48
+ s.summary = %q{Generic SQL support for the Fluent Query. Fluent Query is cool way how to write SQL queries in Ruby. Contains base libraries used by specific SQL driver.}
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<hash-utils>, [">= 0.18.0"])
55
+ s.add_runtime_dependency(%q<abstract>, [">= 1.0.0"])
56
+ s.add_runtime_dependency(%q<fluent-query>, [">= 0.9.0"])
57
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.13"])
58
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
59
+ else
60
+ s.add_dependency(%q<hash-utils>, [">= 0.18.0"])
61
+ s.add_dependency(%q<abstract>, [">= 1.0.0"])
62
+ s.add_dependency(%q<fluent-query>, [">= 0.9.0"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0.13"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<hash-utils>, [">= 0.18.0"])
68
+ s.add_dependency(%q<abstract>, [">= 1.0.0"])
69
+ s.add_dependency(%q<fluent-query>, [">= 0.9.0"])
70
+ s.add_dependency(%q<bundler>, ["~> 1.0.13"])
71
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
72
+ end
73
+ end
74
+
@@ -0,0 +1,128 @@
1
+ # encoding: utf-8
2
+ require "hash-utils/object" # >= 0.17.0
3
+
4
+ module FluentQuery
5
+ module Drivers
6
+ module Shared
7
+ module Tokens
8
+
9
+ ##
10
+ # PostgreSQL query native token.
11
+ #
12
+
13
+ class SQLToken
14
+
15
+ ##
16
+ # Query to which is this token associated to.
17
+ #
18
+
19
+ @_query
20
+
21
+ ##
22
+ # Parent driver.
23
+ #
24
+
25
+ @_driver
26
+
27
+ ##
28
+ # Original subtokens associated to native token.
29
+ #
30
+
31
+ @_subtokens
32
+
33
+ ##
34
+ # Holds token transformer.
35
+ #
36
+
37
+ TRANSFORMER = /([A-Z])/
38
+
39
+ ##
40
+ # Initializes token.
41
+ #
42
+
43
+ public
44
+ def initialize(driver, query, subtokens)
45
+ @_query = query
46
+ @_driver = driver
47
+ @_subtokens = subtokens
48
+ end
49
+
50
+ ##
51
+ # Renders this token.
52
+ #
53
+ # Name of the token transforms to the SQL form. Joins arguments
54
+ # in Array by commas, in Hash by name = value separated by
55
+ # commas form or by token body itself if token is operator.
56
+ #
57
+ # Mode can be :prepare or :build. Preparing means building the
58
+ # query without expanding the formatting directives.
59
+ #
60
+
61
+ public
62
+ def render!(mode = :build)
63
+
64
+ result = ""
65
+ processor = @_query.processor
66
+
67
+ # Transforms all subtokens to real string SQL tokens
68
+
69
+ @_subtokens.each do |token|
70
+
71
+ arguments = token.arguments
72
+ name = token.name
73
+ transformed = self._transform_token(name.to_s)
74
+ operator = @_driver.operator_token? name
75
+
76
+ if operator
77
+ glue = transformed
78
+ else
79
+ glue = ","
80
+ end
81
+
82
+ first = arguments.first
83
+
84
+ if first.array?
85
+ arguments_result = processor.process_array(first, glue)
86
+ elsif first.hash?
87
+ arguments_result = processor.process_hash(first, glue)
88
+ elsif first.symbol?
89
+ arguments_result = processor.process_identifiers(arguments)
90
+ else
91
+ arguments_result = processor.process_formatted(arguments, mode)
92
+ end
93
+
94
+ result << transformed << " " << arguments_result << " "
95
+ end
96
+
97
+ return result
98
+ end
99
+
100
+ ##
101
+ # Transform token name to the SQL token.
102
+ #
103
+ # Upper case characters handles as separators, so for example:
104
+ # 'leftJoin' will be transformed to 'LEFT JOIN'
105
+ #
106
+
107
+ protected
108
+ def _transform_token(token_name)
109
+ sql_name = token_name.to_s.gsub(self.class::TRANSFORMER, ' \1')
110
+ sql_name.upcase!
111
+
112
+ return sql_name
113
+ end
114
+
115
+ ##
116
+ # Returns appropriate class for anonymous tokens.
117
+ #
118
+
119
+ def unknown_token
120
+ FluentQuery::Drivers::Shared::Tokens::SQLToken
121
+ end
122
+
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ require "hash-utils/object" # >= 0.17.0
3
+ require "fluent-query/drivers/shared/tokens/sql"
4
+ require "fluent-query/drivers/exception"
5
+
6
+ module FluentQuery
7
+ module Drivers
8
+ module Shared
9
+ module Tokens
10
+ module SQL
11
+
12
+ ##
13
+ # Generic SQL query UPDATE token.
14
+ #
15
+
16
+ class Delete < FluentQuery::Drivers::Shared::Tokens::SQLToken
17
+
18
+ ##
19
+ # Renders this token.
20
+ #
21
+
22
+ public
23
+ def render!(mode = nil)
24
+ processor = @_query.processor
25
+ result = "DELETE"
26
+
27
+ @_subtokens.each do |token|
28
+ arguments = token.arguments
29
+
30
+ # FROM token
31
+
32
+ if token.name == :from
33
+ first = arguments.first
34
+
35
+ # Checks for arguments
36
+ if (not first.symbol?)
37
+ raise FluentQuery::Drivers::Exception::new("Symbol argument expected for #from method.")
38
+ end
39
+
40
+ # Process
41
+ table = processor.quote_identifier(first.to_s)
42
+ result << "FROM " << table
43
+
44
+ # Unknown tokens renders directly
45
+ else
46
+ result = self.unknown_token::new(@_driver, @_query, [token]).render!
47
+ end
48
+ end
49
+
50
+ return result
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+ require "fluent-query/drivers/shared/tokens/sql"
3
+ require "hash-utils/object" # >= 0.17.0
4
+
5
+ module FluentQuery
6
+ module Drivers
7
+ module Shared
8
+ module Tokens
9
+ module SQL
10
+
11
+ ##
12
+ # Generic SQL query WHERE token.
13
+ #
14
+
15
+ class From < FluentQuery::Drivers::Shared::Tokens::SQLToken
16
+
17
+ ##
18
+ # Renders this token.
19
+ #
20
+
21
+ public
22
+ def render!(mode = :build)
23
+ _class = self.unknown_token
24
+
25
+ stack = [ ]
26
+ unknown = [ ]
27
+
28
+ processor = @_query.processor
29
+ operator = @_driver.quote_operator(:and)
30
+
31
+ result = "FROM "
32
+
33
+ # Process subtokens
34
+
35
+ @_subtokens.each do |token|
36
+ arguments = token.arguments
37
+
38
+ # Known process
39
+ if token.name == :from
40
+ length = arguments.length
41
+ first = arguments.first
42
+
43
+ if length > 0
44
+ if first.symbol?
45
+ stack << processor.process_identifiers(arguments)
46
+ elsif (length > 1) or (first.string?)
47
+ stack << processor.process_formatted(arguments, mode)
48
+ elsif first.array?
49
+ stack << first.join(operator)
50
+ elsif first.hash?
51
+ stack << processor.process_hash(first, operator)
52
+ end
53
+ end
54
+
55
+ # Closes opened native token with unknown tokens
56
+ if unknown.length > 0
57
+ native = _class::new(@_driver, @_query, unknown)
58
+ stack << native
59
+ unknown = [ ]
60
+ end
61
+
62
+ # Unknowns arguments pushes to the general native token
63
+ else
64
+ unknown << token
65
+ end
66
+
67
+ end
68
+
69
+ # Closes opened native token with unknown tokens
70
+ if unknown.length > 0
71
+ native = _class::new(@_driver, @_query, unknown)
72
+ stack << native
73
+ unknown = [ ]
74
+ end
75
+
76
+ # Process stack with results
77
+ first = true
78
+
79
+ stack.each do |item|
80
+ if item.kind_of? _class
81
+ result << item.render!
82
+ elsif item.string?
83
+ if not first
84
+ result << operator << " "
85
+ else
86
+ first = false
87
+ end
88
+
89
+ result << item
90
+ end
91
+
92
+ result << " "
93
+ end
94
+
95
+ return result
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+