Module: ActiveRecord::ConnectionAdapters::Clickhouse::SchemaStatements

Included in:
ActiveRecord::ConnectionAdapters::ClickhouseAdapter
Defined in:
lib/active_record/connection_adapters/clickhouse/schema_statements.rb

Instance Method Summary collapse

Instance Method Details

#add_index_options(table_name, expression, **options) ⇒ Object



138
139
140
141
142
143
144
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 138

def add_index_options(table_name, expression, **options)
  options.assert_valid_keys(:name, :type, :granularity, :first, :after, :if_not_exists, :if_exists)

  validate_index_length!(table_name, options[:name])

  IndexDefinition.new(table_name, options[:name], expression, options[:type], options[:granularity], first: options[:first], after: options[:after], if_not_exists: options[:if_not_exists], if_exists: options[:if_exists])
end

#assume_migrated_upto_version(version, migrations_paths = nil) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 178

def assume_migrated_upto_version(version, migrations_paths = nil)
  version = version.to_i
  sm_table = quote_table_name(schema_migration.table_name)

  migrated = migration_context.get_all_versions
  versions = migration_context.migrations.map(&:version)

  unless migrated.include?(version)
    exec_insert "INSERT INTO #{sm_table} (version) VALUES (#{quote(version.to_s)})", nil, nil
  end

  inserting = (versions - migrated).select { |v| v < version }
  if inserting.any?
    if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
      raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
    end
    execute(insert_versions_sql(inserting), nil, settings: {max_partitions_per_insert_block: [100, inserting.size].max})
  end
end

#data_sourcesObject



146
147
148
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 146

def data_sources
  tables
end

#do_execute(sql, name = nil, format: DEFAULT_RESPONSE_FORMAT, settings: {}) ⇒ Object



156
157
158
159
160
161
162
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 156

def do_execute(sql, name = nil, format: DEFAULT_RESPONSE_FORMAT, settings: {})
  ActiveRecord.deprecator.warn(<<~MSG.squish)
    `do_execute` is deprecated and will be removed in an upcoming release.
    Please use `execute` instead.
  MSG
  execute(sql, name, format: format, settings: settings)
end

#do_system_execute(sql, name = nil, except_params: []) ⇒ Object



150
151
152
153
154
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 150

def do_system_execute(sql, name = nil, except_params: [])
  log_with_debug(sql, [adapter_name, name].compact.join(' ')) do
    raw_execute(sql, except_params: except_params)
  end
end

#exec_delete(sql, name = nil, _binds = []) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 84

def exec_delete(sql, name = nil, _binds = [])
  log(sql, "#{adapter_name} #{name}") do
    statement = Statement.new(sql, format: @response_format)
    res = request(statement)
    begin
      data = JSON.parse(res.header['x-clickhouse-summary'])
      data['result_rows'].to_i
    rescue JSON::ParserError
      0
    end
  end
end

#exec_insert(sql, name = nil, _binds = [], _pk = nil, _sequence_name = nil, returning: nil) ⇒ Object



50
51
52
53
54
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 50

def exec_insert(sql, name = nil, _binds = [], _pk = nil, _sequence_name = nil, returning: nil)
  new_sql = sql.sub(/ (DEFAULT )?VALUES/, " VALUES")
  with_response_format(nil) { execute(new_sql, name) }
  true
end

#exec_insert_all(sql, name) ⇒ Object



72
73
74
75
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 72

def exec_insert_all(sql, name)
  with_response_format(nil) { execute(sql, name) }
  true
end

#exec_update(sql, name = nil, _binds = []) ⇒ Object



78
79
80
81
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 78

def exec_update(sql, name = nil, _binds = [])
  execute(sql, name)
  0
end

#execute(sql, name = nil, format: @response_format, settings: {}) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 42

def execute(sql, name = nil, format: @response_format, settings: {})
  with_response_format(format) do
    log(sql, [adapter_name, name].compact.join(' ')) do
      raw_execute(sql, settings: settings)
    end
  end
end

#functionsObject



115
116
117
118
119
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 115

def functions
  result = do_system_execute("SELECT name FROM system.functions WHERE origin = 'SQLUserDefined' ORDER BY name")
  return [] if result.nil?
  result['data'].flatten
