149 lines
5.5 KiB
Ruby
149 lines
5.5 KiB
Ruby
|
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
|