yancya-big_query 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d5bd68e33c49a23f96f348b24d41aa9e2140af2
4
+ data.tar.gz: a4ae4adae7acf4754728e94ca31a9726239aa1ad
5
+ SHA512:
6
+ metadata.gz: dcae7d1b73287106727ac1ebbf5a4e0f344ad6f981c78686f4ae47de33cda2b93fbf36a0e108a6052b56ad763f1e1eed93bf9af891589aafa94cf8f37a653025
7
+ data.tar.gz: aa6af3940f7b669a3b00a727cc75638f550f1fa4690bbfffb83fee0d145fb7c95142963d74865dfe84f4f5dda11c229ebcf4ea238f6b3fe593593422ad203ba4
data/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
35
+
36
+ # IDEA config file
37
+ .idea
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # 0.0.2
2
+
3
+ * Can use streaming insert
4
+ * Add simple tests
5
+
6
+ # 0.0.1
7
+
8
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in big_query.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,80 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ big_query (0.0.2)
5
+ google-api-client
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.2.1)
11
+ i18n (~> 0.7)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.3, >= 0.3.4)
15
+ tzinfo (~> 1.1)
16
+ addressable (2.3.8)
17
+ autoparse (0.3.3)
18
+ addressable (>= 2.3.1)
19
+ extlib (>= 0.9.15)
20
+ multi_json (>= 1.0.0)
21
+ extlib (0.9.16)
22
+ faraday (0.9.1)
23
+ multipart-post (>= 1.2, < 3)
24
+ google-api-client (0.8.6)
25
+ activesupport (>= 3.2)
26
+ addressable (~> 2.3)
27
+ autoparse (~> 0.3)
28
+ extlib (~> 0.9)
29
+ faraday (~> 0.9)
30
+ googleauth (~> 0.3)
31
+ launchy (~> 2.4)
32
+ multi_json (~> 1.10)
33
+ retriable (~> 1.4)
34
+ signet (~> 0.6)
35
+ googleauth (0.4.1)
36
+ faraday (~> 0.9)
37
+ jwt (~> 1.4)
38
+ logging (~> 2.0)
39
+ memoist (~> 0.12)
40
+ multi_json (= 1.11)
41
+ signet (~> 0.6)
42
+ i18n (0.7.0)
43
+ json (1.8.3)
44
+ jwt (1.5.0)
45
+ launchy (2.4.3)
46
+ addressable (~> 2.3)
47
+ little-plugger (1.1.3)
48
+ logging (2.0.0)
49
+ little-plugger (~> 1.1)
50
+ multi_json (~> 1.10)
51
+ memoist (0.12.0)
52
+ minitest (5.7.0)
53
+ multi_json (1.11.0)
54
+ multipart-post (2.0.0)
55
+ power_assert (0.2.3)
56
+ rake (10.4.2)
57
+ retriable (1.4.1)
58
+ signet (0.6.1)
59
+ addressable (~> 2.3)
60
+ extlib (~> 0.9)
61
+ faraday (~> 0.9)
62
+ jwt (~> 1.5)
63
+ multi_json (~> 1.10)
64
+ test-unit (3.1.1)
65
+ power_assert
66
+ thread_safe (0.3.5)
67
+ tzinfo (1.2.2)
68
+ thread_safe (~> 0.1)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ big_query!
75
+ bundler (~> 1.6)
76
+ rake
77
+ test-unit
78
+
79
+ BUNDLED WITH
80
+ 1.10.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Shinta Koyanagi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # BigQuery
2
+
3
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/yancya/big_query?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
5
+ Google BigQuery API client library
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'big_query', github: "yancya/big_query"
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or build and install it yourself as:
18
+
19
+ $ git clone git@github.com:yancya/big_query.git
20
+ $ cd big_query
21
+ $ rake install
22
+
23
+ ## Usage
24
+
25
+ ```rb
26
+ bq = BigQuery.new(
27
+ key_path: "path_to_secret_key"
28
+ issuer: "mail@address"
29
+ )
30
+
31
+ job = bq.jobs.query(
32
+ project_id: "name_of_project",
33
+ sql: "select 1 as a, 2 as b, 3 as c"
34
+ )
35
+
36
+ begin
37
+ result = job.query_results
38
+ end until result["jobComplete"]
39
+
40
+ result["schema"]["fields"].map{|f| f["name"]}.join(",") #=> "a,b,c"
41
+ result["rows"].map{|row| row["f"].map{|col| col["v"]}.join(",")} #=> ["1,2,3"]
42
+ ```
43
+
44
+ ## Google BigQuery API Reference
45
+
46
+ https://developers.google.com/bigquery/docs/reference/v2/
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it ( https://github.com/yancya/big_query/fork )
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => :test
4
+
5
+ require "rake/testtask"
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "test"
9
+ t.test_files = Dir["test/**/test_*.rb"]
10
+ end
data/big_query.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'yancya/big_query/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "yancya-big_query"
8
+ spec.version = Yancya::BigQuery::VERSION
9
+ spec.authors = ["yancya"]
10
+ spec.email = ["yancya@upec.jp"]
11
+ spec.summary = %q{Google BigQuery API client library.}
12
+ spec.description = %q{Google BigQuery API client library. This is simple wrapper.}
13
+ spec.homepage = "https://github.com/yancya/big_query"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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_runtime_dependency "google-api-client", "~> 0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake", "~> 0"
25
+ spec.add_development_dependency "test-unit", "~> 0"
26
+ end
data/bin/big_query ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'big_query'
@@ -0,0 +1,31 @@
1
+ require_relative 'tables'
2
+
3
+ module Yancya
4
+ class BigQuery::Dataset
5
+ def initialize(resource:, bq:)
6
+ @resource = resource
7
+ @tables = BigQuery::Tables.new(bq: bq)
8
+ end
9
+
10
+ def tables
11
+ @tables.list(
12
+ project_id: project_id,
13
+ dataset_id: dataset_id
14
+ )
15
+ end
16
+
17
+ def project_id
18
+ dataset_reference["projectId"]
19
+ end
20
+
21
+ def dataset_id
22
+ dataset_reference["datasetId"]
23
+ end
24
+
25
+ private
26
+
27
+ def dataset_reference
28
+ @resource["datasetReference"]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,63 @@
1
+ require_relative 'initializer'
2
+ require_relative 'request_executor'
3
+
4
+ require_relative 'dataset'
5
+
6
+ module Yancya
7
+ class BigQuery::Datasets
8
+ include Initializer
9
+ include RequestExecutor
10
+
11
+ def delete(project_id:, dataset_id:)
12
+ execute(
13
+ api_method: @bq.api.datasets.delete,
14
+ parameters: {projectId: project_id, datasetId: dataset_id, deleteContents: true}
15
+ )
16
+ end
17
+
18
+ def get(project_id:, dataset_id:)
19
+ execute(
20
+ api_method: @bq.api.datasets.get,
21
+ parameters: {projectId: project_id, datasetId: dataset_id}
22
+ )
23
+ end
24
+
25
+ def insert(project_id:, dataset:)
26
+ execute(
27
+ api_method: @bq.api.datasets.insert,
28
+ parameters: {projectId: project_id},
29
+ body_object: dataset
30
+ )
31
+ end
32
+
33
+ def list(project_id:)
34
+ resources = execute(
35
+ api_method: @bq.api.datasets.list,
36
+ parameters: {projectId: project_id}
37
+ )
38
+
39
+ resources["datasets"].map{ |resource|
40
+ Yancya::BigQuery::Dataset.new(
41
+ resource: resource,
42
+ bq: @bq
43
+ )
44
+ }
45
+ end
46
+
47
+ def patch(project_id:, dataset_id:, dataset:)
48
+ execute(
49
+ api_method: @bq.api.datasets.patch,
50
+ parameters: {projectId: project_id, datasetId: dataset_id},
51
+ body_object: dataset
52
+ )
53
+ end
54
+
55
+ def update(project_id:, dataset_id:, dataset:)
56
+ execute(
57
+ api_method: @bq.api.datasets.update,
58
+ parameters: {projectId: project_id, datasetId: dataset_id},
59
+ body_object: dataset
60
+ )
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,9 @@
1
+ module Yancya
2
+ module Initializer
3
+ def self.included(_)
4
+ define_method(:initialize) do |bq:|
5
+ @bq = bq
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ module Yancya
2
+ class BigQuery::Job
3
+ def initialize(resource:, bq:)
4
+ @resource = resource
5
+ @jobs = BigQuery::Jobs.new(bq: bq)
6
+ end
7
+
8
+ def query_results
9
+ @jobs.get_query_results(
10
+ project_id: project_id,
11
+ job_id: job_id
12
+ )
13
+ end
14
+
15
+ def reload
16
+ @jobs.get(project_id: project_id, job_id: job_id)
17
+ end
18
+
19
+ def project_id
20
+ job_reference["projectId"]
21
+ end
22
+
23
+ def job_id
24
+ job_reference["jobId"]
25
+ end
26
+
27
+ def query
28
+ (configuration["query"]||{})["query"]
29
+ end
30
+
31
+ def state
32
+ status["state"]
33
+ end
34
+
35
+ def errors
36
+ status["errors"]
37
+ end
38
+
39
+ private
40
+
41
+ def configuration
42
+ @resource["configuration"]
43
+ end
44
+
45
+ def status
46
+ @resource["status"]
47
+ end
48
+
49
+ def job_reference
50
+ @resource["jobReference"]
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,61 @@
1
+ require 'json'
2
+
3
+ require_relative 'initializer'
4
+ require_relative 'request_executor'
5
+ require_relative 'job'
6
+
7
+ module Yancya
8
+ class BigQuery::Jobs
9
+ include Initializer
10
+ include RequestExecutor
11
+
12
+ def cancel(project_id:, job_id:)
13
+ execute(
14
+ api_method: @bq.api.jobs.cancel,
15
+ parameters: { projectId: project_id, jobId: job_id }
16
+ )
17
+ end
18
+
19
+ def get(project_id:, job_id:)
20
+ resource = execute(
21
+ api_method: @bq.api.jobs.get,
22
+ parameters: { projectId: project_id, jobId: job_id }
23
+ )
24
+
25
+ BigQuery::Job.new(resource: resource, bq: @bq)
26
+ end
27
+
28
+ def get_query_results(project_id:, job_id:)
29
+ execute(
30
+ api_method: @bq.api.jobs.get_query_results,
31
+ parameters: { projectId: project_id, jobId: job_id }
32
+ )
33
+ end
34
+
35
+ def insert(project_id:)
36
+ # TODO: https://developers.google.com/bigquery/docs/reference/v2/jobs/insert
37
+ raise "This method is not yet working"
38
+ end
39
+
40
+ def list(project_id:)
41
+ resources = execute(
42
+ api_method: @bq.api.jobs.list,
43
+ parameters: { projectId: project_id, projection: "full" }
44
+ )
45
+
46
+ resources["jobs"].map{|job|
47
+ BigQuery::Job.new(resource: job, bq: @bq)
48
+ }
49
+ end
50
+
51
+ def query(project_id:, sql:)
52
+ resource = execute(
53
+ api_method: @bq.api.jobs.query,
54
+ body_object: { query: sql },
55
+ parameters: { projectId: project_id }
56
+ )
57
+
58
+ BigQuery::Job.new(resource: resource, bq: @bq)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'jobs'
2
+ require_relative 'datasets'
3
+ require_relative 'request_executor'
4
+
5
+ module Yancya
6
+ class BigQuery::Project
7
+ include RequestExecutor
8
+
9
+ def initialize(resource:, bq:)
10
+ @resource = resource
11
+ @jobs = BigQuery::Jobs.new(bq: bq)
12
+ @datasets = BigQuery::Datasets.new(bq: bq)
13
+ @bq = bq
14
+ end
15
+
16
+ def query(sql)
17
+ @jobs.query(project_id: project_id, sql: sql)
18
+ end
19
+
20
+ def jobs
21
+ @jobs.list(project_id: project_id)
22
+ end
23
+
24
+ def datasets
25
+ @datasets.list(project_id: project_id)
26
+ end
27
+
28
+ def project_id
29
+ @resource["projectReference"]["projectId"]
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,21 @@
1
+ require_relative 'request_executor'
2
+ require_relative 'initializer'
3
+
4
+ require_relative 'project'
5
+
6
+ module Yancya
7
+ class BigQuery::Projects
8
+ include Initializer
9
+ include RequestExecutor
10
+
11
+ def list
12
+ resources = execute(
13
+ api_method: @bq.api.projects.list
14
+ )
15
+
16
+ resources["projects"].map do |resource|
17
+ BigQuery::Project.new(resource: resource, bq: @bq)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Yancya
2
+ module RequestExecutor
3
+ private
4
+
5
+ def response_to_json(obj)
6
+ return {} if obj.response.body.empty?
7
+ JSON.parse(obj.response.body).tap do |resource|
8
+ raise resource["error"].to_s if resource["error"]
9
+ break resource
10
+ end
11
+ end
12
+
13
+ def execute(api_method:, body_object: nil, parameters: nil)
14
+ response_to_json(
15
+ @bq.client.execute(
16
+ api_method: api_method,
17
+ body_object: body_object,
18
+ parameters: parameters
19
+ )
20
+ )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,68 @@
1
+ module Yancya
2
+ class BigQuery::Table
3
+ def initialize(resource:, tables:)
4
+ @resource = resource
5
+ @tables = tables
6
+ end
7
+
8
+ def project_id
9
+ table_reference["projectId"]
10
+ end
11
+
12
+ def dataset_id
13
+ table_reference["datasetId"]
14
+ end
15
+
16
+ def table_id
17
+ table_reference["tableId"]
18
+ end
19
+
20
+ def description
21
+ @resource["description"]
22
+ end
23
+
24
+ def schema
25
+ @resource["schema"]
26
+ end
27
+
28
+ def reload
29
+ @tables.get(
30
+ project_id: project_id,
31
+ dataset_id: dataset_id,
32
+ table_id: table_id
33
+ )
34
+ end
35
+
36
+ def delete
37
+ @tables.delete(
38
+ project_id: project_id,
39
+ dataset_id: dataset_id,
40
+ table_id: table_id
41
+ )
42
+ end
43
+
44
+ def patch(table_reference:)
45
+ @tables.patch(
46
+ project_id: project_id,
47
+ dataset_id: dataset_id,
48
+ table_id: table_id,
49
+ table: table_reference
50
+ )
51
+ end
52
+
53
+ def update(table_reference:)
54
+ @tables.update(
55
+ project_id: project_id,
56
+ dataset_id: dataset_id,
57
+ table_id: table_id,
58
+ table: table_reference
59
+ )
60
+ end
61
+
62
+ private
63
+ def table_reference
64
+ @resource["tableReference"]
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,37 @@
1
+ require_relative 'request_executor'
2
+
3
+ module Yancya
4
+ class BigQuery::Tabledata
5
+ include RequestExecutor
6
+
7
+ def initialize(project_id:, dataset_id:, table_id:, bq:)
8
+ @project_id = project_id
9
+ @dataset_id = dataset_id
10
+ @table_id = table_id
11
+ @bq = bq
12
+ end
13
+
14
+ def insert_all(rows)
15
+ execute(
16
+ api_method: @bq.api.tabledata.insert_all,
17
+ body_object: {rows: rows},
18
+ parameters: {
19
+ datasetId: @dataset_id,
20
+ projectId: @project_id,
21
+ tableId: @table_id
22
+ }
23
+ )
24
+ end
25
+
26
+ def list
27
+ execute(
28
+ api_method: @bq.api.tabledata.list,
29
+ parameters: {
30
+ datasetId: @dataset_id,
31
+ projectId: @project_id,
32
+ tableId: @table_id
33
+ }
34
+ )
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,90 @@
1
+ require_relative 'initializer'
2
+ require_relative 'request_executor'
3
+
4
+ require_relative 'table'
5
+
6
+ module Yancya
7
+ class BigQuery::Tables
8
+ include Initializer
9
+ include RequestExecutor
10
+
11
+ def delete(project_id:, dataset_id:, table_id:)
12
+ execute(
13
+ api_method: @bq.api.tables.delete,
14
+ parameters: {
15
+ datasetId: dataset_id,
16
+ projectId: project_id,
17
+ tableId: table_id,
18
+ }
19
+ )
20
+ end
21
+
22
+ def get(project_id:, dataset_id:, table_id:)
23
+ resource = execute(
24
+ api_method: @bq.api.tables.get,
25
+ parameters: {
26
+ datasetId: dataset_id,
27
+ projectId: project_id,
28
+ tableId: table_id,
29
+ }
30
+ )
31
+
32
+ BigQuery::Table.new(resource: resource, tables: self)
33
+ end
34
+
35
+ def insert(project_id:, dataset_id:, table:)
36
+ resource = execute(
37
+ api_method: @bq.api.tables.insert,
38
+ parameters: {
39
+ datasetId: dataset_id,
40
+ projectId: project_id,
41
+ },
42
+ body_object: table
43
+ )
44
+
45
+ BigQuery::Table.new(resource: resource, tables: self)
46
+ end
47
+
48
+ def list(project_id:, dataset_id:)
49
+ resources = execute(
50
+ api_method: @bq.api.tables.list,
51
+ parameters: {
52
+ datasetId: dataset_id,
53
+ projectId: project_id,
54
+ }
55
+ )
56
+
57
+ (resources["tables"]||[]).map do |resource|
58
+ BigQuery::Table.new(resource: resource, tables: self)
59
+ end
60
+ end
61
+
62
+ def patch(project_id:, dataset_id:, table_id:, table:)
63
+ resource = execute(
64
+ api_method: @bq.api.tables.patch,
65
+ parameters: {
66
+ datasetId: dataset_id,
67
+ projectId: project_id,
68
+ tableId: table_id,
69
+ },
70
+ body_object: table
71
+ )
72
+
73
+ BigQuery::Table.new(resource: resource, tables: self)
74
+ end
75
+
76
+ def update(project_id:, dataset_id:, table_id:, table:)
77
+ resource = execute(
78
+ api_method: @bq.api.tables.update,
79
+ parameters: {
80
+ datasetId: dataset_id,
81
+ projectId: project_id,
82
+ tableId: table_id,
83
+ },
84
+ body_object: table
85
+ )
86
+
87
+ BigQuery::Table.new(resource: resource, tables: self)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ module Yancya
2
+ class BigQuery
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,68 @@
1
+ require_relative "big_query/version"
2
+ require_relative "big_query/datasets"
3
+ require_relative "big_query/jobs"
4
+ require_relative "big_query/projects"
5
+ require_relative "big_query/tabledata"
6
+ require_relative "big_query/tables"
7
+
8
+ require 'google/api_client'
9
+
10
+ module Yancya
11
+ class BigQuery
12
+ attr_reader :client
13
+
14
+ BQ = Struct.new(:client) do
15
+ def api
16
+ client.discovered_api("bigquery", "v2")
17
+ end
18
+ end
19
+
20
+ def initialize(key_path:,
21
+ issuer:,
22
+ application_name: "github.com/yancya/big_query",
23
+ application_version: BigQuery::VERSION)
24
+
25
+ app_info = {
26
+ application_name: application_name,
27
+ application_version: application_version
28
+ }
29
+
30
+ client = Google::APIClient.new(app_info)
31
+
32
+ asserter = Google::APIClient::JWTAsserter.new(
33
+ issuer,
34
+ "https://www.googleapis.com/auth/bigquery",
35
+ Google::APIClient::PKCS12.load_key(File.open(key_path), "notasecret")
36
+ )
37
+
38
+ client.authorization = asserter.authorize
39
+
40
+ @bq = BQ.new(client)
41
+ end
42
+
43
+ def datasets
44
+ Datasets.new(bq: @bq)
45
+ end
46
+
47
+ def jobs
48
+ Jobs.new(bq: @bq)
49
+ end
50
+
51
+ def projects
52
+ Projects.new(bq: @bq)
53
+ end
54
+
55
+ def tabledata(project_id:, dataset_id:, table_id:)
56
+ Tabledata.new(
57
+ project_id: project_id,
58
+ dataset_id: dataset_id,
59
+ table_id: table_id,
60
+ bq: @bq
61
+ )
62
+ end
63
+
64
+ def tables
65
+ Tables.new(bq: @bq)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,176 @@
1
+ require 'test-unit'
2
+ require 'pp'
3
+ require_relative '../lib/yancya/big_query'
4
+
5
+ class TestBigQuery < Test::Unit::TestCase
6
+ TEST_DATASET_ID = "test_dataset_for_yancya_big_query_gem"
7
+ TEST_DATASET_ID_MODIFIED = "test_dataset_for_yancya_big_query_gem_"
8
+ TEST_TABLE_ID = "test_table"
9
+ TEST_TABLE_INFO = {
10
+ schema: {
11
+ fields: [
12
+ {name: "column_s", type: "STRING"},
13
+ {name: "column_i", type: "INTEGER"},
14
+ {name: "column_f", type: "FLOAT"},
15
+ {name: "column_b", type: "BOOLEAN"}
16
+ ]
17
+ },
18
+ tableReference: {
19
+ tableId: TEST_TABLE_ID
20
+ }
21
+ }
22
+
23
+ setup do
24
+ @bq = Yancya::BigQuery.new(
25
+ key_path: ENV["GCP_KEY_PATH"],
26
+ issuer: ENV["GCP_ISSUER"]
27
+ )
28
+
29
+ @project_id = ENV["BQ_PROJECT_ID"]
30
+
31
+ if @bq.datasets.list(project_id: @project_id).map{ |ds| ds.dataset_id }.include? TEST_DATASET_ID
32
+ @bq.datasets.delete(project_id: @project_id, dataset_id: TEST_DATASET_ID)
33
+ end
34
+
35
+ dataset = {
36
+ datasetReference: {
37
+ datasetId: TEST_DATASET_ID
38
+ }
39
+ }
40
+
41
+ @bq.datasets.insert(project_id: @project_id, dataset: dataset)
42
+ end
43
+
44
+ teardown do
45
+ @bq.datasets.delete(project_id: @project_id, dataset_id: TEST_DATASET_ID)
46
+ end
47
+
48
+ test "get dataset" do
49
+ dataset = @bq.
50
+ datasets.
51
+ get(
52
+ project_id: @project_id,
53
+ dataset_id: TEST_DATASET_ID
54
+ )["datasetReference"]
55
+
56
+ assert { TEST_DATASET_ID == dataset["datasetId"] }
57
+ end
58
+
59
+ test "jobs list" do
60
+ job_list = @bq.jobs.list(project_id: @project_id)
61
+ assert { job_list.is_a? Array }
62
+ end
63
+
64
+ test "get job" do
65
+ job_id = @bq.jobs.list(project_id: @project_id).last.job_id
66
+ assert do
67
+ job_id == @bq.jobs.get(project_id: @project_id, job_id: job_id).job_id
68
+ end
69
+ end
70
+
71
+ test "project list" do
72
+ assert do
73
+ @bq.projects.list.map{ |project| project.project_id }.include? @project_id
74
+ end
75
+ end
76
+
77
+ test "select without table" do
78
+ result = execute_query("select 1 as a, 2 as b, 3 as c")
79
+
80
+ assert do
81
+ "1,2,3" == result["rows"].map{|row| row["f"].map{|col| col["v"]}.join(",")}.first
82
+ end
83
+ end
84
+
85
+ test "create table" do
86
+ result = create_table
87
+
88
+ assert { TEST_TABLE_ID == result.table_id }
89
+ end
90
+
91
+ test "insert_all data" do
92
+ create_table
93
+
94
+ table_data = @bq.tabledata(
95
+ project_id: @project_id,
96
+ dataset_id: TEST_DATASET_ID,
97
+ table_id: TEST_TABLE_ID
98
+ )
99
+
100
+ rows = [{ json: { column_s: "hoge", column_i: 1, column_f: 0.1, column_b: false } }]
101
+
102
+ assert { table_data.insert_all(rows)["insertErrors"].nil? }
103
+ assert { table_data.list["totalRows"] }
104
+ end
105
+
106
+ test "table list" do
107
+ create_table
108
+
109
+ assert { 1 == @bq.tables.list(project_id: @project_id, dataset_id: TEST_DATASET_ID).size }
110
+ end
111
+
112
+ test "get table"do
113
+ create_table
114
+
115
+ table = @bq.tables.get(project_id: @project_id, dataset_id: TEST_DATASET_ID, table_id: TEST_TABLE_ID)
116
+
117
+ assert { TEST_TABLE_ID == table.table_id }
118
+ end
119
+
120
+ test "delete table" do
121
+ table = create_table
122
+ @bq.tables.delete(project_id: @project_id, dataset_id: TEST_DATASET_ID, table_id: table.table_id)
123
+
124
+ assert { @bq.tables.list(project_id: @project_id, dataset_id: TEST_DATASET_ID).empty? }
125
+ end
126
+
127
+ test "patch table" do
128
+ create_table
129
+
130
+ table = @bq.tables.patch(
131
+ project_id: @project_id,
132
+ dataset_id: TEST_DATASET_ID,
133
+ table_id: TEST_TABLE_ID,
134
+ table: {
135
+ description: "hello world"
136
+ }
137
+ )
138
+
139
+ assert { "hello world" == table.description }
140
+ end
141
+
142
+ test "update table" do
143
+ schema = create_table.schema
144
+
145
+ table = @bq.tables.update(
146
+ project_id: @project_id,
147
+ dataset_id: TEST_DATASET_ID,
148
+ table_id: TEST_TABLE_ID,
149
+ table: {
150
+ schema: schema.tap { |hash| hash["fields"] << { name: "hoge", type: "STRING" }; break hash }
151
+ }
152
+ )
153
+
154
+ assert { table.schema["fields"].map { |field| field["name"] }.include? "hoge" }
155
+ end
156
+
157
+ private
158
+
159
+ def create_table
160
+ @bq.tables.insert(
161
+ project_id: @project_id,
162
+ dataset_id: TEST_DATASET_ID,
163
+ table: TEST_TABLE_INFO
164
+ )
165
+ end
166
+
167
+ def execute_query(sql)
168
+ job = @bq.jobs.query(project_id: @project_id, sql: sql)
169
+
170
+ begin
171
+ result = job.query_results
172
+ end until result["jobComplete"]
173
+
174
+ result
175
+ end
176
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yancya-big_query
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - yancya
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: google-api-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Google BigQuery API client library. This is simple wrapper.
70
+ email:
71
+ - yancya@upec.jp
72
+ executables:
73
+ - big_query
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - CHANGELOG.md
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - big_query.gemspec
85
+ - bin/big_query
86
+ - lib/yancya/big_query.rb
87
+ - lib/yancya/big_query/dataset.rb
88
+ - lib/yancya/big_query/datasets.rb
89
+ - lib/yancya/big_query/initializer.rb
90
+ - lib/yancya/big_query/job.rb
91
+ - lib/yancya/big_query/jobs.rb
92
+ - lib/yancya/big_query/project.rb
93
+ - lib/yancya/big_query/projects.rb
94
+ - lib/yancya/big_query/request_executor.rb
95
+ - lib/yancya/big_query/table.rb
96
+ - lib/yancya/big_query/tabledata.rb
97
+ - lib/yancya/big_query/tables.rb
98
+ - lib/yancya/big_query/version.rb
99
+ - test/test_big_query.rb
100
+ homepage: https://github.com/yancya/big_query
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.4.5
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Google BigQuery API client library.
124
+ test_files:
125
+ - test/test_big_query.rb