sqldump 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/CHANGELOG +8 -0
- data/Gemfile +4 -0
- data/Guardfile +6 -0
- data/LICENSE +19 -0
- data/README.md +105 -0
- data/Rakefile +1 -0
- data/bin/sqldump +13 -0
- data/features/database_types.feature +28 -0
- data/features/dump_as_csv.feature +57 -0
- data/features/dump_as_insert.feature +23 -0
- data/features/step_definitions/sqldump_steps.rb +15 -0
- data/features/support/cuke_table_data_converter.rb +62 -0
- data/features/support/env.rb +66 -0
- data/lib/sqldump.rb +4 -0
- data/lib/sqldump/connector.rb +47 -0
- data/lib/sqldump/csv_formatter.rb +21 -0
- data/lib/sqldump/dumper.rb +23 -0
- data/lib/sqldump/formatter.rb +21 -0
- data/lib/sqldump/insert_formatter.rb +59 -0
- data/lib/sqldump/options.rb +90 -0
- data/lib/sqldump/version.rb +3 -0
- data/numbers +0 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/sqldump/connector_spec.rb +67 -0
- data/spec/sqldump/csv_formatter_spec.rb +43 -0
- data/spec/sqldump/dumper_spec.rb +28 -0
- data/spec/sqldump/formatter_spec.rb +36 -0
- data/spec/sqldump/insert_formatter_spec.rb +69 -0
- data/spec/sqldump/options_spec.rb +111 -0
- data/sqldump.gemspec +29 -0
- metadata +171 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2012 Mats Sigge
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# SQLDump
|
2
|
+
|
3
|
+
A command line tool to dump the data in a database table as INSERT or UPDATE statements, or in CSV format.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Just install the gem with
|
8
|
+
|
9
|
+
```bash
|
10
|
+
$ gem install sqldump
|
11
|
+
```
|
12
|
+
|
13
|
+
This will make the executable `sqldump` available from your command line.
|
14
|
+
|
15
|
+
**Requires Ruby 1.9.2 or later.**
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
###Simplest case (SQLite3 is default). Dumps in csv format.
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ sqldump -d mydatabase.sqlite3 mytable
|
23
|
+
```
|
24
|
+
|
25
|
+
###Dump as INSERT statements
|
26
|
+
|
27
|
+
```bash
|
28
|
+
$ sqldump -d mydatabase.sqlite3 -i mytable
|
29
|
+
```
|
30
|
+
|
31
|
+
###Postgres database with username and password
|
32
|
+
|
33
|
+
```bash
|
34
|
+
$ sqldump -T pg -d mypostgresdb -U username -P password -i mytable
|
35
|
+
```
|
36
|
+
|
37
|
+
###Show all options
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ sqldump -h
|
41
|
+
```
|
42
|
+
|
43
|
+
## Development
|
44
|
+
|
45
|
+
Questions or problems? Please post them on the [issue tracker](https://github.com/matssigge/sqldump/issues). You can contribute changes by forking the project and submitting a pull request. You can ensure the tests passing by running `bundle` and `rake`.
|
46
|
+
|
47
|
+
This gem is created by Mats Sigge and is under the MIT License.
|
48
|
+
|
49
|
+
## Roadmap
|
50
|
+
|
51
|
+
###Immediate goals
|
52
|
+
* More databases. At least MySQL and SQL Server.
|
53
|
+
* Selecting only some columns
|
54
|
+
* Support for UPDATEs
|
55
|
+
* Pretty-printing SQL on multiple lines
|
56
|
+
* Suppressing NULL columns in output
|
57
|
+
* Handling auto-incrementing columns, e.g. nextval('sequence_name') in PostgreSQL
|
58
|
+
|
59
|
+
###Longer-term goals / pipe dreams
|
60
|
+
* Configuration system, e.g. .sqldump file
|
61
|
+
** Default user, password, host, database
|
62
|
+
* "Column handlers", e.g. some way of saying that the column CREATED_AT should get the value now() or getDate() instead of whatever value is actually in the database.
|
63
|
+
* Other hooks, e.g. being able to append `SELECT @id = @@IDENTITY` after a select on SQL Server.
|
64
|
+
|
65
|
+
###Done
|
66
|
+
* Initial support for dumping INSERTs
|
67
|
+
* Support for SQLite3
|
68
|
+
* Support for PostgreSQL
|
69
|
+
|
70
|
+
## History
|
71
|
+
|
72
|
+
Once, at a company where I worked, there was a whole lot of DB scripting. So much that I got tired of writing all that SQL by hand. At first, there were some SQL scripts that generated SQL as output, i.e. something like
|
73
|
+
|
74
|
+
```SQL
|
75
|
+
SELECT 'INSERT INTO ' + ...
|
76
|
+
```
|
77
|
+
|
78
|
+
but that gets tired *really quickly*. So after a while, I started hacking on a perl tool called SQLDump. It would query the database and output the results as INSERT (or UPDATE) statements directly. More and more options were added on, and it got to be quite powerful. It could take a command line like
|
79
|
+
|
80
|
+
```bash
|
81
|
+
$ sqldump -S testserver -d test_db_14 -irtl -f SPROCKET_ID RATCHET WHERE RATCHET_DATE = '2012-01-02'
|
82
|
+
```
|
83
|
+
|
84
|
+
and output
|
85
|
+
|
86
|
+
```SQL
|
87
|
+
INSERT INTO RATCHET (
|
88
|
+
SPROCKET_ID,
|
89
|
+
RATCHET_NAME,
|
90
|
+
RATCHET_DATE
|
91
|
+
CREATED_AT
|
92
|
+
)
|
93
|
+
VALUES (
|
94
|
+
@SPROCKET_ID,
|
95
|
+
'My ratchet rocks!',
|
96
|
+
'2012-01-02',
|
97
|
+
getDate()
|
98
|
+
)
|
99
|
+
```
|
100
|
+
|
101
|
+
which was pretty useful at the time. I could chain together sequences of calls and dump whole hierarchies of data. I used it a lot.
|
102
|
+
|
103
|
+
It also ended up a big smelly mess. And while it's possible to make a mess in any language, it's one of the things that Perl does best. (Don't get me wrong, I love Perl, and can't imagíne life without it, but I've also written some of my worst code in it.) So I decided that I wanted to rewrite it in Ruby, and at least attempting to keep the code clean. Also, the initial tool was specific to both SQL Server and the idiosynchracies of the system I worked on (i.e. special handling of some column names and other stuff). My vision of this rewrite is to be able to support the same kind of special handling, but through some form of hooks instead of hard coding that logic into the guts of the tool.
|
104
|
+
|
105
|
+
Mats Sigge
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/sqldump
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'sqldump'
|
4
|
+
|
5
|
+
options = Sqldump::Options.new(ARGV)
|
6
|
+
connector = Sqldump::Connector.new(options)
|
7
|
+
connector.connect do |dbh|
|
8
|
+
dumper = Sqldump::Dumper.new(dbh, options)
|
9
|
+
dumper.dump do |sth|
|
10
|
+
formatter = Sqldump::Formatter.formatter(sth, STDOUT, options)
|
11
|
+
formatter.output
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: dump data from different database types (e.g. MySQL, PostgreSQL, SQLite, etc.)
|
2
|
+
|
3
|
+
sqldump supports dumping data from any database type supported by Ruby DBI/DBD.
|
4
|
+
The default database type is (for now) SQLite3 for the simple reason that it's extremely easy to test with.
|
5
|
+
|
6
|
+
In a distant future, there may be JRuby support for JDBC to (possibly) extend the range of supported databases
|
7
|
+
even further.
|
8
|
+
|
9
|
+
Scenario: SQLite3
|
10
|
+
|
11
|
+
Scenario: MySQL
|
12
|
+
|
13
|
+
Scenario: SQL Server
|
14
|
+
|
15
|
+
Scenario: PostgreSQL
|
16
|
+
Given a PostgreSQL database named "numbers" on "localhost"
|
17
|
+
And a table "numbers" with the following data
|
18
|
+
| number[int] |
|
19
|
+
| 17 |
|
20
|
+
| 42 |
|
21
|
+
| 4711 |
|
22
|
+
When I run `sqldump -T postgresql -d numbers -S localhost -U mats numbers`
|
23
|
+
Then it should pass with:
|
24
|
+
"""
|
25
|
+
17
|
26
|
+
42
|
27
|
+
4711
|
28
|
+
"""
|
@@ -0,0 +1,57 @@
|
|
1
|
+
Feature: dump as csv
|
2
|
+
|
3
|
+
The default mode of operation of sqldump is to output data in CSV
|
4
|
+
√
|
5
|
+
Scenario: one-column, one-row table
|
6
|
+
Given a database "foo.sqlite" with a table "number" with the following data
|
7
|
+
| number[int] |
|
8
|
+
| 42 |
|
9
|
+
When I run `sqldump -d foo.sqlite number`
|
10
|
+
Then it should pass with:
|
11
|
+
"""
|
12
|
+
42
|
13
|
+
"""
|
14
|
+
|
15
|
+
Scenario: multi-row table
|
16
|
+
Given a database "foo.sqlite" with a table "numbers" with the following data
|
17
|
+
| number[int] |
|
18
|
+
| 17 |
|
19
|
+
| 42 |
|
20
|
+
| 4711 |
|
21
|
+
When I run `sqldump -d foo.sqlite numbers`
|
22
|
+
Then it should pass with:
|
23
|
+
"""
|
24
|
+
17
|
25
|
+
42
|
26
|
+
4711
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: multi-column table
|
30
|
+
Given a database "foo.sqlite" with a table "numbers_and_strings" with the following data
|
31
|
+
| number[int] | string |
|
32
|
+
| 17 | foo |
|
33
|
+
| 42 | bar |
|
34
|
+
| 4711 | baz |
|
35
|
+
When I run `sqldump -d foo.sqlite numbers_and_strings`
|
36
|
+
Then it should pass with:
|
37
|
+
"""
|
38
|
+
17,foo
|
39
|
+
42,bar
|
40
|
+
4711,baz
|
41
|
+
"""
|
42
|
+
|
43
|
+
Scenario: with header line
|
44
|
+
Given a database "foo.sqlite" with a table "numbers_strings_and_things" with the following data
|
45
|
+
| number[int] | string | thing |
|
46
|
+
| 17 | foo | rubber duck |
|
47
|
+
When I run `sqldump -d foo.sqlite -H numbers_strings_and_things`
|
48
|
+
Then it should pass with:
|
49
|
+
"""
|
50
|
+
number,string,thing
|
51
|
+
17,foo,rubber duck
|
52
|
+
"""
|
53
|
+
|
54
|
+
Scenario: custom separator
|
55
|
+
|
56
|
+
|
57
|
+
Scenario: quoting of separator
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Feature: dump data as INSERT statements
|
2
|
+
|
3
|
+
sqldump can dump data as INSERT statements so that the corresponding data can be inserted in a new database
|
4
|
+
|
5
|
+
Scenario: simple table
|
6
|
+
Given a database "foo.sqlite" with a table "number" with the following data
|
7
|
+
| number[int] |
|
8
|
+
| 42 |
|
9
|
+
When I run `sqldump -d foo.sqlite -i number`
|
10
|
+
Then it should pass with:
|
11
|
+
"""
|
12
|
+
INSERT INTO number (number) VALUES (42);
|
13
|
+
"""
|
14
|
+
|
15
|
+
Scenario: null value
|
16
|
+
Given a database "foo.sqlite" with a table "number" with the following data
|
17
|
+
| number[int] |
|
18
|
+
| <null> |
|
19
|
+
When I run `sqldump -d foo.sqlite -i number`
|
20
|
+
Then it should pass with:
|
21
|
+
"""
|
22
|
+
INSERT INTO number (number) VALUES (NULL);
|
23
|
+
"""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'dbi'
|
2
|
+
|
3
|
+
Given /^a database "([^"]*)" with a table "([^"]*)" with the following data$/ do |database, table_name, table|
|
4
|
+
create_dummy_database_with_data(:sqlite3, nil, database, table_name, table)
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^a PostgreSQL database named "([^"]*)" on "([^"]*)"$/ do |database, host|
|
8
|
+
@database = database
|
9
|
+
@host = host
|
10
|
+
@driver = :postgresql
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^a table "([^"]*)" with the following data$/ do |table_name, table|
|
14
|
+
create_dummy_database_with_data(@driver, @host, @database, table_name, table)
|
15
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class CukeTableDataConverter
|
2
|
+
|
3
|
+
def initialize(table_name, table)
|
4
|
+
@table_name = table_name
|
5
|
+
@table = table
|
6
|
+
|
7
|
+
@column_names = extract_column_names(table)
|
8
|
+
@datatypes = extract_column_datatypes(table)
|
9
|
+
end
|
10
|
+
|
11
|
+
def extract_column_names(table)
|
12
|
+
table.column_names.collect { |column| column_name(column) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract_column_datatypes(table)
|
16
|
+
datatypes = Hash.new
|
17
|
+
table.column_names.each do |column|
|
18
|
+
datatype = column_datatype(column)
|
19
|
+
datatypes[column_name(column)] = datatype
|
20
|
+
end
|
21
|
+
datatypes
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_create_table_sql
|
25
|
+
query = "CREATE TABLE #{@table_name} ("
|
26
|
+
query += @column_names.collect { |column| "#{column} #{@datatypes[column]}" }.join ", "
|
27
|
+
query += ");"
|
28
|
+
query
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_insert_sql
|
32
|
+
sql = []
|
33
|
+
@table.hashes.each do |hash|
|
34
|
+
query = "INSERT INTO #{@table_name} ("
|
35
|
+
query += @column_names.join ", "
|
36
|
+
query += ") VALUES ("
|
37
|
+
query += @table.column_names.collect { |column| as_sql_literal(hash[column]) }.join ", "
|
38
|
+
query += ");"
|
39
|
+
sql << query
|
40
|
+
end
|
41
|
+
sql
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_sql_literal(value)
|
45
|
+
if value == '<null>'
|
46
|
+
'NULL'
|
47
|
+
elsif (value =~ /[^0-9]/ || value =~ /^0./)
|
48
|
+
"'#{value}'"
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def column_name(column_heading)
|
55
|
+
/^(\w+)/.match(column_heading)[1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def column_datatype(column_heading)
|
59
|
+
column_heading =~ /\[([^\]]+)\]/ ? $1 : 'varchar(100)'
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path('../../../lib', __FILE__)
|
2
|
+
require 'aruba/cucumber'
|
3
|
+
# Ensure aruba can find the bin folder
|
4
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
5
|
+
|
6
|
+
def drop_database_if_exists(driver, host, database, username, password)
|
7
|
+
case driver
|
8
|
+
when :sqlite3
|
9
|
+
File.delete(database) if File.exists?(database)
|
10
|
+
when :postgresql
|
11
|
+
DBI.connect("DBI:Pg:postgres:#{host}", username, password) do |dbh|
|
12
|
+
dbh.do("DROP DATABASE IF EXISTS #{database}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_driver_string(driver)
|
18
|
+
driver_string = case driver
|
19
|
+
when :sqlite3
|
20
|
+
"SQLite3"
|
21
|
+
when :postgresql
|
22
|
+
"Pg"
|
23
|
+
end
|
24
|
+
driver_string
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_and_connect_to_database(driver, host, database, username, password, &block)
|
28
|
+
create_database(driver, host, database, username, password)
|
29
|
+
|
30
|
+
url = "DBI:#{get_driver_string(driver)}:#{database}"
|
31
|
+
url += ":#{host}" if host
|
32
|
+
|
33
|
+
if block
|
34
|
+
DBI.connect(url, username, password, nil, &block)
|
35
|
+
end
|
36
|
+
DBI.connect(url, username, password)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_database(driver, host, database, username, password)
|
40
|
+
case driver
|
41
|
+
when :sqlite3
|
42
|
+
# Do nothing - just connecting to the correct filename creates the database
|
43
|
+
when :postgresql
|
44
|
+
DBI.connect("DBI:Pg:postgres:#{host}", username, password) do |dbh|
|
45
|
+
dbh.do("CREATE DATABASE #{database}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_dummy_database_with_data(driver, host, database, table_name, table_data)
|
51
|
+
username = 'mats'
|
52
|
+
password = nil
|
53
|
+
|
54
|
+
in_current_dir do
|
55
|
+
drop_database_if_exists(driver, host, database, username, password)
|
56
|
+
|
57
|
+
converter = CukeTableDataConverter.new(table_name, table_data)
|
58
|
+
|
59
|
+
create_and_connect_to_database(driver, host, database, username, password) do |dbh|
|
60
|
+
dbh.do(converter.get_create_table_sql)
|
61
|
+
converter.get_insert_sql.each do |sql|
|
62
|
+
dbh.do(sql)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/sqldump.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'dbi'
|
2
|
+
|
3
|
+
module Sqldump
|
4
|
+
|
5
|
+
class Connector
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect
|
12
|
+
begin
|
13
|
+
dbh = DBI.connect(get_url, get_user, get_password)
|
14
|
+
yield dbh
|
15
|
+
|
16
|
+
ensure
|
17
|
+
dbh.disconnect if dbh
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_url
|
23
|
+
database = @options.database
|
24
|
+
driver = get_driver
|
25
|
+
"DBI:#{driver}:#{database}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_driver
|
29
|
+
case @options.database_type
|
30
|
+
when :sqlite3
|
31
|
+
"SQLite3"
|
32
|
+
when :postgresql
|
33
|
+
"Pg"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_user
|
38
|
+
@options.username
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_password
|
42
|
+
@options.password
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sqldump
|
2
|
+
|
3
|
+
class CsvFormatter
|
4
|
+
|
5
|
+
def initialize(sth, io, options)
|
6
|
+
@sth = sth
|
7
|
+
@io = io
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def output
|
12
|
+
if @options.csv_header
|
13
|
+
@io.puts @sth.column_names.join(",")
|
14
|
+
end
|
15
|
+
@sth.fetch do |row|
|
16
|
+
@io.puts row.join(",")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Sqldump
|
2
|
+
|
3
|
+
class Dumper
|
4
|
+
|
5
|
+
def initialize(dbh, options)
|
6
|
+
@dbh = dbh
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump
|
11
|
+
begin
|
12
|
+
sth = @dbh.execute(@options.sql)
|
13
|
+
yield sth
|
14
|
+
|
15
|
+
ensure
|
16
|
+
sth.finish if sth
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'sqldump/csv_formatter'
|
2
|
+
require 'sqldump/insert_formatter'
|
3
|
+
|
4
|
+
module Sqldump
|
5
|
+
|
6
|
+
class Formatter
|
7
|
+
|
8
|
+
private_class_method :new
|
9
|
+
|
10
|
+
def self.formatter(sth, io, options)
|
11
|
+
case options.dump_mode
|
12
|
+
when :csv
|
13
|
+
CsvFormatter.new(sth, io, options)
|
14
|
+
when :insert
|
15
|
+
InsertFormatter.new(sth, io, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Sqldump
|
2
|
+
|
3
|
+
class InsertFormatter
|
4
|
+
|
5
|
+
def initialize(sth, io, options)
|
6
|
+
@sth = sth
|
7
|
+
@io = io
|
8
|
+
@options = options
|
9
|
+
|
10
|
+
setup_column_type_mapping()
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup_column_type_mapping
|
14
|
+
@column_type_by_name = Hash[@sth.column_names.zip(@sth.column_types)]
|
15
|
+
end
|
16
|
+
|
17
|
+
def column_type(column_name)
|
18
|
+
@column_type_by_name[column_name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def output_column_names
|
22
|
+
@io.print @sth.column_names.join(", ")
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_values(row)
|
26
|
+
quoted_list = []
|
27
|
+
row.each_with_name do |value, column_name|
|
28
|
+
quoted_list.push quote(value, column_name)
|
29
|
+
end
|
30
|
+
@io.print quoted_list.join(", ")
|
31
|
+
end
|
32
|
+
|
33
|
+
def output
|
34
|
+
@sth.fetch do |row|
|
35
|
+
@io.print("INSERT INTO #{@options.table} (")
|
36
|
+
output_column_names()
|
37
|
+
@io.print ") VALUES ("
|
38
|
+
output_values(row)
|
39
|
+
@io.print ");\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def quote(value, column_name)
|
44
|
+
if value.nil?
|
45
|
+
"NULL"
|
46
|
+
else
|
47
|
+
type = column_type(column_name)
|
48
|
+
if type == DBI::Type::Integer or type == DBI::Type::Float or type == DBI::Type::Decimal
|
49
|
+
value
|
50
|
+
else
|
51
|
+
value = value.to_s.gsub(/'/, "''")
|
52
|
+
"'#{value}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Sqldump
|
4
|
+
|
5
|
+
class Options
|
6
|
+
|
7
|
+
attr_accessor :database
|
8
|
+
attr_accessor :host
|
9
|
+
attr_accessor :username
|
10
|
+
attr_accessor :password
|
11
|
+
attr_accessor :database_type
|
12
|
+
attr_accessor :table
|
13
|
+
attr_accessor :sql
|
14
|
+
attr_accessor :csv_header
|
15
|
+
attr_accessor :dump_mode
|
16
|
+
|
17
|
+
def initialize(argv)
|
18
|
+
parse_options(argv)
|
19
|
+
|
20
|
+
set_derived_options(argv)
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_derived_options(argv)
|
24
|
+
self.table = argv[0]
|
25
|
+
|
26
|
+
self.sql = "select * from " + argv.join(" ")
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_options(argv)
|
30
|
+
optparse = define_options()
|
31
|
+
optparse.parse!(argv)
|
32
|
+
if argv.size == 0
|
33
|
+
print optparse
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup_defaults
|
39
|
+
self.dump_mode = :csv
|
40
|
+
self.database_type = :sqlite3
|
41
|
+
self.host = 'localhost'
|
42
|
+
end
|
43
|
+
|
44
|
+
def define_options
|
45
|
+
optparse = OptionParser.new do |opts|
|
46
|
+
setup_defaults()
|
47
|
+
|
48
|
+
opts.banner = "Usage: sqldump [options] table [extra sql]"
|
49
|
+
|
50
|
+
opts.on_head('-h', '--help', 'Display this help.') do
|
51
|
+
puts opts
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: Handle line wrapping in description
|
56
|
+
opts.on('-d', '--database DATABASE', "Specify the database to dump data from. In the case of file-based databases, this should be the full path of the database file.") do |database|
|
57
|
+
self.database = database
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on('-S', '--host USER', 'Specifies the host where the database is located, if applicable. If not specified, the default host is localhost.') do |host|
|
61
|
+
self.host = host
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on('-U', '--username USER', 'Specifies the username to use') do |username|
|
65
|
+
self.username = username
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on('-P', '--password PASSWORD', 'Specifies the password to use') do |password|
|
69
|
+
self.password = password
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on('-T', '--dbtype TYPE', 'Specify the type of database to connect to. Supported types are sqlite3, postgresql/pg.') do |type|
|
73
|
+
type = 'postgresql' if type == 'pg'
|
74
|
+
self.database_type = type.to_sym
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on('-i', '--insert', 'Dump data as INSERT statements.') do
|
78
|
+
self.dump_mode = :insert
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on('-H', '--header', 'Include column names in csv mode.') do
|
82
|
+
self.csv_header = true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
optparse
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/numbers
ADDED
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sqldump'
|
2
|
+
require 'dbi'
|
3
|
+
|
4
|
+
class Object
|
5
|
+
|
6
|
+
def create_dummy_database(database = '/tmp/foo.sqlite')
|
7
|
+
File.delete(database) if File.exists?(database)
|
8
|
+
|
9
|
+
dbh = DBI.connect("DBI:SQLite3:#{database}")
|
10
|
+
dbh.do("CREATE TABLE numbers (number int);")
|
11
|
+
dbh.do("INSERT INTO numbers (number) VALUES (42);")
|
12
|
+
dbh
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Sqldump
|
5
|
+
|
6
|
+
describe 'Connector' do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@options = double('options')
|
10
|
+
@options.stub(:database).and_return('database')
|
11
|
+
@options.stub(:database_type).and_return(:sqlite3)
|
12
|
+
@options.stub(:username).and_return(nil)
|
13
|
+
@options.stub(:password).and_return(nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#connect' do
|
17
|
+
|
18
|
+
it 'connects to the specified database' do
|
19
|
+
database = "/tmp/foo.sqlite"
|
20
|
+
dbh = create_dummy_database(database)
|
21
|
+
dbh.disconnect
|
22
|
+
|
23
|
+
@options.stub(:database).and_return(database)
|
24
|
+
|
25
|
+
connector = Connector.new(@options)
|
26
|
+
connector.connect do |dbh|
|
27
|
+
sth = dbh.execute("SELECT * FROM numbers")
|
28
|
+
sth.fetch do |row|
|
29
|
+
row[0].should == 42
|
30
|
+
end
|
31
|
+
sth.finish
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#get_url' do
|
38
|
+
it 'uses the Pg driver when postgresql is specified' do
|
39
|
+
@options.stub(:database).and_return('numbers')
|
40
|
+
@options.stub(:database_type).and_return(:postgresql)
|
41
|
+
|
42
|
+
connector = Connector.new(@options)
|
43
|
+
connector.get_url.should == 'DBI:Pg:numbers'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#get_user' do
|
48
|
+
it 'returns the specified password' do
|
49
|
+
@options.stub(:username).and_return('the_user')
|
50
|
+
|
51
|
+
connector = Connector.new(@options)
|
52
|
+
connector.get_user.should == 'the_user'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#get_user' do
|
57
|
+
it 'returns the specified password' do
|
58
|
+
@options.stub(:password).and_return('top_secret')
|
59
|
+
|
60
|
+
connector = Connector.new(@options)
|
61
|
+
connector.get_password.should == 'top_secret'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'dbi'
|
4
|
+
|
5
|
+
module Sqldump
|
6
|
+
|
7
|
+
describe "CsvFormatter" do
|
8
|
+
|
9
|
+
def formatter_example(csv_header_option, expected_result)
|
10
|
+
strio = StringIO.new
|
11
|
+
|
12
|
+
options = double("Options")
|
13
|
+
options.stub(:csv_header).and_return(csv_header_option)
|
14
|
+
|
15
|
+
formatter = CsvFormatter.new(@sth, strio, options)
|
16
|
+
formatter.output
|
17
|
+
strio.close
|
18
|
+
strio.string.should == expected_result
|
19
|
+
end
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
@dbh = create_dummy_database
|
23
|
+
@dbh.do("create table numbers_and_strings (number int, string varchar(100));")
|
24
|
+
@dbh.do("insert into numbers_and_strings values (42, 'thingy')")
|
25
|
+
@sth = @dbh.execute "select * from numbers_and_strings"
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:each) do
|
29
|
+
@sth.finish
|
30
|
+
@dbh.disconnect
|
31
|
+
end
|
32
|
+
|
33
|
+
it "prints column values verbatim, semicolon-separated, to supplied IO object" do
|
34
|
+
formatter_example(false, "42,thingy\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "prints column headings when given csv_header flag" do
|
38
|
+
formatter_example(true, "number,string\n42,thingy\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Sqldump
|
5
|
+
|
6
|
+
describe 'Dumper' do
|
7
|
+
|
8
|
+
describe 'Dump' do
|
9
|
+
|
10
|
+
it 'Executes the select and passes an open statement handle to the supplied block' do
|
11
|
+
dbh = create_dummy_database
|
12
|
+
|
13
|
+
options = double('options')
|
14
|
+
options.stub(:sql).and_return("select * from numbers")
|
15
|
+
|
16
|
+
dumper = Dumper.new(dbh, options)
|
17
|
+
dumper.dump do |sth|
|
18
|
+
sth.fetch do |row|
|
19
|
+
row[0].should == 42
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Sqldump
|
5
|
+
|
6
|
+
describe Formatter do
|
7
|
+
|
8
|
+
context "dump_mode is :csv" do
|
9
|
+
|
10
|
+
it "creates a CsvFormatter" do
|
11
|
+
options = double("Options")
|
12
|
+
options.stub(:dump_mode).and_return(:csv)
|
13
|
+
formatter = Formatter.formatter(nil, nil, options)
|
14
|
+
formatter.class.should == CsvFormatter
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
context "dump_mode is :insert" do
|
20
|
+
|
21
|
+
class InsertFormatter
|
22
|
+
def setup_column_type_mapping
|
23
|
+
@column_type_by_name = {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "creates an InsertFormatter" do
|
28
|
+
options = double("Options")
|
29
|
+
options.stub(:dump_mode).and_return(:insert)
|
30
|
+
formatter = Formatter.formatter(double("sth").as_null_object, nil, options)
|
31
|
+
formatter.class.should == InsertFormatter
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'dbi'
|
4
|
+
|
5
|
+
module Sqldump
|
6
|
+
|
7
|
+
describe InsertFormatter do
|
8
|
+
|
9
|
+
describe "#output" do
|
10
|
+
|
11
|
+
def formatter_example(expected_result)
|
12
|
+
strio = StringIO.new
|
13
|
+
|
14
|
+
options = double("Options")
|
15
|
+
options.stub(:table).and_return('numbers_and_strings')
|
16
|
+
|
17
|
+
formatter = InsertFormatter.new(@sth, strio, options)
|
18
|
+
formatter.output
|
19
|
+
strio.close
|
20
|
+
|
21
|
+
strio.string.should == expected_result
|
22
|
+
end
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
@dbh = create_dummy_database
|
26
|
+
@dbh.do("create table numbers_and_strings (number int, string varchar(100));")
|
27
|
+
@dbh.do("insert into numbers_and_strings values (42, 'thingy')")
|
28
|
+
@sth = @dbh.execute "select * from numbers_and_strings"
|
29
|
+
end
|
30
|
+
|
31
|
+
after(:each) do
|
32
|
+
@sth.finish
|
33
|
+
@dbh.disconnect
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates an insert statement for each row of the table" do
|
37
|
+
formatter_example("INSERT INTO numbers_and_strings (number, string) VALUES (42, 'thingy');\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#quote" do
|
43
|
+
|
44
|
+
class InsertFormatter
|
45
|
+
def setup_column_type_mapping
|
46
|
+
@column_type_by_name = {
|
47
|
+
"number" => DBI::Type::Integer,
|
48
|
+
"string" => DBI::Type::Varchar
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
before(:each) do
|
54
|
+
@formatter = InsertFormatter.new(nil, nil, nil)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "quotes a string" do
|
58
|
+
@formatter.quote("thing", "string").should == "'thing'"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "doesn't quote an integer" do
|
62
|
+
@formatter.quote(17, "number").should == 17
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
def make_options(args)
|
5
|
+
args << 'table' unless args[-1] == 'table'
|
6
|
+
Sqldump::Options.new(args)
|
7
|
+
end
|
8
|
+
|
9
|
+
module Sqldump
|
10
|
+
|
11
|
+
describe 'Options handler' do
|
12
|
+
|
13
|
+
|
14
|
+
describe 'database and table' do
|
15
|
+
let(:options) { make_options(%w(-d dbname table)) }
|
16
|
+
|
17
|
+
it "extracts the database name" do
|
18
|
+
options.database.should == 'dbname'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "extracts the table name" do
|
22
|
+
options.table.should == 'table'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "generates select sql" do
|
26
|
+
options.sql.should match /select \* from table/i
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'host' do
|
31
|
+
it 'sets the host to localhost if not specified' do
|
32
|
+
options = make_options([])
|
33
|
+
options.host.should == 'localhost'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'sets the host to what is specified' do
|
37
|
+
options = make_options(%w(-S server.example.com))
|
38
|
+
options.host.should == 'server.example.com'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'database type' do
|
43
|
+
it 'sets the default to SQLite3' do
|
44
|
+
options = make_options([])
|
45
|
+
options.database_type.should == :sqlite3
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'sets the type to postgresql if specified' do
|
49
|
+
options = make_options(%w(-T postgresql))
|
50
|
+
options.database_type.should == :postgresql
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'pg is an alias for postgresql' do
|
54
|
+
options = make_options(%w(-T pg))
|
55
|
+
options.database_type.should == :postgresql
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'username' do
|
60
|
+
it 'sets the username to nil if not specified' do
|
61
|
+
options = make_options([])
|
62
|
+
options.username.should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'sets the username to what is specified' do
|
66
|
+
options = make_options(%w(-U the_user))
|
67
|
+
options.username.should == 'the_user'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'password' do
|
72
|
+
it 'sets the password to nil if not specified' do
|
73
|
+
options = make_options([])
|
74
|
+
options.password.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'sets the username to what is specified' do
|
78
|
+
options = make_options(%w(-P top_secret table))
|
79
|
+
options.password.should == 'top_secret'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'csv mode is default' do
|
84
|
+
it "sets the mode to :csv" do
|
85
|
+
options = make_options([])
|
86
|
+
options.dump_mode.should == :csv
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'csv header option' do
|
91
|
+
it "the csv_header flag is false by default" do
|
92
|
+
options = make_options([])
|
93
|
+
options.csv_header.should be_false
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sets the options flag csv_header to true" do
|
97
|
+
options = make_options(%w(-H table))
|
98
|
+
options.csv_header.should be_true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'insert mode option' do
|
103
|
+
it "sets the mode to :insert" do
|
104
|
+
options = make_options(%w(-i table))
|
105
|
+
options.dump_mode.should == :insert
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/sqldump.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "sqldump/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sqldump"
|
7
|
+
s.version = Sqldump::VERSION
|
8
|
+
s.authors = ["Mats Sigge"]
|
9
|
+
s.email = ["mats.sigge@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/matssigge/sqldump"
|
11
|
+
s.summary = %q{Dumps data as insert statements}
|
12
|
+
s.description = %q{A command line tool to generate SQL insert or update statements from the data in a database.}
|
13
|
+
|
14
|
+
# s.rubyforge_project = "sqldump"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_dependency "dbi"
|
23
|
+
s.add_dependency "dbd-sqlite3"
|
24
|
+
s.add_development_dependency "rspec"
|
25
|
+
s.add_development_dependency "cucumber"
|
26
|
+
s.add_development_dependency "guard-rspec"
|
27
|
+
s.add_development_dependency "rb-fsevent" if RUBY_PLATFORM =~ /darwin/i
|
28
|
+
s.add_development_dependency "dbd-pg"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqldump
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mats Sigge
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-05 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: dbi
|
16
|
+
requirement: &2160361380 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2160361380
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dbd-sqlite3
|
27
|
+
requirement: &2160360440 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2160360440
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &2160359900 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2160359900
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: cucumber
|
49
|
+
requirement: &2160359280 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2160359280
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard-rspec
|
60
|
+
requirement: &2160358300 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2160358300
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rb-fsevent
|
71
|
+
requirement: &2160357060 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2160357060
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: dbd-pg
|
82
|
+
requirement: &2160353280 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2160353280
|
91
|
+
description: A command line tool to generate SQL insert or update statements from
|
92
|
+
the data in a database.
|
93
|
+
email:
|
94
|
+
- mats.sigge@gmail.com
|
95
|
+
executables:
|
96
|
+
- sqldump
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- .gitignore
|
101
|
+
- .idea/inspectionProfiles/Project_Default.xml
|
102
|
+
- .idea/inspectionProfiles/profiles_settings.xml
|
103
|
+
- .rspec
|
104
|
+
- CHANGELOG
|
105
|
+
- Gemfile
|
106
|
+
- Guardfile
|
107
|
+
- LICENSE
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- bin/sqldump
|
111
|
+
- features/database_types.feature
|
112
|
+
- features/dump_as_csv.feature
|
113
|
+
- features/dump_as_insert.feature
|
114
|
+
- features/step_definitions/sqldump_steps.rb
|
115
|
+
- features/support/cuke_table_data_converter.rb
|
116
|
+
- features/support/env.rb
|
117
|
+
- lib/sqldump.rb
|
118
|
+
- lib/sqldump/connector.rb
|
119
|
+
- lib/sqldump/csv_formatter.rb
|
120
|
+
- lib/sqldump/dumper.rb
|
121
|
+
- lib/sqldump/formatter.rb
|
122
|
+
- lib/sqldump/insert_formatter.rb
|
123
|
+
- lib/sqldump/options.rb
|
124
|
+
- lib/sqldump/version.rb
|
125
|
+
- numbers
|
126
|
+
- spec/spec_helper.rb
|
127
|
+
- spec/sqldump/connector_spec.rb
|
128
|
+
- spec/sqldump/csv_formatter_spec.rb
|
129
|
+
- spec/sqldump/dumper_spec.rb
|
130
|
+
- spec/sqldump/formatter_spec.rb
|
131
|
+
- spec/sqldump/insert_formatter_spec.rb
|
132
|
+
- spec/sqldump/options_spec.rb
|
133
|
+
- sqldump.gemspec
|
134
|
+
homepage: http://github.com/matssigge/sqldump
|
135
|
+
licenses: []
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 1.8.10
|
155
|
+
signing_key:
|
156
|
+
specification_version: 3
|
157
|
+
summary: Dumps data as insert statements
|
158
|
+
test_files:
|
159
|
+
- features/database_types.feature
|
160
|
+
- features/dump_as_csv.feature
|
161
|
+
- features/dump_as_insert.feature
|
162
|
+
- features/step_definitions/sqldump_steps.rb
|
163
|
+
- features/support/cuke_table_data_converter.rb
|
164
|
+
- features/support/env.rb
|
165
|
+
- spec/spec_helper.rb
|
166
|
+
- spec/sqldump/connector_spec.rb
|
167
|
+
- spec/sqldump/csv_formatter_spec.rb
|
168
|
+
- spec/sqldump/dumper_spec.rb
|
169
|
+
- spec/sqldump/formatter_spec.rb
|
170
|
+
- spec/sqldump/insert_formatter_spec.rb
|
171
|
+
- spec/sqldump/options_spec.rb
|