snowflake_rb 0.0.0
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 +7 -0
- data/ext/snowflake-darwin-amd64.so +0 -0
- data/ext/snowflake-darwin-arm64.so +0 -0
- data/ext/snowflake-linux-amd64.so +0 -0
- data/ext/snowflake-linux-arm64.so +0 -0
- data/ext/snowflake.so +0 -0
- data/lib/snowflake_rb/configuration.rb +18 -0
- data/lib/snowflake_rb/extension.rb +31 -0
- data/lib/snowflake_rb.rb +164 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f52d1d74097341acc40cf111a11d5ab1bf403eb59e14dbf0405b78fa4a51d067
|
4
|
+
data.tar.gz: e1fde37704e432fb3ec95825b51c57490e8535f303a9891ece31bc0545187feb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 81351cbcddcedc5228d22689e7d6bce667a57cf4640e50286da04c91c6feaa00f5c2747d3cc3264ef1238c8f0270045232c9c03d53d70ff16da958bdf3c62ba7
|
7
|
+
data.tar.gz: cfba487d85753ae881613ff6daf91c0d0713d409d93f8f09eb0f45e46258709152a0f360d0efb5f15d39aa0b3548e503f92dba1df34b79b18108167f90d878cd
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/ext/snowflake.so
ADDED
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry-configurable'
|
4
|
+
|
5
|
+
module SnowflakeRB
|
6
|
+
module Configuration
|
7
|
+
extend Dry::Configurable
|
8
|
+
|
9
|
+
setting :account
|
10
|
+
setting :warehouse
|
11
|
+
setting :database
|
12
|
+
setting :schema
|
13
|
+
setting :user
|
14
|
+
setting :password
|
15
|
+
setting :role
|
16
|
+
setting :port, default: 443
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SnowflakeRB
|
4
|
+
module Extension
|
5
|
+
def self.env_specific_extension_path
|
6
|
+
"../ext/snowflake-#{os}-#{arch}.so"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.os
|
10
|
+
case RUBY_PLATFORM
|
11
|
+
when /.*linux.*/
|
12
|
+
'linux'
|
13
|
+
when /.*darwin.*/
|
14
|
+
'darwin'
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.arch
|
21
|
+
case RUBY_PLATFORM
|
22
|
+
when /.*x86_64.*/
|
23
|
+
'amd64'
|
24
|
+
when /.*arm64.*/
|
25
|
+
'arm64'
|
26
|
+
else
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/snowflake_rb.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'snowflake_rb/extension'
|
3
|
+
require 'snowflake_rb/configuration'
|
4
|
+
|
5
|
+
# Note: this library is not thread safe as it caches the last error
|
6
|
+
# The call pattern expectation is to call last_error after any call which may have gotten an error. If last_error is
|
7
|
+
# `nil`, there was no error.
|
8
|
+
module Snowflake
|
9
|
+
module LibC
|
10
|
+
extend FFI::Library
|
11
|
+
ffi_lib(FFI::Library::LIBC)
|
12
|
+
|
13
|
+
attach_function(:free, [:pointer], :void)
|
14
|
+
end
|
15
|
+
|
16
|
+
module Binding
|
17
|
+
extend FFI::Library
|
18
|
+
|
19
|
+
POINTER_SIZE = FFI.type_size(:pointer)
|
20
|
+
|
21
|
+
ffi_lib(File.expand_path(SnowflakeRB::Extension.env_specific_extension_path, __dir__))
|
22
|
+
attach_function(:last_error, 'LastError', [], :strptr)
|
23
|
+
# ugh, `port` in gosnowflake is just :int; however, ruby - ffi -> go is passing 32bit int if I just decl :int.
|
24
|
+
attach_function(:connect, 'Connect', %i[string string string string string string string int64], :pointer)
|
25
|
+
attach_function(:close, 'Close', [:pointer], :void)
|
26
|
+
attach_function(:exec, 'Exec', %i[pointer string], :int64)
|
27
|
+
attach_function(:fetch, 'Fetch', %i[pointer string], :pointer)
|
28
|
+
attach_function(:next_row, 'NextRow', [:pointer], :pointer)
|
29
|
+
attach_function(:query_columns, 'QueryColumns', [:pointer], :pointer)
|
30
|
+
attach_function(:query_column_count, 'QueryColumnCount', [:pointer], :int32)
|
31
|
+
end
|
32
|
+
|
33
|
+
module Client
|
34
|
+
extend SnowflakeRB::Configuration
|
35
|
+
module_function
|
36
|
+
|
37
|
+
# @return String last error or nil. May be end of file which is not really an error
|
38
|
+
def last_error
|
39
|
+
error, cptr = ::Snowflake::Binding.last_error
|
40
|
+
LibC.free(cptr) if error
|
41
|
+
error
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param account[String] should include everything in the db url ahead of 'snowflakecomputing.com'
|
45
|
+
# @param port[Integer]
|
46
|
+
# @return query_object[Pointer] a pointer to use for subsequent calls not inspectable nor viewable by Ruby
|
47
|
+
def connect(
|
48
|
+
account = nil,
|
49
|
+
warehouse = nil,
|
50
|
+
database = nil,
|
51
|
+
schema = nil,
|
52
|
+
user = nil,
|
53
|
+
password = nil,
|
54
|
+
role = nil,
|
55
|
+
port = nil
|
56
|
+
)
|
57
|
+
::Snowflake::Binding.connect(
|
58
|
+
account || config.account,
|
59
|
+
warehouse || config.warehouse,
|
60
|
+
database || config.database,
|
61
|
+
schema || config.schema,
|
62
|
+
user || config.user,
|
63
|
+
password || config.password,
|
64
|
+
role || config.role,
|
65
|
+
port || config.port
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param db_pointer[Pointer] the pointer which `connect` returned.
|
70
|
+
def close(db_pointer)
|
71
|
+
::Snowflake::Binding.close(db_pointer)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param db_pointer[Pointer] the pointer which `connect` returned.
|
75
|
+
# @param statement[String] an executable query which should return number of rows affected
|
76
|
+
# @return rowcount[Number] number of rows or nil if there was an error
|
77
|
+
def exec(db_pointer, statement)
|
78
|
+
count = ::Snowflake::Binding.exec(db_pointer, statement) # returns -1 for error
|
79
|
+
count >= 0 ? count : nil
|
80
|
+
end
|
81
|
+
|
82
|
+
# Send a query and then yield each row as an array of strings to the given block
|
83
|
+
# @param db_pointer[Pointer] the pointer which `connect` returned.
|
84
|
+
# @param query[String] a select query to run.
|
85
|
+
# @return error_string
|
86
|
+
# @yield List<String>
|
87
|
+
def select(db_pointer, sql, field_count: nil)
|
88
|
+
return 'db_pointer not initialized' unless db_pointer
|
89
|
+
return to_enum(__method__, db_pointer, sql) unless block_given?
|
90
|
+
|
91
|
+
query_pointer = fetch(db_pointer, sql)
|
92
|
+
return last_error if query_pointer.nil? || query_pointer == FFI::Pointer::NULL
|
93
|
+
|
94
|
+
field_count ||= column_count(query_pointer)
|
95
|
+
loop do
|
96
|
+
row = get_next_row(query_pointer, field_count)
|
97
|
+
return last_error unless row
|
98
|
+
|
99
|
+
yield row
|
100
|
+
end
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
# @param db_pointer[Pointer] the pointer which `connect` returned.
|
105
|
+
# @param query[String] a select query to run.
|
106
|
+
# @return query_object[Pointer] a pointer to use for subsequent calls not inspectable nor viewable by Ruby; however,
|
107
|
+
# if it's `nil`, check `last_error`
|
108
|
+
def fetch(db_pointer, query)
|
109
|
+
::Snowflake::Binding.fetch(db_pointer, query)
|
110
|
+
end
|
111
|
+
|
112
|
+
# @param query_object[Pointer] the pointer which `fetch` returned. Go will gc this object when the query is done; so,
|
113
|
+
# don't expect to reference it after the call which returned `nil`
|
114
|
+
# @param field_count[Integer] column count: it will seg fault if you provide a number greater than the actual number.
|
115
|
+
# Using code should use wrap this in something like
|
116
|
+
#
|
117
|
+
# @return [List<String>] the column values in order
|
118
|
+
def get_next_row(query_object, field_count)
|
119
|
+
raw_row = ::Snowflake::Binding.next_row(query_object)
|
120
|
+
return nil if raw_row.nil? || raw_row == FFI::Pointer::NULL
|
121
|
+
|
122
|
+
raw_row.get_array_of_pointer(0, field_count).map do |cstr|
|
123
|
+
if cstr == FFI::Pointer::NULL || cstr.nil?
|
124
|
+
nil
|
125
|
+
else
|
126
|
+
str = cstr.read_string
|
127
|
+
LibC.free(cstr)
|
128
|
+
str
|
129
|
+
end
|
130
|
+
end
|
131
|
+
ensure
|
132
|
+
LibC.free(raw_row) if raw_row
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param query_object[Pointer] the pointer which `fetch` returned.
|
136
|
+
# @return [List<String>] the column values in order
|
137
|
+
def column_names(query_object, field_count = nil)
|
138
|
+
raw_row = ::Snowflake::Binding.query_columns(query_object)
|
139
|
+
return nil if raw_row.nil? || raw_row == FFI::Pointer::NULL
|
140
|
+
|
141
|
+
raw_row.get_array_of_pointer(0, field_count).map do |cstr|
|
142
|
+
if cstr == FFI::Pointer::NULL || cstr.nil?
|
143
|
+
nil
|
144
|
+
else
|
145
|
+
str = cstr.read_string
|
146
|
+
LibC.free(cstr)
|
147
|
+
str
|
148
|
+
end
|
149
|
+
end
|
150
|
+
ensure
|
151
|
+
LibC.free(raw_row) if raw_row
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param query_object[Pointer] the pointer which `fetch` returned.
|
155
|
+
def column_count(query_object)
|
156
|
+
::Snowflake::Binding.query_column_count(query_object)
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [Dry::Configurable::Config] configuration for the gem.
|
160
|
+
def config
|
161
|
+
SnowflakeRB::Configuration.config
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snowflake_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Darren Cheng
|
8
|
+
- Arjun Krishnan
|
9
|
+
- Mohammad-Reza
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2023-04-12 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ffi
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.15.5
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 1.15.5
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: dry-configurable
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.0.1
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.0.1
|
43
|
+
description: This gem adds a ruby wrapper around the go native snowflake client
|
44
|
+
email:
|
45
|
+
- darren@thanx.com
|
46
|
+
- arjun@thanx.com
|
47
|
+
- mohammad-reza@thanx.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- ext/snowflake-darwin-amd64.so
|
53
|
+
- ext/snowflake-darwin-arm64.so
|
54
|
+
- ext/snowflake-linux-amd64.so
|
55
|
+
- ext/snowflake-linux-arm64.so
|
56
|
+
- ext/snowflake.so
|
57
|
+
- lib/snowflake_rb.rb
|
58
|
+
- lib/snowflake_rb/configuration.rb
|
59
|
+
- lib/snowflake_rb/extension.rb
|
60
|
+
homepage: https://github.com/thanx/snowflake-rb
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.1.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Ruby wrapper for go native snowflake client
|
83
|
+
test_files: []
|