module Relationizer::BigQuery
Constants
- DEFAULT_TYPES
- KNOWN_TYPES
Public Instance Methods
create_relation_literal(schema, tuples)
click to toggle source
# File lib/relationizer/big_query.rb, line 28 def create_relation_literal(schema, tuples) types = fixed_types(schema.values, tuples) _types_exp = types_exp(schema.keys, types) tuples_exp = tuples.map { |tuple| tuple.zip(types). map { |(col, type)| to_literal(col, type) }. join(", "). tap { |t| break "(#{t}#{', NULL' if tuple.length == 1})" } }.join(", ").tap { |t| break "[#{t}]"} select_exp = if schema.one? "#{schema.keys.first}" else '*' end "SELECT #{select_exp} FROM UNNEST(#{_types_exp}#{tuples_exp})" end
Private Instance Methods
array_type(array)
click to toggle source
# File lib/relationizer/big_query.rb, line 51 def array_type(array) classes = array.compact.map(&:class).uniq unless classes.length == 1 raise ReasonlessTypeError.new("Ambiguous type of element in array: #{classes}") end DEFAULT_TYPES[array.first] || :STRING end
empty_candidate_check(types)
click to toggle source
# File lib/relationizer/big_query.rb, line 74 def empty_candidate_check(types) raise ReasonlessTypeError.new("Candidate nothing") if types.empty? end
fixed_types(schema, tuples)
click to toggle source
# File lib/relationizer/big_query.rb, line 78 def fixed_types(schema, tuples) if tuples.empty? raise TypeNotFoundError unless schema.all? return schema end tuples.transpose.zip(schema.to_a).map { |values, type| next type if type if values.map { |o| o.is_a?(Array) }.all? types = values. map(&method(:array_type)).uniq. tap(&method(:empty_candidate_check)). tap(&method(:many_candidate_check)) next "ARRAY<#{types.first}>".to_sym end values. map(&DEFAULT_TYPES).compact.uniq. tap(&method(:empty_candidate_check)). tap(&method(:many_candidate_check)). first || :STRING } end
many_candidate_check(types)
click to toggle source
# File lib/relationizer/big_query.rb, line 70 def many_candidate_check(types) raise ReasonlessTypeError.new("Many candidate: #{types.join(', ')}") unless types.one? end
to_literal(obj, type)
click to toggle source
# File lib/relationizer/big_query.rb, line 104 def to_literal(obj, type) return "NULL" if obj.nil? case type when :ARRAY t = array_type(obj) obj.map { |e| to_literal(e, t) }.join(', ').tap { |s| break "[#{s}]"} when /^ARRAY\<.+\>$/ t = /^ARRAY\<(.+)\>$/.match(type).to_a&.dig(1).to_sym raise "Unknown type: #{t}" unless KNOWN_TYPES.include?(t) obj.map { |e| to_literal(e, t) }.join(', ').tap { |s| break "[#{s}]"} when :TIMESTAMP %Q{'#{obj.strftime('%Y-%m-%d %H:%M:%S')}'} when :STRING, :DATE obj.to_s.gsub(/'/, "\'").tap do |s| break "'#{s}'" end when :BOOL case obj when TrueClass, FalseClass obj else !!obj end when :FLOAT64 case obj when Float::INFINITY "CAST('inf' AS FLOAT64)" when -Float::INFINITY "CAST('-inf' AS FLOAT64)" else obj end when :INT64 obj.to_s else raise "Unknown type: #{type}" end end
types_exp(names, types)
click to toggle source
# File lib/relationizer/big_query.rb, line 61 def types_exp(names, types) case names.length when 1 %Q{ARRAY<STRUCT<`#{names.first}` #{types.first}, `___dummy` STRING>>} else %Q{ARRAY<STRUCT<#{names.zip(types).map { |(name, type)| "`#{name}` #{type}" }.join(", ")}>>} end end