-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to do a change_table to change partition key #64
base: master
Are you sure you want to change the base?
Conversation
74a54d6
to
0030104
Compare
0030104
to
987337a
Compare
… there is a change_table :partition_key
"ON kcu.constraint_name = tco.constraint_name " \ | ||
"AND kcu.constraint_schema = tco.constraint_schema "\ | ||
"WHERE tco.constraint_type = 'PRIMARY KEY' " \ | ||
"AND tco.constraint_name = '#{table_name}_pkey'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a bind parameter here, instead of string substitution?
Whilst its unlikely that someone will do SQL injection here, it seems better to avoid problems with table_name called '; DROP TABLE xyz; SELECT '
columns_result.values.each do |c| columns.push(c[0]) end | ||
|
||
if columns.length != pkey_columns.length | ||
execute "ALTER TABLE #{table_name} DROP CONSTRAINT IF EXISTS #{table_name}_pkey" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here regarding SQL injection - I think there are methods to escape identifier names in ActiveRecord::Base
that we can use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I tried looking into it, the method to sanitize raw sql is sanitize_sql_array
, except here, we are taking the name of the table in the ALTER TABLE
which ends up like this:
query = ActiveRecord::Base::sanitize_sql_array(["ALTER TABLE $1 DROP CONSTRAINT IF EXISTS $2_pkey;", table_name, table_name])
execute(query)
And this triggers errors because SQL doesn't suppose that format
If you have an idea how to do change the queries, let me know
def create_table(table_name, options = {}, &block) | ||
ret = orig_create_table(table_name, options.except(:partition_key), &block) | ||
if options[:partition_key] && options[:partition_key].to_s != 'id' | ||
execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{table_name}_pkey" | ||
execute "ALTER TABLE #{table_name} ADD PRIMARY KEY(id, \"#{options[:partition_key]}\")" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course, to be fair my own code was not up to my comments :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha, noted, I'll work on avoiding SQL injection ;)
spec/schema.rb
Outdated
create_distributed_table :allowed_places, :account_id | ||
create_reference_table :categories | ||
|
||
change_table :project_categories, partition_key: :account_id do |t| | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can not pass the block at all, unless that throws an error:
change_table :project_categories, partition_key: :account_id
|
||
if columns_result.present? | ||
columns = [] | ||
columns_result.values.each do |c| columns.push(c[0]) end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For one liners usually in Ruby you'd use the { .. }
syntax:
columns_result.values.each { |c| columns.push(c[0]) }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there anyway to do this without initializing a constant? in python you can do
columns = [e[0] for e in columns_result.values]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you could do it like this:
columns = columns_result.values.map { |c| c[0] }
or without the block, utilizing the fact that there is a first
method on arrays:
columns = columns_result.values.map(&:first)
…f the structure.sql
93aa622
to
419f234
Compare
Hi, are you planning to merge this? |
No, both Louis & Lukas are no longer with Citus If someone else wants this to get through they can create a new PR based on this one |
This PR allows a user to create a migration to do
Which will create the primary key (partittion_key, id).
Things this PR does not do: