sql_formatter_web_interface 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v1.0.0. First release. Provides the SqlFormatterWebInterface::format and optionally the String#to_formatted_sql methods
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem 'yard'
5
+ gem 'redcarpet'
6
+ gem 'github-markup'
7
+ gem 'echoe'
8
+ end
9
+
10
+ group :test do
11
+ gem 'rspec'
12
+ gem 'heredoc_unindent'
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ allison (2.0.3)
5
+ diff-lcs (1.1.3)
6
+ echoe (4.6.3)
7
+ allison (>= 2.0.3)
8
+ gemcutter (>= 0.7.0)
9
+ rake (>= 0.9.2)
10
+ rdoc (>= 3.6.1)
11
+ rubyforge (>= 2.0.4)
12
+ gemcutter (0.7.1)
13
+ github-markup (0.7.2)
14
+ heredoc_unindent (1.1.2)
15
+ json (1.7.0)
16
+ json_pure (1.7.0)
17
+ rake (0.9.2.2)
18
+ rdoc (3.12)
19
+ json (~> 1.4)
20
+ redcarpet (2.1.1)
21
+ rspec (2.9.0)
22
+ rspec-core (~> 2.9.0)
23
+ rspec-expectations (~> 2.9.0)
24
+ rspec-mocks (~> 2.9.0)
25
+ rspec-core (2.9.0)
26
+ rspec-expectations (2.9.1)
27
+ diff-lcs (~> 1.1.3)
28
+ rspec-mocks (2.9.0)
29
+ rubyforge (2.0.4)
30
+ json_pure (>= 1.1.7)
31
+ yard (0.7.5)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ echoe
38
+ github-markup
39
+ heredoc_unindent
40
+ redcarpet
41
+ rspec
42
+ yard
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012 Maurizio De Santis <desantis.maurizio@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,14 @@
1
+ CHANGELOG
2
+ Gemfile
3
+ Gemfile.lock
4
+ LICENSE
5
+ README.markdown
6
+ Rakefile
7
+ examples/multiple_inserts.sql
8
+ examples/pg_view.sql
9
+ examples/subquery.sql
10
+ lib/sql_formatter_web_interface.rb
11
+ lib/sql_formatter_web_interface/to_formatted_sql.rb
12
+ spec/spec_helper.rb
13
+ spec/sql_formatter_web_interface_spec.rb
14
+ Manifest
data/README.markdown ADDED
@@ -0,0 +1,99 @@
1
+ # SqlFormatterWebInterface
2
+
3
+ ## Description
4
+ This library lets you write this:
5
+
6
+ ```ruby
7
+ sql = <<-SQL
8
+ select user_id, count(*) as how_many from bboard where
9
+ not exists (select 1 from bboard_authorized_maintainers bam
10
+ where bam.user_id = bboard.user_id) and posting_time + 60 > sysdate
11
+ group by user_id order by how_many desc;
12
+ SQL
13
+ SqlFormatterWebInterface.format(sql) #=>
14
+ # SELECT user_id,
15
+ # count(*) AS how_many
16
+ # FROM bboard
17
+ # WHERE NOT EXISTS
18
+ # (SELECT 1
19
+ # FROM bboard_authorized_maintainers bam
20
+ # WHERE bam.user_id = bboard.user_id)
21
+ # AND posting_time + 60 > sysdate
22
+ # GROUP BY user_id
23
+ # ORDER BY how_many DESC;
24
+ ```
25
+
26
+ or this:
27
+
28
+ ```ruby
29
+ sql = <<-SQL
30
+ insert into customer (id, name) values (1, 'John');
31
+ insert into customer (id, name) values (2, 'Jack');
32
+ insert into customer (id, name) values (3, 'Jane');
33
+ insert into customer (id, name) values (4, 'Jim');
34
+ insert into customer (id, name) values (5, 'Jerry');
35
+ insert into customer (id, name) values (1, 'Joe');
36
+ SQL
37
+ SqlFormatterWebInterface.format(sql) #=>
38
+ # INSERT INTO customer (id, name)
39
+ # VALUES (1,
40
+ # 'John');
41
+ #
42
+ # INSERT INTO customer (id, name)
43
+ # VALUES (2,
44
+ # 'Jack');
45
+ #
46
+ # INSERT INTO customer (id, name)
47
+ # VALUES (3,
48
+ # 'Jane');
49
+ #
50
+ # INSERT INTO customer (id, name)
51
+ # VALUES (4,
52
+ # 'Jim');
53
+ #
54
+ # INSERT INTO customer (id, name)
55
+ # VALUES (5,
56
+ # 'Jerry');
57
+ #
58
+ # INSERT INTO customer (id, name)
59
+ # VALUES (1,
60
+ # 'Joe');
61
+ ```
62
+
63
+ or even this:
64
+
65
+ ```ruby
66
+ require 'sql_formatter_web_interface/to_formatted_sql'
67
+ 'select * from foo join bar on val1 = val2 where id = 123;'.to_formatted_sql(:keyword_case => 'capitalize') #=>
68
+ # Select *
69
+ # From foo
70
+ # Join bar On val1 = val2
71
+ # Where id = 123;
72
+ ```
73
+
74
+ Formatting happens making a request to an online SQL formatting service (http://sqlformat.appspot.com/format/ is the only supported at the moment).
75
+
76
+ ## Installation
77
+
78
+ ```ruby
79
+ gem install sql_formatter_web_interface
80
+ ```
81
+
82
+ In your Gemfile:
83
+
84
+ ```ruby
85
+ gem 'sql_formatter_web_interface'
86
+ ```
87
+
88
+ Or, if you want to use `String#to_formatted_sql`:
89
+
90
+ ```ruby
91
+ gem 'sql_formatter_web_interface', :require => 'sql_formatter_web_interface/to_formatted_sql'
92
+ ```
93
+
94
+ ## Usage
95
+
96
+ You can use `SqlFormatterWebInterface::format(sql, options)` or either `String#to_formatted_sql(options)`, where `options` is an hash with the options supported by the web service (see http://sqlformat.appspot.com/api/)
97
+
98
+ ## License
99
+ MIT (see [LICENSE](LICENSE))
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'echoe'
2
+
3
+ Echoe.new("sql_formatter_web_interface") do |p|
4
+ p.url = 'https://github.com/ProGNOMmers/sql_formatter_web_interface'
5
+ p.project = 'sql_formatter_web_interface'
6
+ p.author = "Maurizio De Santis"
7
+ p.email = 'desantis.maurizio@gmail.com'
8
+ p.description = "SQL formatter web interface - Web interface for SQL formatting"
9
+ p.summary = "It lets you format SQL via web SQL formatting services"
10
+ end
11
+
12
+ desc 'IRB console'
13
+ task :irb do
14
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
15
+ # require 'sql_formatter_web_interface'
16
+ require 'sql_formatter_web_interface/to_formatted_sql'
17
+ require 'irb'
18
+ ARGV.clear
19
+ IRB.start
20
+ end
21
+
22
+ desc 'run example'
23
+ task :run_example, [:example_name, :options] do |t, args|
24
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
25
+ require 'sql_formatter_web_interface'
26
+
27
+ example = args.example_name
28
+
29
+ options =
30
+ if args.options.nil?
31
+ {}
32
+ else
33
+ {}.tap do |hash|
34
+ args.options.split(';').each do |v|
35
+ _v = v.split(':')
36
+ raise Exception, 'options must be in this format: opt1:val1;opt2:val2;...' unless _v.size == 2
37
+ hash[_v[0]] = _v[1]
38
+ end
39
+ end
40
+ end
41
+
42
+ examples_dir = File.join(File.dirname(__FILE__), 'examples')
43
+ examples = Dir[File.join(examples_dir, '*.sql')].map { |filename| File.basename(filename, '.sql') }
44
+
45
+ raise Exception, "there is not any example named '#{example}'" unless examples.include? example
46
+
47
+ example_content = open(File.join(examples_dir, "#{example}.sql")).read
48
+
49
+ puts SqlFormatterWebInterface.format(example_content, options)
50
+
51
+ end
@@ -0,0 +1 @@
1
+ insert into customer (id, name) values (1, 'John');insert into customer (id, name) values (2, 'Jack');insert into customer (id, name) values (3, 'Jane');insert into customer (id, name) values (4, 'Jim');insert into customer (id, name) values (5, 'Jerry');insert into customer (id, name) values (1, 'Joe');
@@ -0,0 +1 @@
1
+ SELECT DISTINCT (current_database())::information_schema.sql_identifier AS view_catalog, (nv.nspname)::information_schema.sql_identifier AS view_schema, (v.relname)::information_schema.sql_identifier AS view_name, (current_database())::information_schema.sql_identifier AS table_catalog, (nt.nspname)::information_schema.sql_identifier AS table_schema, (t.relname)::information_schema.sql_identifier AS table_name FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt WHERE ((((((((((((((nv.oid = v.relnamespace) AND (v.relkind = 'v'::"char")) AND (v.oid = dv.refobjid)) AND (dv.refclassid = ('pg_class'::regclass)::oid)) AND (dv.classid = ('pg_rewrite'::regclass)::oid)) AND (dv.deptype = 'i'::"char")) AND (dv.objid = dt.objid)) AND (dv.refobjid <> dt.refobjid)) AND (dt.classid = ('pg_rewrite'::regclass)::oid)) AND (dt.refclassid = ('pg_class'::regclass)::oid)) AND (dt.refobjid = t.oid)) AND (t.relnamespace = nt.oid)) AND (t.relkind = ANY (ARRAY['r'::"char", 'v'::"char"]))) AND pg_has_role(t.relowner, 'USAGE'::text)) ORDER BY (current_database())::information_schema.sql_identifier, (nv.nspname)::information_schema.sql_identifier, (v.relname)::information_schema.sql_identifier, (current_database())::information_schema.sql_identifier, (nt.nspname)::information_schema.sql_identifier, (t.relname)::information_schema.sql_identifier;
@@ -0,0 +1 @@
1
+ select sum(a1.Sales) from Store_Information a1 where a1.Store_name in (select store_name from Geography a2 where a2.store_name = a1.store_name);
@@ -0,0 +1,85 @@
1
+ require 'net/http'
2
+ # @author Maurizio De Santis <desantis.maurizio@gmail.com>
3
+ #
4
+ # This module helps you to format your SQL using an online SQL formatting
5
+ # service (http://sqlformat.appspot.com/format/ is the only supported at the
6
+ # moment), providing a {format} method which accepts a SQL string and returns
7
+ # the formatted version.
8
+ #
9
+ # @note <b>
10
+ # Being a web interface, it is _VERY_ unsafe sending data via HTTP
11
+ # to a service that could store informations about the requests;
12
+ # this library should be used only with queries not including
13
+ # sensitive data - did someone say _development database_?
14
+ # </b>
15
+ module SqlFormatterWebInterface
16
+
17
+ SQL_FORMATTER_URL = 'http://sqlformat.appspot.com/format/'
18
+
19
+ # @private
20
+ # XXX According to HTTP::NET API must be String => String
21
+ DEFAULT_OPTIONS = {
22
+ 'format' => 'text',
23
+ 'remove_comments' => '',
24
+ 'highlight' => '',
25
+ 'keyword_case' => 'upper',
26
+ 'identifier_case' => '',
27
+ 'n_indents' => '2',
28
+ 'right_margin' => '',
29
+ 'output_format' => 'sql'
30
+ }
31
+
32
+ # It makes a request to an online formatting service which will format a SQL string,
33
+ # according to the setted options (see http://sqlformat.appspot.com for details about
34
+ # the default SQL formatting service)
35
+ #
36
+ # @example
37
+ # sql = <<-SQL
38
+ # select user_id, count(*) as how_many from bboard where
39
+ # not exists (select 1 from bboard_authorized_maintainers bam
40
+ # where bam.user_id = bboard.user_id) and posting_time ` 60 > sysdate
41
+ # group by user_id order by how_many desc;
42
+ # SQL
43
+ # SqlFormatterWebInterface.format(sql) #=>
44
+ # # SELECT user_id,
45
+ # # count(*) AS how_many
46
+ # # FROM bboard
47
+ # # WHERE NOT EXISTS
48
+ # # (SELECT 1
49
+ # # FROM bboard_authorized_maintainers bam
50
+ # # WHERE bam.user_id = bboard.user_id)
51
+ # # AND posting_time + 60 > sysdate
52
+ # # GROUP BY user_id
53
+ # # ORDER BY how_many DESC;
54
+ #
55
+ # @param [String] sql SQL query to be formatted
56
+ # @param [Hash] options The options to pass to the web service (see
57
+ # http://sqlformat.appspot.com/api/ for informations about the
58
+ # available options); it will be merged with {DEFAULT_OPTIONS}.
59
+ # The special option `:url` can be used in order to specify
60
+ # the URL of the request (if `nil` {SQL_FORMATTER_URL} will be used)
61
+ #
62
+ # @return [String] If `sql` is a valid SQL a formatted copy of the string
63
+ # converted to the expected format, else an identical copy of the string
64
+ # @raise [SocketError] When the service cannot reach the setted URL
65
+ def self.format(sql, options = {})
66
+ uri = URI(options[:url].nil? ? SQL_FORMATTER_URL : options.delete(:url))
67
+
68
+ stringify_hash!(options)
69
+
70
+ options['data'] = sql
71
+ options = DEFAULT_OPTIONS.merge(options)
72
+
73
+ Net::HTTP.post_form(uri, options).body
74
+
75
+ rescue SocketError
76
+ raise SocketError.new "unable to resolve #{uri.to_s}"
77
+ end
78
+
79
+ private
80
+ def self.stringify_hash!(hash)
81
+ hash.keys.each do |key|
82
+ hash[key.to_s] = hash.delete(key).to_s
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ require 'sql_formatter_web_interface'
2
+
3
+ module SqlFormatterWebInterface
4
+ # Includes the {InstanceMethods#to_formatted_sql} method in the `String` class
5
+ module ToFormattedSql
6
+ def self.included(klass)
7
+ klass.send(:include, InstanceMethods)
8
+ end
9
+
10
+ module InstanceMethods
11
+ # It calls SqlFormatterWebInterface#format using `self` for `sql`
12
+ # @see SqlFormatterWebInterface#format
13
+ def to_formatted_sql(options = {})
14
+ SqlFormatterWebInterface.format(self, options)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ String.send(:include, SqlFormatterWebInterface::ToFormattedSql)
@@ -0,0 +1,3 @@
1
+ require 'open-uri'
2
+ require 'heredoc_unindent'
3
+ require 'sql_formatter_web_interface'
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ # I am online if I can reach Google
4
+ def online?
5
+ open('http://www.google.com')
6
+ true
7
+ rescue SocketError
8
+ false
9
+ end
10
+
11
+ module SqlFormatterWebInterface
12
+ describe SqlFormatterWebInterface do
13
+ before(:each) do
14
+ raise Exception, "it seems you're not online: check your internet connection" unless online?
15
+ end
16
+ describe '::format' do
17
+ context 'with a reachable url' do
18
+ it "returns a String" do
19
+ SqlFormatterWebInterface.format('').class.should == String
20
+ end
21
+ context 'with a valid sql' do
22
+ it "returns a formatted sql" do
23
+ input = <<-SQL.strip
24
+ select user_id, count(*) as how_many from bboard where
25
+ not exists (select 1 from bboard_authorized_maintainers bam
26
+ where bam.user_id = bboard.user_id) and posting_time + 60 > sysdate
27
+ group by user_id order by how_many desc;
28
+ SQL
29
+ expected_output = <<-SQL.unindent.strip
30
+ SELECT user_id,
31
+ count(*) AS how_many
32
+ FROM bboard
33
+ WHERE NOT EXISTS
34
+ (SELECT 1
35
+ FROM bboard_authorized_maintainers bam
36
+ WHERE bam.user_id = bboard.user_id)
37
+ AND posting_time + 60 > sysdate
38
+ GROUP BY user_id
39
+ ORDER BY how_many DESC;
40
+ SQL
41
+ SqlFormatterWebInterface.format(input).should == expected_output
42
+ end
43
+ end
44
+ context 'with an invalid sql' do
45
+ it "returns the same string as the input one" do
46
+ input = 'invalid blah blah blah!'
47
+ SqlFormatterWebInterface.format(input).should == input
48
+ end
49
+ end
50
+ end
51
+ context 'with an unreachable url' do
52
+ it "raises a SocketError" do
53
+ unreachable_url = 'http://this.is.an.unreachable.url'
54
+ proc { SqlFormatterWebInterface.format('', :url => unreachable_url) }.should raise_error SocketError, "unable to resolve #{unreachable_url}"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "sql_formatter_web_interface"
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Maurizio De Santis"]
9
+ s.date = "2012-04-29"
10
+ s.description = "SQL formatter web interface - Web interface for SQL formatting"
11
+ s.email = "desantis.maurizio@gmail.com"
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.markdown", "lib/sql_formatter_web_interface.rb", "lib/sql_formatter_web_interface/to_formatted_sql.rb"]
13
+ s.files = ["CHANGELOG", "Gemfile", "Gemfile.lock", "LICENSE", "README.markdown", "Rakefile", "examples/multiple_inserts.sql", "examples/pg_view.sql", "examples/subquery.sql", "lib/sql_formatter_web_interface.rb", "lib/sql_formatter_web_interface/to_formatted_sql.rb", "spec/spec_helper.rb", "spec/sql_formatter_web_interface_spec.rb", "Manifest", "sql_formatter_web_interface.gemspec"]
14
+ s.homepage = "https://github.com/ProGNOMmers/sql_formatter_web_interface"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sql_formatter_web_interface", "--main", "README.markdown"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = "sql_formatter_web_interface"
18
+ s.rubygems_version = "1.8.24"
19
+ s.summary = "It lets you format SQL via web SQL formatting services"
20
+
21
+ if s.respond_to? :specification_version then
22
+ s.specification_version = 3
23
+
24
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
+ else
26
+ end
27
+ else
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sql_formatter_web_interface
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maurizio De Santis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-29 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: SQL formatter web interface - Web interface for SQL formatting
15
+ email: desantis.maurizio@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - CHANGELOG
20
+ - LICENSE
21
+ - README.markdown
22
+ - lib/sql_formatter_web_interface.rb
23
+ - lib/sql_formatter_web_interface/to_formatted_sql.rb
24
+ files:
25
+ - CHANGELOG
26
+ - Gemfile
27
+ - Gemfile.lock
28
+ - LICENSE
29
+ - README.markdown
30
+ - Rakefile
31
+ - examples/multiple_inserts.sql
32
+ - examples/pg_view.sql
33
+ - examples/subquery.sql
34
+ - lib/sql_formatter_web_interface.rb
35
+ - lib/sql_formatter_web_interface/to_formatted_sql.rb
36
+ - spec/spec_helper.rb
37
+ - spec/sql_formatter_web_interface_spec.rb
38
+ - Manifest
39
+ - sql_formatter_web_interface.gemspec
40
+ homepage: https://github.com/ProGNOMmers/sql_formatter_web_interface
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --line-numbers
45
+ - --inline-source
46
+ - --title
47
+ - Sql_formatter_web_interface
48
+ - --main
49
+ - README.markdown
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '1.2'
64
+ requirements: []
65
+ rubyforge_project: sql_formatter_web_interface
66
+ rubygems_version: 1.8.24
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: It lets you format SQL via web SQL formatting services
70
+ test_files: []