end

#indexes(table_name, name = nil) ⇒ Object

Not indexes on clickhouse



134
135
136
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 134

def indexes(table_name, name = nil)
  []
end

#internal_exec_query(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 56

def internal_exec_query(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false)
  result = execute(sql, name)
  columns = result['meta'].map { |m| m['name'] }
  types = {}
  result['meta'].each_with_index do |m, i|
    # need use column name and index after commit in 7.2:
    # https://github.com/rails/rails/commit/24dbf7637b1d5cd6eb3d7100b8d0f6872c3fee3c
    types[m['name']] = types[i] = type_map.lookup(m['type'])
  end
  ActiveRecord::Result.new(columns, result['data'], types)
rescue ActiveRecord::ActiveRecordError => e
  raise e
rescue StandardError => e
  raise ActiveRecord::ActiveRecordError, "Response: #{e.message}"
end

#internal_metadataObject



173
174
175
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 173

def 
  pool.
end

#materialized_views(name = nil) ⇒ Object



109
110
111
112
113
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 109

def materialized_views(name = nil)
  result = do_system_execute("SHOW TABLES WHERE engine = 'MaterializedView'", name)
  return [] if result.nil?
  result['data'].flatten
end

#migration_contextObject



169
170
171
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 169

def migration_context
  pool.migration_context
end

#schema_migrationObject



165
166
167
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 165

def schema_migration
  pool.schema_migration
end

#show_create_function(function) ⇒ Object



121
122
123
124
125
126
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 121

def show_create_function(function)
  result = do_system_execute("SELECT create_query FROM system.functions WHERE origin = 'SQLUserDefined' AND name = '#{function}'")
  return if result.nil?

  result['data'].flatten.first.sub(/\ACREATE FUNCTION/, 'CREATE OR REPLACE FUNCTION')
end

#table_options(table) ⇒ Object



128
129
130
131
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 128

def table_options(table)
  sql = show_create_table(table)
  { options: sql.gsub(/^(?:.*?)(?:ENGINE = (.*?))?( AS SELECT .*?)?$/, '\\1').presence, as: sql.match(/^CREATE (?:.*?) AS (SELECT .*?)$/).try(:[], 1) }.compact
end

#tables(name = nil) ⇒ Object



97
98
99
100
101
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 97

def tables(name = nil)
  result = do_system_execute("SHOW TABLES WHERE name NOT LIKE '.inner_id.%'", name)
  return [] if result.nil?
  result['data'].flatten
end

#views(name = nil) ⇒ Object



103
104
105
106
107
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 103

def views(name = nil)
  result = do_system_execute("SHOW TABLES WHERE engine = 'View'", name)
  return [] if result.nil?
  result['data'].flatten
end

#with_response_format(format) ⇒ Object

Request a specific format for the duration of the provided block. Pass ‘nil` to explicitly send the SQL statement without a `FORMAT` clause.

Examples:

Specify CSVWithNamesAndTypes format

with_response_format('CSVWithNamesAndTypes') do
  Table.connection.execute('SELECT * FROM table')
end
# sends and executes "SELECT * FROM table FORMAT CSVWithNamesAndTypes"

Specify no format

with_response_format(nil) do
  Table.connection.execute('SELECT * FROM table')
 end
 # sends and executes "SELECT * FROM table"

Parameters:

  • format (String, nil)


34
35
36
37
38
39
40
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 34

def with_response_format(format)
  prev_format = @response_format
  @response_format = format
  yield
ensure
  @response_format = prev_format
end

#with_settings(**settings) ⇒ Object



10
11
12
13
14
15
16
17
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 10

def with_settings(**settings)
  @block_settings ||= {}
  prev_settings = @block_settings
  @block_settings = @block_settings.merge(settings)
  yield
ensure
  @block_settings = prev_settings
end

#with_yaml_fallback(value) ⇒ Object



200
201
202
203
204
205
206
# File 'lib/active_record/connection_adapters/clickhouse/schema_statements.rb', line 200

def with_yaml_fallback(value) # :nodoc:
  if value.is_a?(Array) || value.is_a?(Hash)
    value
  else
    super
  end
end