parent
0463bf036e
commit
91c0abc74c
@ -0,0 +1,94 @@
|
||||
require 'carto/connector/provider'
|
||||
|
||||
class DummyConnectorProvider < Carto::Connector::Provider
|
||||
metadata id: 'dummy', name: 'Dummy'
|
||||
required_parameters %I(table req1 req2)
|
||||
optional_parameters %I(opt1 opt2)
|
||||
|
||||
@copies = []
|
||||
def self.copies
|
||||
@copies
|
||||
end
|
||||
|
||||
@error_message = nil
|
||||
def self.failing_with(msg)
|
||||
prev = @error_message
|
||||
@error_message = msg
|
||||
yield
|
||||
@error_message = prev
|
||||
end
|
||||
def self.error_message
|
||||
@error_message
|
||||
end
|
||||
|
||||
DEFAULT_FEATURES = {
|
||||
'sql_queries': false,
|
||||
'list_databases': false,
|
||||
'list_tables': true,
|
||||
'preview_table': false,
|
||||
'dry_run': false,
|
||||
'list_projects': false
|
||||
}
|
||||
|
||||
def copy_table(schema_name:, table_name:, limits: {})
|
||||
validate!
|
||||
raise self.class.error_message if self.class.error_message
|
||||
self.class.copies << [schema_name, table_name, limits]
|
||||
@connector_context.execute_in_user_database "CREATE TABLE #{schema_name}.#{table_name}()"
|
||||
end
|
||||
|
||||
def check_connection
|
||||
self.class.error_message ? false : true
|
||||
end
|
||||
|
||||
def table_name
|
||||
@params[:table]
|
||||
end
|
||||
|
||||
def remote_data_updated?
|
||||
true
|
||||
end
|
||||
|
||||
def list_tables(limits: {})
|
||||
must_be_defined_in_derived_class unless features_information[:list_tables]
|
||||
[{schema:'s1', name: 't1'}, {schema:'s2', name: 't2'}]
|
||||
end
|
||||
|
||||
def list_databases()
|
||||
must_be_defined_in_derived_class unless features_information[:list_databases]
|
||||
['db1', 'db2']
|
||||
end
|
||||
|
||||
def list_projects()
|
||||
must_be_defined_in_derived_class unless features_information[:list_projects]
|
||||
[{id: 'project-1', friendly_name: 'Project 1'}, {id: 'project-2', friendly_name: 'Project 2'}]
|
||||
end
|
||||
|
||||
def list_project_datasets(project_id)
|
||||
must_be_defined_in_derived_class unless features_information[:list_projects]
|
||||
[{id: 'data-1', qualified_name: "#{project_id}.data-1"}, {id: 'data-2', qualified_name: "#{project_id}.data-2"}]
|
||||
end
|
||||
|
||||
def list_project_dataset_tables(project_id, dataset_id)
|
||||
must_be_defined_in_derived_class unless features_information[:list_projects]
|
||||
[{id: 't-1', qualified_name: "#{project_id}.#{dataset_id}.t-1"}, {id: 't-2', qualified_name: "#{project_id}.#{dataset_id}.t-2"}]
|
||||
end
|
||||
|
||||
def dry_run
|
||||
must_be_defined_in_derived_class unless features_information[:dry_run]
|
||||
raise self.class.error_message if self.class.error_message
|
||||
{dry_run_results: '...'}
|
||||
end
|
||||
|
||||
def features_information
|
||||
DEFAULT_FEATURES
|
||||
end
|
||||
end
|
||||
|
||||
def dummy_connector_provider_with_id(id, name=nil, features=DummyConnectorProvider::DEFAULT_FEATURES)
|
||||
Class.new(DummyConnectorProvider) do
|
||||
metadata id: id, name: name || id
|
||||
@copies = []
|
||||
define_method(:features_information){ features }
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
@ -1,126 +0,0 @@
|
||||
def match_sql_command(sql)
|
||||
options_pattern = %q{
|
||||
(?:\s+OPTIONS\s*\((?<options>
|
||||
(?:
|
||||
\s*
|
||||
(?:\"(?:[^\"]+)\"|(?:[^\s]+))
|
||||
\s+
|
||||
(?:\'(?:[^\']*)\'|(?:[^\'].+))
|
||||
)*
|
||||
\s*
|
||||
)\))?
|
||||
}
|
||||
patterns = {
|
||||
create_server: %r{
|
||||
CREATE\s+SERVER\s+(?<server_name>[^\s]+)
|
||||
\s+
|
||||
FOREIGN\s+DATA\s+WRAPPER\s+(?<fdw_name>[^\s]+)
|
||||
#{options_pattern}
|
||||
}xi,
|
||||
create_user_mapping: %r{
|
||||
CREATE\s+USER\s+MAPPING\s+FOR\s+\"?(?<user_name>[^\s\"]+)\"?
|
||||
\s+
|
||||
SERVER\s+(?<server_name>[^\s]+)
|
||||
#{options_pattern}
|
||||
}xi,
|
||||
import_foreign_schema: %r{
|
||||
IMPORT\s+FOREIGN\s+SCHEMA\s+\"?(?<remote_schema_name>[^\s\"]+)\"?
|
||||
\s+
|
||||
FROM\s+SERVER\s+(?<server_name>[^\s]+)
|
||||
\s+
|
||||
INTO\s+\"?(?<schema_name>[^\s\"]+)\"?
|
||||
#{options_pattern}
|
||||
}xi,
|
||||
import_foreign_schema_limited: %r{
|
||||
IMPORT\s+FOREIGN\s+SCHEMA\s+\"?(?<remote_schema_name>[^\s\"]+)\"?
|
||||
\s+
|
||||
LIMIT\s+TO\s+\((?<limited_to>.+)\)
|
||||
\s+
|
||||
FROM\s+SERVER\s+(?<server_name>[^\s]+)
|
||||
\s+
|
||||
INTO\s+\"?(?<schema_name>[^\s\"]+)\"?
|
||||
#{options_pattern}
|
||||
}xi,
|
||||
create_foreign_table: %r{
|
||||
CREATE\+FOREIGN\+TABLE\s+(?<table_name>.+)\s*\((?<columns>.+)\)
|
||||
\s+
|
||||
SERVER\s+(?<server_name>[^\s]+)
|
||||
#{options_pattern}
|
||||
}xi,
|
||||
grant_select: %r{
|
||||
GRANT\s+SELECT\s+ON\s+(?<table_name>[^\s]+)\s+TO\s+\"?(?<user_name>[^\s\"]+)\"?
|
||||
}xi,
|
||||
create_table_as_select: %r{
|
||||
CREATE\s+TABLE\s+(?<table_name>[^\s]+)\s+AS\s+SELECT\s+(?<select>.+)(?:\s+LIMIT\s+(?<limit>\d+))?
|
||||
}xi,
|
||||
drop_foreign_table_if_exists: %r{
|
||||
DROP\s+FOREIGN\s+TABLE\s+IF\s+EXISTS\s+(?<table_name>[^\s]+)(?:\s+(?<cascade>CASCADE))?
|
||||
}xi,
|
||||
drop_server_if_exists: %r{
|
||||
DROP\s+SERVER\s+IF\s+EXISTS\s+(?<server_name>[^\s]+)(?:\s+(?<cascade>CASCADE))?
|
||||
}xi,
|
||||
drop_usermapping_if_exists: %r{
|
||||
DROP\s+USER\s+MAPPING\s+IF\s+EXISTS\s+FOR\s+\"?(?<user_name>[^\s\"]+)\"?\s+SERVER\s+(?<server_name>[^\s]+)
|
||||
}xi,
|
||||
rename_foreign_table: %r{
|
||||
ALTER\s+FOREIGN\s+TABLE\s+(?<table_name>.+)\s+RENAME\s+TO\s+(?<new_name>.+)
|
||||
}xi,
|
||||
select_all: %r{
|
||||
SELECT\s+\*\s+FROM\s+(?<from>.+)
|
||||
}xi
|
||||
}
|
||||
option_pair = %r{
|
||||
\A\s*
|
||||
(?:\"(?<quoted_name>[^\"]+)\"|(?<name>[^\s]+))
|
||||
\s+
|
||||
(?:\'(?<quoted_value>[^\']*)\'|(?<value>[^\'].+))
|
||||
}x
|
||||
|
||||
result = nil
|
||||
patterns.each do |command, regexp|
|
||||
match = regexp.match(sql)
|
||||
if match
|
||||
result = {
|
||||
command: command
|
||||
}
|
||||
match.names.each do |name|
|
||||
value = match[name]
|
||||
if value
|
||||
if name.in? ['options', 'columns']
|
||||
value = Hash[
|
||||
value.split(',').map { |opt|
|
||||
match = opt.match(option_pair)
|
||||
[match[:name] || match[:quoted_name], match[:value] || match[:quoted_value]] if match
|
||||
}.compact
|
||||
]
|
||||
end
|
||||
result[name.to_sym] = value
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def match_sql(sql)
|
||||
sql.scan(/(?:'[^']*'|[^;])+/).map { |command| match_sql_command(command) }.compact
|
||||
end
|
||||
|
||||
def expect_sql(sql, expectactions = [])
|
||||
match_sql(sql).zip(expectactions).each do |parsed_sql, sql_expectactions|
|
||||
sql_expectactions.each do |key, expected_value|
|
||||
if expected_value.nil?
|
||||
parsed_sql[key].should be_nil, "#{key.inspect} wasn't expected in SQL"
|
||||
else
|
||||
parsed_sql[key].should_not be_nil, "#{key.inspect} was expected in SQL"
|
||||
if expected_value.is_a?(Regexp)
|
||||
parsed_sql[key].should match expected_value
|
||||
else
|
||||
parsed_sql[key].should == expected_value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in new issue