Class: Webhookdb::Snowflake
- Inherits:
-
Object
- Object
- Webhookdb::Snowflake
- Includes:
- Appydays::Configurable, Appydays::Loggable
- Defined in:
- lib/webhookdb/snowflake.rb
Class Method Summary collapse
-
._parse_json(stdout) ⇒ Object
We can’t parse newline delimited json easily, so split it ourselves and parse each document.
-
.parse_url_to_cli_args(url, format: "json") ⇒ Object
Given a Snowflake URL, return the command line args.
- .run_cli(url, query, parse: false, format: "json") ⇒ Object
Class Method Details
._parse_json(stdout) ⇒ Object
We can’t parse newline delimited json easily, so split it ourselves and parse each document.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/webhookdb/snowflake.rb', line 73 def self._parse_json(stdout) docs = stdout.split("]\n[") result = docs.each_with_index.map do |j, i| if docs.size > 1 if i.zero? j += "]" else j = "[" + j end end Oj.load(j.strip) end return result rescue StandardError => e msg = "error: #{e}, stdout: #{stdout}" raise Webhookdb::InvalidPostcondition, "Error parsing snowsql output: #{msg}" end |
.parse_url_to_cli_args(url, format: "json") ⇒ Object
Given a Snowflake URL, return the command line args. Args for the commandline can be traditional URL pieces (host -> account, user/password, etc), or passed as query params. Rules are:
-
Any query param exactly matching accountname/username/dbname/schemaname/rolename/warehouse is used.
-
Any query param matching account/user/db/schema/role is used.
-
URI hostname is used as accountname, basic auth user as username, and uri path as dbname.
-
Password is pulled from query param ‘password’ or uri basic auth password.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/webhookdb/snowflake.rb', line 25 def self.parse_url_to_cli_args(url, format: "json") uri = URI(url) params = Rack::Utils.parse_query(uri.query) password = params["password"] || uri.password raise ArgumentError, "must provide password in uri basic auth or query params" if password.blank? cli = [ self.snowsql, "-o", "friendly=false", "-o", "output_format=#{format}", "-o", "timing=false", "--accountname", params["accountname"] || params["account"] || uri.hostname || "", "--username", params["username"] || params["user"] || uri.user || "", "--dbname", params["dbname"] || params["db"] || uri.path&.delete_prefix("/") || "", ] raise ArgumentError, "url requires account (host), user, and db (or uri path): #{url}" if cli.include?("") if (schemaname = params["schemaname"] || params["schema"]).present? cli.push("--schemaname", schemaname) end if (rolename = params["rolename"] || params["role"]).present? cli.push("--rolename", rolename) end cli.push("--warehouse", params["warehouse"]) if params["warehouse"].present? return cli, {"SNOWSQL_PWD" => password} end |
.run_cli(url, query, parse: false, format: "json") ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/webhookdb/snowflake.rb', line 51 def self.run_cli(url, query, parse: false, format: "json") args, env = self.parse_url_to_cli_args(url, format:) args.push("-q", query) stdout, stderr, status = Open3.capture3(env, *args) if stderr.blank? && status.success? result = if parse.respond_to?(:call) parse.call(stdout) elsif parse && format == "json" self._parse_json(stdout) else stdout end return result end self.logger.error("snowflake_error", stdout:, stderr:, status:, cli_args: args) msg = "status: #{status}, stderr: #{stderr}, stdout: #{stdout}, query: #{query}" raise Webhookdb::InvalidPostcondition, "snowflake failed: #{msg}" end |