I am doing Rails + PostgreSql app. I need to run sql dump on production env. I have courses table with courseID attribute. But when I run my sql I get this error:
PG::UndefinedColumn: ERROR: column "courseid" of relation "courses" does not exist
LINE 1: INSERT INTO courses (courseID, name, created_at, updated_at)...
Here is how my sql dump looks like:
INSERT INTO course (courseID, name, created_at, updated_at) VALUES
('CSCI150', 'Fundamentals of Programming',
localtimestamp, localtimestamp ),
etc...;
Tried to put quotes (' ') around attributes, didn't help. Strange error. What might cause that?
EDIT:
Here is what in my schema.rb
create_table "courses", force: :cascade do |t|
t.string "name"
t.string "courseID"
t.integer "school_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
All identifiers (including column names) that are not double-quoted are folded to lower case in PostgreSQL. Column names that were created with double-quotes and thereby retained upper-case letters (and/or other syntax violations) have to be double-quoted for the rest of their life. So, yes, PostgreSQL column names are case-sensitive
Read it here
Try changing courseID to lowercase or enclose it in doublequotes in the dump.
Related
I'm struggling to wrap my mind around an ActiveRecord query.
I'm trying to search my database for GolfRetailer objects with ID's 1..100, that have something (not nil) in their :website field, and that don't have true in their duplicate_domain field.
Here's the query I expected to work:
GolfRetailer.where.not(website: nil, duplicate_domain: true).where(id: 1..100)
I also tried this variant of essentially the same query: GolfRetailer.where.not(website: nil).where(id: 1..100, duplicate_domain: !true)
But both return an empty array, despite there definitely being records that meet those requirements.
When I run GolfRetailer.where.not(website: nil).where(id: 1..100) I get an array, and when I run GolfRetailer.where.not(website: nil, duplicate_domain: nil).where(id: 1..100) I also get an array, but with all records that do have the true duplicate_domain flag, which isn't what I'm looking for.
I'd rather not search for records that have duplicate_domain: nil as that's not always correct (I may not have processed their domain yet).
For clarity, here is the Schema for the Model.
create_table "golf_retailers", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "place_id"
t.string "website"
t.string "formatted_address"
t.string "google_places_name"
t.string "email"
t.boolean "duplicate_domain"
t.index ["duplicate_domain"], name: "index_golf_retailers_on_duplicate_domain"
end
What am I missing to make this query work?
This is happening because in SQL when you do a != TRUE, any NULL values will not be included in the result. This is because the NULL value represents an unknown value, so the DB does not know how to do any comparison operations on an unknown value and therefore they're excluded.
One way to get around this is to use IS DISTINCT FROM:
GolfRetailer
.where(id: 1..100)
.where.not(website: nil)
.where("duplicate_domain IS DISTINCT FROM ?", true)
As others have mentioned, you should also ask yourself if it's really the case that it's ever unknown to you if a GolfRetailer has a duplicate_domain.
If, all GolfRetailers with a duplicate_domain of NULL actually mean they don't have one (false) than you should consider preventing a NULL value for that column entirely.
You can do this by adding a NOT NULL constraint on the column with a change_column database migration.
In order to add the NOT NULL constraint you will first need to make sure all of the data in the column has non-null values.
def change
GolfRetailer.in_batches.update_all(duplicate_domain: false)
change_column_null :golf_retailers, :duplicate_domain
end
If your application is under load, you should also be careful about the potential performance any migration like this might have - notably if you add a NOT NULL constraint with a default value.
Consider using something like the Strong Migrations gem to help find DB migrations that might cause downtime before production.
I am trying to add a date of birth to each patient in my database and having issues adding a date to the dob attribute on each patient. When I add for ex. Patient.first(dob: "01/25/1990") I get an error reading no implicit conversion of Integer into Hash. Any ideas on how I would do so?
create_table "patients", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.integer "age"
t.date "dob"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
When I seeded my database, my dob field was nil
I have also tried Patient.first(dob: Date.parse('31-12-2010')) and still get the same error.
You have two problems:
first doesn't take query arguments.
Your date format is ambiguous.
The first finder method looks like:
first(limit = nil)
Find the first record (or first N records if a parameter is supplied). If no order is defined it will order by primary key.
You want to use find_by as your .where(...).first shortcut.
And to avoid ambiguity with your dates, you should use Date objects or ISO-8601 formatted strings (i.e. YYYY-MM-DD) inside the application and leave the supposedly "human friendly" formats for the very edges.
You want to say:
Patient.find_by(dob: '1990-01-25')
I am obtaining this error on my Ruby on Rails app,
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
I've read on the stack overflow API and can't find an answer that works for me. So this is the specific parts of the code:
ActiveRecord::StatementInvalid in Store#show_item
Showing /media/store_test/app/views/store/show_item.html.erb where line #24 raised:
PG::UndefinedFunction: ERROR: operator does not exist: character varying = integer
LINE 1: ...CT "show_item".* FROM "current_item" WHERE (user_id = 1)
^
My logic behind this error is that I have two users, store users and employee users, they are both users but employee users have a "flag" on them, so they can see all items in store. Store users do not have this flag, so this web page should show items they have "wishlisted", and when I create a table to populate this, I am getting the above error/
This code works when Im a employee user, and populates my table as required, but does not work when I'm a store user.
Question: How can I fix this error without heavily modifying my code?
EDIT: SCHEMA
create_table "current_item", force: :cascade do |t|
t.string "name", default: "", null: false
t.string "description"
t.integer "cost"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "user_id"
end
Thanks to Marcin Kologziej:
user_id column was defined with the wrong type. Instead of strings, it should have been integer, as per the error. Therefore, I have created a new migration, using the code:
change_column :current_item, :user_id, :integer, using: 'user_id_id::integer'
And then performing:
rake db:migrate
And everything works perfectly now.
My model is really simple:
create_table "stack_items", force: true do |t|
t.integer "stack_id"
t.integer "service_id"
t.text "description"
end
I need to remove duplicate StackItem records that have the same stack_id and service_id. However if one of the dupes has anything in the description field, I have to keep that one, and delete the other duplicate.
StackItem.group(:stack_id, :service_id).order("count_id desc").where("COUNT(*) > 1")
So far I've tried to just grab the duplicates but it's saying I cannot count within a where statement.
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: aggregate functions are not allowed in WHERE
How can I achieve this using Rails 4 and ActiveRecord? My database is Postgresql.
I am getting the error below when trying to query my PostgreSQL database. I can view the table and all columns in pgAdmin and even perform a select *, so I know the table and column exists. Any help with this will be greatly appreciated.
Here is the error I am getting:
PG::Error: ERROR: column "fi_ase" does not exist
Here is the schema for the table in question. It was generated with a migration as part of a Rails 3.2 app.
create_table "certificates", :force => true do |t|
t.integer "profile_id"
t.boolean "FI_ASE"
t.boolean "FI_AME"
t.boolean "FI_INSTA"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "C_ASEL"
t.boolean "C_AMEL"
t.boolean "C_ASES"
t.boolean "C_AMES"
t.boolean "ATP_ASEL"
t.boolean "ATP_AMEL"
t.boolean "ATP_ASES"
t.boolean "ATP_AMES"
t.boolean "GI_Basic"
t.boolean "GI_Advanced"
t.boolean "GI_Instrument"
end
Here is my query/method in Rails:
def self.search(city, state, zip, *certs)
query_obj = joins(:profile => [:addresses, :certificate])
query_obj = query_obj.where("city like ?", "%#{city}%") unless city.blank?
query_obj = query_obj.where("state = ?", state) unless state.blank?
query_obj = query_obj.where("zip like ?", "%#{zip}%") unless zip.blank?
query_obj = query_obj.where("FI_ASE = ?", true) unless certs[0].blank?
query_obj
end
I get the same error when running the following SQL statement directly in my pgAmin SQL Editor:
select *
from contacts c
inner join profiles p on c.id = p.contact_id
inner join addresses a on p.id = a.profile_id
inner join certificates ct on p.id = ct.profile_id
where ct.FI_ASE = true
Rails will double quote the column names when it generates them. For example, the CREATE TABLE for your table will look like this when PostgreSQL sees it:
create table "certificates" (
-- ...
"FI_ASE" boolean,
When an identifier is double quoted, it is case sensitive. But, PostgreSQL will normalize unquoted identifiers to lower case so when you say this:
query_obj.where("FI_ASE = ?", true)
the SQL will come out as:
where FI_ASE = 't'
but, since your FI_ASE is not quoted, PostgreSQL will see that as:
where fi_ase = 't'
However, your table doesn't have an fi_ase column, it has an FI_ASE column.
Now that we know what's wrong, how do we fix it? You can manually quote the column name all the time:
where('"FI_ASE" = ?', true)
or you could let ActiveRecord do it (but make sure you use the right case):
where(:FI_ASE => true)
or best of all, recreate the table using lower case column names so that you don't have to quote things.