Rails ActiveRecord SQlite3 datatype mismatch error on change_column from string to text - ruby-on-rails

I am trying to change the datatype of a column from string to id. But SQlite3 is giving me a hard time. This is the only line in my migration:
change_column :containers, :title, :text
When the migration is running I'm getting an error of datatype mismatch:
SQLite3::MismatchException: datatype mismatch: INSERT INTO "acontainers"
I am pretty sure this is because of ActiveRecord creating a temporary table that has a id field with datatype INT while the original table actually has a datatype VARCHAR as can be seen here:
CREATE TEMPORARY TABLE "acontainers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
The problem is that I have no idea how to get around this. Any input is greatly appreciated!

Looks like a bug in the SQLite wrapper.
You can try to update to the latest version if you're not using the one
As a workaround you can do the migration in multiple steps:
Create a new column
Write to both columns
Backfill data from the old column to the new column
Move reads from the old column to the new column
Stop writing to the old column
Drop the old column
It is also a safer approach as change_column may cause downtimes and errors
You can read more about it in this gem description

Related

Rails 6, float or bigint column types being treated as integer by ActiveRecord

I need to accept very large integer values on a postgres column on a table pre_transaction. The column name is give_amount.
I tried changing the column type to bigint with:
change_column :pre_transactions, :give_amount, :bigint
but I still get the following error when I try to save the record even after restarting the console:
ActiveModel::RangeError (1000000000000000000000 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
I also realized that if I run PreTransaction in the rails console, the bigint columns are shown as integer columns (same for foreign keys that are stated as bigint in the schema but appear as integer on rails c), which is weird.
That's why I then changed the column type to float. Now when I run PreTransaction in the rails console I do see the column as type float but now when I try to save the record it saves, but rounding up to 1.0.
So, how can I do to store very large integers in the database?
Instead of :bigint use the :decimal type. It avoids float rounding inconsistencies and allows for large numbers to be ok.

How to change id data type from INT to BIGINT safely following strong_migrations suggestions?

I wonder how to change data type of id field from INT to BIGINT safely following strong_migrations suggestions?
Changing the type of an existing column requires the entire
table and indexes to be rewritten. A safer approach is to:
1. Create a new column
2. Write to both columns
3. Backfill data from the old column to the new column
4. Move reads from the old column to the new column
5. Stop writing to the old column
6. Drop the old column
What should be the name of new column in that case?

How can I use value of the id column as default value of another non-nullable column when using postgresql-rails?

Here's one example where such a requirement comes up:
Suppose we have a table 'sample' in our database which has a column 'col1' and an auto-incremental 'id' column.
We want the default value of 'col1' to be taken as the value of the 'id' column. How do I do that?
I am using rails to write the migration script which will create the table in my postgres databse.
def self.up
Yourmodel.update_all("updated_at=created_at")
end
Something like this in your migration script can help you.

how to create table in MySQL using sequel with int(3)?

How to create int(3) columns in MySQL using the sequel gem?
I tried the following, but the column is still created with the type int(11) in MySQL.
DB.create_table :table1 do
Integer(:a, :size => 3)
end
Specifying the size (length in bytes) of the column using the size option is not supported for Integer column types in Sequel. The author of the gem advises to use a string definition of the column.
For this to work, you'll also need to use the other style of defining schema in sequel, using the column methods, like in the following rewrite of your creation sample:
DB.create_table(:table1) do
column :a, 'integer(3)'
end

string/text storage limits in a sqlite3 database

I have a note field of string type in one of my models in my sqlite3 database, but I realized that I needed to store more text than string would allow.
I just ran a migration changing the type of the field from string to text. Looking at my database, it says that the type is now text(255), whereas before it was varchar(255).
What does the 255 mean? Is that a character limit? If so, would I have the same storage problems as before? How would I fix this?
Here is the migration I used to change the field type
change_column(:posts, :note, :text)
SQLite does not enforce text storage limits. If you declare a column VARCHAR(1) or TEXT(1) you still can store some very long blob of 500 Megabytes inside it. Even though that is not adviseable.
~$ sqlite
SQLite version 3.7.2
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table foo ( bar text(3));
sqlite> insert into foo values ('aeiou');
sqlite> select * from foo;
aeiou
You should just make your storage type text and not put any limit on it. The 255 denotes the maximum number of characters allowed in the field.

Resources