jsonsql 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +45 -0
- data/Rakefile +1 -0
- data/bin/jsonsql +5 -0
- data/jsonsql.gemspec +27 -0
- data/jsonsql.gif +0 -0
- data/lib/jsonsql.rb +4 -0
- data/lib/jsonsql/command.rb +49 -0
- data/lib/jsonsql/importer.rb +67 -0
- data/lib/jsonsql/transformer.rb +17 -0
- data/lib/jsonsql/version.rb +3 -0
- data/samples/mtr/437582112921640960.json +7 -0
- data/samples/mtr/437619123200086016.json +7 -0
- data/samples/mtr/437741703663869953.json +7 -0
- data/samples/mtr/437742060028719104.json +7 -0
- data/samples/mtr/437745519050256384.json +7 -0
- data/samples/mtr/437745801716985856.json +7 -0
- data/samples/mtr/437750489242161153.json +7 -0
- data/samples/mtr/437752084700467201.json +7 -0
- data/samples/mtr/437752199980933120.json +7 -0
- data/samples/mtr/437776429975994368.json +7 -0
- data/samples/mtr/438102225232359424.json +7 -0
- data/samples/mtr/438102443663314944.json +7 -0
- data/samples/mtr/438104066649247744.json +7 -0
- data/samples/mtr/438104276263784448.json +7 -0
- data/samples/mtr/438106319539937280.json +7 -0
- data/samples/mtr/438106591116922880.json +7 -0
- data/samples/mtr/438106828455829505.json +7 -0
- data/samples/mtr/438108309355511809.json +7 -0
- data/samples/mtr/438118659513663488.json +7 -0
- data/samples/mtr/438118752815972352.json +7 -0
- data/samples/mtr/438126088913309696.json +7 -0
- data/samples/mtr/438126258451275778.json +7 -0
- data/samples/mtr/438127980003348480.json +7 -0
- data/samples/mtr/438162980908175360.json +7 -0
- data/samples/mtr/438169095335206912.json +7 -0
- data/samples/mtr/438169291074965506.json +7 -0
- data/samples/mtr/438182947787505664.json +7 -0
- data/samples/mtr/438184226127486976.json +7 -0
- data/samples/mtr/438184269517574145.json +7 -0
- data/samples/mtr/438298854644256768.json +7 -0
- data/samples/mtr/438376362844233729.json +7 -0
- data/samples/mtr/438378012992475136.json +7 -0
- data/samples/mtr/438484708301631488.json +7 -0
- data/samples/mtr/438525303129128960.json +7 -0
- data/samples/mtr/438525455046410241.json +7 -0
- data/samples/mtr/438836995029090304.json +7 -0
- data/samples/mtr/438837397577408512.json +7 -0
- data/samples/mtr/438882017023762432.json +7 -0
- data/samples/mtr/438885035861483520.json +7 -0
- data/samples/mtr/438886437241364480.json +7 -0
- data/samples/mtr/438923308999135232.json +7 -0
- data/samples/mtr/438931286992773120.json +7 -0
- data/samples/mtr/439026660629692416.json +7 -0
- data/spec/importer_spec.rb +47 -0
- data/spec/spec_helpers.rb +2 -0
- data/spec/transformer_spec.rb +27 -0
- metadata +67 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff85f78499548e7afc3b76ff4527c3aad4636b2e
|
4
|
+
data.tar.gz: ba0108c1dcaef8f1e420f9a702e52747ef5a16a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bb30649e94c0f6c6d66fe0a28327d22c349a642ff3f2169a8091fe0cc99863035ebe7340bde7551006f2894ba3bfd577b0829eefe17efc33252075bad67dab5
|
7
|
+
data.tar.gz: 923a298f3183a4eaad8757ee6d645ead3dff5363069bdab7cdf644a5d8ecd372838734d37202940a647cc3d34f6ca7c74d1f757649af23e2a94fb6b264e33a49
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Francis Chong
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Jsonsql
|
2
|
+
|
3
|
+
Allows you to easily execute SQL against and experiment group of JSON files.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'jsonsql'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install jsonsql
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
jsonsql assume you have set of JSON files having identical structure. To use it, you supply set of JSON files to jsonsql:
|
24
|
+
|
25
|
+
```
|
26
|
+
jsonsql data/*.json --save-to=output.sqlite
|
27
|
+
```
|
28
|
+
|
29
|
+
The JSON will imported to output.sqlite file.
|
30
|
+
|
31
|
+
Adding ``--console`` will open a ``pry`` console with the database as ``self``.
|
32
|
+
|
33
|
+
```
|
34
|
+
jsonsql data/*.json --console --save-to=output.sqlite
|
35
|
+
```
|
36
|
+
|
37
|
+
If you omit the ``--save-to`` option, the database will be discarded after the command.
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
1. Fork it ( http://github.com/<my-github-username>/jsonsql/fork )
|
42
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
43
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
44
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
45
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/jsonsql
ADDED
data/jsonsql.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jsonsql/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "jsonsql"
|
8
|
+
spec.version = Jsonsql::VERSION
|
9
|
+
spec.authors = ["Francis Chong"]
|
10
|
+
spec.email = ["francis@ignition.hk"]
|
11
|
+
spec.summary = %q{Execute SQL against set of JSON files.}
|
12
|
+
spec.description = %q{Allows you to easily execute SQL against and experiment group of JSON files.}
|
13
|
+
spec.homepage = "https://github.com/siuying/jsonsql"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_dependency "sequel"
|
25
|
+
spec.add_dependency "sqlite3"
|
26
|
+
spec.add_dependency "claide"
|
27
|
+
end
|
data/jsonsql.gif
ADDED
Binary file
|
data/lib/jsonsql.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'claide'
|
2
|
+
require_relative './importer'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
module Jsonsql
|
6
|
+
class Command < CLAide::Command
|
7
|
+
self.description = 'Execute SQL against set of JSON files'
|
8
|
+
self.command = 'jsonsql'
|
9
|
+
self.arguments = '[JSON_FILE] ...'
|
10
|
+
|
11
|
+
def self.options
|
12
|
+
[
|
13
|
+
['--console', 'After all commands are run, open pry console with this data'],
|
14
|
+
['--save-to=[filename]', 'If set, sqlite3 db is left on disk at this path'],
|
15
|
+
['--table-name=[table]', 'Override the default table name (table)']
|
16
|
+
].concat(super)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(argv)
|
20
|
+
@jsons = []
|
21
|
+
|
22
|
+
while argument = argv.shift_argument
|
23
|
+
@jsons << argument
|
24
|
+
end
|
25
|
+
|
26
|
+
@console = argv.flag?('console', true)
|
27
|
+
@filename = argv.option('save-to') || ':memory:'
|
28
|
+
@table_name = argv.option('table-name') || 'table'
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate!
|
33
|
+
super
|
34
|
+
if @jsons.size == 0
|
35
|
+
help! "At least one JSON files is required."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
sequel = Sequel.sqlite(@filename)
|
41
|
+
importer = Importer.new(database: sequel, table_name: @table_name)
|
42
|
+
importer.import @jsons
|
43
|
+
|
44
|
+
if @console
|
45
|
+
importer.database.pry
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Jsonsql
|
5
|
+
class Importer
|
6
|
+
SEQUEL_SUPPORTED_CLASSES = [Integer, String, Fixnum, Bignum, Float, BigDecimal, Date, DateTime, Time, Numeric, TrueClass, FalseClass]
|
7
|
+
|
8
|
+
attr_reader :database, :table_name
|
9
|
+
|
10
|
+
def initialize(database: Sequel.sqlite, table_name: "table")
|
11
|
+
@table_name = table_name
|
12
|
+
@database = database
|
13
|
+
@table_created = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def table
|
17
|
+
@table ||= @database[table_name.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def import(files)
|
21
|
+
database.transaction do
|
22
|
+
files.each do |filename|
|
23
|
+
import_jsonfile(filename)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def import_jsonfile(filename)
|
29
|
+
row = JSON.parse(open(filename).read)
|
30
|
+
create_table_if_needed(row)
|
31
|
+
table.insert(row)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def class_supported?(clazz)
|
36
|
+
SEQUEL_SUPPORTED_CLASSES.include?(clazz)
|
37
|
+
end
|
38
|
+
|
39
|
+
# create a table using row data, if it has not been created
|
40
|
+
def create_table_if_needed(row)
|
41
|
+
unless @table_created
|
42
|
+
create_columns = columns_with_row(row)
|
43
|
+
database.create_table(table_name.to_sym) do
|
44
|
+
create_columns.each do |name, clazz|
|
45
|
+
column name.to_sym, clazz
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@table_created = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# find the columns of a table via a row of data
|
53
|
+
def columns_with_row(row)
|
54
|
+
columns = {}
|
55
|
+
row.each do |name, value|
|
56
|
+
clazz = value.class
|
57
|
+
if class_supported?(clazz)
|
58
|
+
columns[name] = value.class
|
59
|
+
else
|
60
|
+
columns[name] = String
|
61
|
+
end
|
62
|
+
end
|
63
|
+
columns
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Jsonsql
|
2
|
+
class Transformer
|
3
|
+
def initialize(&block)
|
4
|
+
@transformation = block
|
5
|
+
end
|
6
|
+
|
7
|
+
def transform(row)
|
8
|
+
self.instance_exec(row, &@transformation)
|
9
|
+
row
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.transformer_with_block(string)
|
13
|
+
block = eval(string)
|
14
|
+
Transformer.new(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
{
|
2
|
+
"id": 438931286992773120,
|
3
|
+
"text": "@twixhime 因為自「韓製列車」後,港鐵新列車都習慣以產地命名,例如「中國製列車 C-Train」,南港島綫的就是「南港島綫中國製列車 SIL C-Train」\n\n「中國製造」沒有特別含意,也不是臭名遠播,沒有大問題: http://t.co/Mx5gNUXV17",
|
4
|
+
"created_at": "2014-02-27 14:59:08 +0800",
|
5
|
+
"lang": "ja",
|
6
|
+
"reply_to": "TwixHime"
|
7
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helpers'
|
2
|
+
require 'date'
|
3
|
+
require 'sequel'
|
4
|
+
|
5
|
+
describe Jsonsql::Importer do
|
6
|
+
subject { Jsonsql::Importer.new }
|
7
|
+
|
8
|
+
context "#import_jsonfile" do
|
9
|
+
it "import one json file to db" do
|
10
|
+
subject.import_jsonfile("samples/mtr/437582112921640960.json")
|
11
|
+
|
12
|
+
expect(subject.table).to_not be_nil
|
13
|
+
expect(subject.table.count).to eq(1)
|
14
|
+
expected_row = {
|
15
|
+
:id => 437582112921640960,
|
16
|
+
:text => "@kaede19940908 圖片係港鐵官方的",
|
17
|
+
:created_at => "2014-02-23 21:38:00 +0800",
|
18
|
+
:lang => "zh",
|
19
|
+
:reply_to => "kaede19940908"
|
20
|
+
}
|
21
|
+
expect(subject.table.where(:id => 437582112921640960).to_a).to eq([expected_row])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "#import" do
|
26
|
+
it "should import all files given" do
|
27
|
+
expect(subject).to receive(:import_jsonfile).exactly(3).times
|
28
|
+
|
29
|
+
subject.import(["1", "2", "3"])
|
30
|
+
end
|
31
|
+
|
32
|
+
it "populate database after import" do
|
33
|
+
subject.import(Dir["samples/mtr/*.json"])
|
34
|
+
|
35
|
+
expect(subject.table).to_not be_nil
|
36
|
+
expect(subject.table.count).to eq(43)
|
37
|
+
expected_row = {
|
38
|
+
:id => 437582112921640960,
|
39
|
+
:text => "@kaede19940908 圖片係港鐵官方的",
|
40
|
+
:created_at => "2014-02-23 21:38:00 +0800",
|
41
|
+
:lang => "zh",
|
42
|
+
:reply_to => "kaede19940908"
|
43
|
+
}
|
44
|
+
expect(subject.table.where(:id => 437582112921640960).to_a).to eq([expected_row])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helpers'
|
2
|
+
require 'date'
|
3
|
+
require 'sequel'
|
4
|
+
|
5
|
+
describe Jsonsql::Transformer do
|
6
|
+
context "::new" do
|
7
|
+
it "create a transformer with block" do
|
8
|
+
transformer = Jsonsql::Transformer.new do |row|
|
9
|
+
row[:name] = row[:name].downcase if row[:name]
|
10
|
+
row
|
11
|
+
end
|
12
|
+
|
13
|
+
data = transformer.transform({:name => "Peter", :id => 1})
|
14
|
+
expect(data).to eq({:name => "peter", :id => 1})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "::transformer_with_block" do
|
19
|
+
it "create a transformer with block" do
|
20
|
+
transformer = Jsonsql::Transformer.transformer_with_block "
|
21
|
+
Proc.new { |row| row[:name] = row[:name].downcase if row[:name] }
|
22
|
+
"
|
23
|
+
data = transformer.transform({:name => "Peter", :id => 1})
|
24
|
+
expect(data).to eq({:name => "peter", :id => 1})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonsql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francis Chong
|
@@ -84,10 +84,70 @@ description: Allows you to easily execute SQL against and experiment group of JS
|
|
84
84
|
files.
|
85
85
|
email:
|
86
86
|
- francis@ignition.hk
|
87
|
-
executables:
|
87
|
+
executables:
|
88
|
+
- jsonsql
|
88
89
|
extensions: []
|
89
90
|
extra_rdoc_files: []
|
90
|
-
files:
|
91
|
+
files:
|
92
|
+
- ".gitignore"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/jsonsql
|
98
|
+
- jsonsql.gemspec
|
99
|
+
- jsonsql.gif
|
100
|
+
- lib/jsonsql.rb
|
101
|
+
- lib/jsonsql/command.rb
|
102
|
+
- lib/jsonsql/importer.rb
|
103
|
+
- lib/jsonsql/transformer.rb
|
104
|
+
- lib/jsonsql/version.rb
|
105
|
+
- samples/mtr/437582112921640960.json
|
106
|
+
- samples/mtr/437619123200086016.json
|
107
|
+
- samples/mtr/437741703663869953.json
|
108
|
+
- samples/mtr/437742060028719104.json
|
109
|
+
- samples/mtr/437745519050256384.json
|
110
|
+
- samples/mtr/437745801716985856.json
|
111
|
+
- samples/mtr/437750489242161153.json
|
112
|
+
- samples/mtr/437752084700467201.json
|
113
|
+
- samples/mtr/437752199980933120.json
|
114
|
+
- samples/mtr/437776429975994368.json
|
115
|
+
- samples/mtr/438102225232359424.json
|
116
|
+
- samples/mtr/438102443663314944.json
|
117
|
+
- samples/mtr/438104066649247744.json
|
118
|
+
- samples/mtr/438104276263784448.json
|
119
|
+
- samples/mtr/438106319539937280.json
|
120
|
+
- samples/mtr/438106591116922880.json
|
121
|
+
- samples/mtr/438106828455829505.json
|
122
|
+
- samples/mtr/438108309355511809.json
|
123
|
+
- samples/mtr/438118659513663488.json
|
124
|
+
- samples/mtr/438118752815972352.json
|
125
|
+
- samples/mtr/438126088913309696.json
|
126
|
+
- samples/mtr/438126258451275778.json
|
127
|
+
- samples/mtr/438127980003348480.json
|
128
|
+
- samples/mtr/438162980908175360.json
|
129
|
+
- samples/mtr/438169095335206912.json
|
130
|
+
- samples/mtr/438169291074965506.json
|
131
|
+
- samples/mtr/438182947787505664.json
|
132
|
+
- samples/mtr/438184226127486976.json
|
133
|
+
- samples/mtr/438184269517574145.json
|
134
|
+
- samples/mtr/438298854644256768.json
|
135
|
+
- samples/mtr/438376362844233729.json
|
136
|
+
- samples/mtr/438378012992475136.json
|
137
|
+
- samples/mtr/438484708301631488.json
|
138
|
+
- samples/mtr/438525303129128960.json
|
139
|
+
- samples/mtr/438525455046410241.json
|
140
|
+
- samples/mtr/438836995029090304.json
|
141
|
+
- samples/mtr/438837397577408512.json
|
142
|
+
- samples/mtr/438882017023762432.json
|
143
|
+
- samples/mtr/438885035861483520.json
|
144
|
+
- samples/mtr/438886437241364480.json
|
145
|
+
- samples/mtr/438923308999135232.json
|
146
|
+
- samples/mtr/438931286992773120.json
|
147
|
+
- samples/mtr/439026660629692416.json
|
148
|
+
- spec/importer_spec.rb
|
149
|
+
- spec/spec_helpers.rb
|
150
|
+
- spec/transformer_spec.rb
|
91
151
|
homepage: https://github.com/siuying/jsonsql
|
92
152
|
licenses:
|
93
153
|
- MIT
|
@@ -112,4 +172,7 @@ rubygems_version: 2.2.2
|
|
112
172
|
signing_key:
|
113
173
|
specification_version: 4
|
114
174
|
summary: Execute SQL against set of JSON files.
|
115
|
-
test_files:
|
175
|
+
test_files:
|
176
|
+
- spec/importer_spec.rb
|
177
|
+
- spec/spec_helpers.rb
|
178
|
+
- spec/transformer_spec.rb
|