cartodb/app/models/visualization/support_tables.rb

149 lines
5.5 KiB
Ruby
Raw Normal View History

2020-06-15 10:58:47 +08:00
require_relative './member'
module CartoDB
module Visualization
class SupportTables
def initialize(database_connection, config={})
@database = database_connection
@parent_id = config.fetch(:parent_id, nil)
@parent_kind = config.fetch(:parent_kind, nil)
@public_user_roles_list = config.fetch(:public_user_roles)
@tables_list = nil
end
def reset
@tables_list = nil
end
# Only intended to be used if from the Visualization Relator (who will set the parent)
def load_actual_list(parent_name=nil)
return [] if @parent_id.nil? || @parent_kind != Visualization::Member::KIND_RASTER
parent = Visualization::Member.new(id:@parent_id).fetch
table_data = @database.fetch(%Q{
SELECT o_table_catalog AS catalog, o_table_schema AS schema, o_table_name AS name
FROM raster_overviews
WHERE r_table_catalog = '#{parent.user.database_name}'
AND r_table_schema = '#{parent.user.database_schema}'
AND r_table_name = '#{parent_name.nil? ? parent.name : parent_name}'
}).all
table_data.nil? ? [] : table_data
end
def delete_all
tables.each { |table|
@database.execute(%Q{
DROP TABLE "#{table[:schema]}"."#{table[:name]}"
})
}
end
# @param existing_parent_name String
# @param new_parent_name String
# @param recreate_relations Bool If true will recreate constraints and permissions from overviews
# @param seek_parent_name String|nil If specified, seeking of tables will be performed using this name
def rename(existing_parent_name, new_parent_name, recreate_relations=true, seek_parent_name=nil)
begin
schema = nil
support_tables_new_names = []
tables_list = tables(seek_parent_name)
tables_list.each { |item|
schema = item[:schema]
new_support_table_name = item[:name].dup
# CONVENTION: support_tables will always end in "_tablename", so we substitute using parent name
new_support_table_name.slice!(-existing_parent_name.length, existing_parent_name.length)
new_support_table_name = "#{new_support_table_name}#{new_parent_name}"
@database.execute(%Q{
ALTER TABLE "#{item[:schema]}"."#{item[:name]}" RENAME TO "#{new_support_table_name}"
})
support_tables_new_names.push(new_support_table_name)
}
renamed = true
rescue
renamed = false
end
if renamed && recreate_relations
support_tables_new_names.each { |table_name|
recreate_raster_constraints_if_exists(table_name, new_parent_name, schema)
update_permissions(table_name, @public_user_roles_list, schema)
}
end
{ success: renamed, names: support_tables_new_names }
end
def change_schema(new_schema, parent_table_name)
tables.each { |item|
@database.execute(%Q{
ALTER TABLE "#{item[:schema]}"."#{item[:name]}"
SET SCHEMA "#{new_schema}"
})
# Constraints are not automatically updated upon schema change or table renaming
recreate_raster_constraints_if_exists(item[:name], parent_table_name, new_schema)
update_permissions(item[:name], @public_user_roles_list, new_schema)
}
end
# For import purposes
# @param new_list Array [ { :schema, :name } ]
def tables=(new_list)
@tables_list = new_list
end
private
def tables(seek_parent_name=nil)
@tables_list ||= load_actual_list(seek_parent_name)
end
def update_permissions(overview_table_name, db_roles_list, schema)
overviews = @database.fetch(%Q{
SELECT o_table_name, o_table_schema
FROM raster_overviews
WHERE o_table_name = '#{overview_table_name}'
AND o_table_schema = '#{schema}'
}).first
return if overviews.nil?
@database.transaction do
db_roles_list.each { |role_name|
@database.execute(%Q{
GRANT SELECT ON TABLE "#{overviews[:o_table_schema]}"."#{overviews[:o_table_name]}" TO "#{role_name}"
})
}
end
end
# @see http://postgis.net/docs/manual-dev/using_raster_dataman.html#RT_Raster_Overviews
def recreate_raster_constraints_if_exists(overview_table_name, raster_table_name, schema)
constraint = @database.fetch(%Q{
SELECT o_table_name, o_raster_column, r_table_name, r_raster_column, overview_factor
FROM raster_overviews
WHERE o_table_name = '#{overview_table_name}'
AND o_table_schema = '#{schema}'
}).first
return if constraint.nil?
@database.transaction do
# @see http://postgis.net/docs/RT_DropOverviewConstraints.html
@database.execute(%Q{
SELECT DropOverviewConstraints('#{schema}', '#{constraint[:o_table_name]}',
'#{constraint[:o_raster_column]}')
})
# @see http://postgis.net/docs/manual-dev/RT_AddOverviewConstraints.html
@database.execute(%Q{
SELECT AddOverviewConstraints('#{schema}', '#{constraint[:o_table_name]}',
'#{constraint[:o_raster_column]}', '#{schema}', '#{raster_table_name}',
'#{constraint[:r_raster_column]}', #{constraint[:overview_factor]});
})
end
end
end
end
end