boss_db:save_record not working with PostgreSQL adapter - chicagoboss

I'm trying to save a BossRecord to the database using pgsql adapter, of this way:
boss_db:save_record(admins:new("admins-1", 1)).
In ChicagoBoss's shell this returns:
{ok,{admins,"admins-1",1}}
But the record is not actually being saved in the database.
This is my table:
CREATE TABLE admins("
"ID integer primary key,"
"user_ID integer"
")
My model:
-module(admins, [Id, UserId]).
-compile(export_all).
Thanks.

Thanks to Evan Miller I've found the solution, like here he says evan miller ChicagoBoss blog "the Id field of each model is assumed to be an integer supplied by the database (e.g., a SERIAL type in Postgres)... specifying an Id value other than the atom 'id' for a new record will result in an error"
So I changed my table to:
"CREATE TABLE IF NOT EXISTS admins("
"ID serial primary key,"
"user_ID integer"
")"
And also change the model (to specify the name of the table and the columns):
-module(admin, [Id, UserId]).
-columns([{id, "ID"}, {user_id, "user_ID"}]).
-table("admins").
And using 'id' atom to save the record:
boss_db:save_record(admins:new(id, 1)).

Related

How do I order results by hstore attribute in Rails 4?

How can I order query results by an hstore attribute?
#items = Item.includes(:product).order('products.properties #> hstore("platform")')
Causes
PG::Error: ERROR: column "platform" does not exist
LINE 1: ...oduct_id" ORDER BY products.properties #> hstore("platform"...
platform is a hstore key, stored in the properties column, which is an hstore type.
Double quotes are used to quote identifiers (such as table and column names) in PostgreSQL (and other databases that follow the standard). So when you say:
hstore("platform")
PostgreSQL sees "platform" as a quoted column name and since there is no platform column, you get an error.
Strings in standard SQL are quoted with single quotes, you want to say:
.order("products.properties #> hstore('platform')")
This will probably still fail though, hstore('platform') doesn't make much sense and neither does using #> here; a #> b means
does the hstore a contain the hstore b
If you're trying to sort on the value of the 'platform' key in the properties hstore then you'd want to use -> to lookup the 'platform' key like this:
.order("products.properties -> 'platform'")

Rails reports can't find a column that is there

I am currently trying to do a complicated WHERE search on a table using Rails, the trouble is I get the error:
PG::Error: ERROR: column "email" does not exist
LINE 1: SELECT "bans".* FROM "bans" WHERE (Email='' AND IP='' AND (...
^
: SELECT "bans".* FROM "bans" WHERE (Email='' AND IP='' AND (Username='NULL' ))
And I know that column actually exists, and doing a rails dbconsole gives me the following:
Jungle=> select * from bans;
id | Username | IP | Email | Reason | Length | created_at | updated_at
----+----------+----+-------+--------+--------+------------+------------
(0 rows)
So this is definatly in the database, has anyone had any experience with this?
SQL column names are case insensitive unless quoted, the standard says that identifiers should be normalized to upper case but PostgreSQL normalizes to lower case:
Quoting an identifier also makes it case-sensitive, whereas unquoted names are always folded to lower case. For example, the identifiers FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo" and "FOO" are different from these three and each other. (The folding of unquoted names to lower case in PostgreSQL is incompatible with the SQL standard, which says that unquoted names should be folded to upper case. Thus, foo should be equivalent to "FOO" not "foo" according to the standard. If you want to write portable applications you are advised to always quote a particular name or never quote it.)
You're referencing Email in your SQL:
SELECT "bans".* FROM "bans" WHERE (Email='' ...
but PostgreSQL is complaining about email:
column "email" does not exist
Your unquoted Email is being treated as email because PostgreSQL normalizes identifiers to lower case. Sounds like you created the columns with capitalized names by double quoting them:
create table "bans" (
"Email" varchar(...)
...
)
or by using :Email to identify the column in a migration. If you quote a column name when it is created, then it is not normalized to lower case (or upper case in the SQL standard case) and you'll have to double quote it and match the case forever:
SELECT "bans".* FROM "bans" WHERE ("Email"='' ...
Once you fix Email, you'll have the same problem with IP, Username, Reason, and Length: you'll have to double quote them all in any SQL that references them.
The best practise is to use lower case column and table names so that you don't have to worry about quoting things all the time. I'd recommend that you fix your table to have lower case column names.
As an aside, your 'NULL' string literal:
SELECT "bans".* FROM "bans" WHERE (Email='' AND IP='' AND (Username='NULL' ))
-- -------------------->------------------>---------->---------------^^^^^^
looks odd, are you sure that you don't mean "Username" is null? The 'NULL' string literal and the NULL value are entirely different things and you can't use = or != to compare things against NULL, you have to use is null, is not null, is distinct from, or is not distinct from (depending on your intent) when NULLs might be in play.
It doesn't look like you're error is from a test database but if so try rake db:test:prepare.
In general, be aware that you have 3 databases - Test, Development, Production. So it's easy to get them mixed up and check the wrong one.
I had the same problem here,
but as mu-is-too-short said, PostgreSql can be told to
search with case sensitivity on columns names.
So by implemented this code I managed to bypass the same error that you're facing:
Transaction.find(:all,:conditions => ["(date between ? and ?) AND \"Membership_id\" = ?", Time.now.at_beginning_of_month, Time.now.end_of_month,membership.id])
Noticed the \" sign srrounding the column name? Well.. as annoying as it is, that's the fix to this problem.

Newly assigned Sequence is not working

In PostgreSQL, I created a new table and assigned a new sequence to the id column. If I insert a record from the PostgreSQL console it works but when I try to import a record from from Rails, it raises an exception that it is unable to find the associated sequence.
Here is the table:
\d+ user_messages;
Table "public.user_messages"
Column | Type | Modifiers | Storage | Description
-------------+-----------------------------+------------------------------------------------------------+----------+-------------
id | integer | not null default nextval('new_user_messages_id'::regclass) | plain |
But when I try to get the sequence with the SQL query which Rails uses, it returns NULL:
select pg_catalog.pg_get_serial_sequence('user_messages', 'id');
pg_get_serial_sequence
------------------------
(1 row)
The error being raised by Rails is:
UserMessage.import [UserMessage.new]
NoMethodError: undefined method `split' for nil:NilClass
from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:910:in `default_sequence_name'
This problem only occurs when I use the ActiveRecord extension for importing bulk records, single records get saved through ActiveRecord.
How do I fix it?
I think your problem is that you set all this up by hand rather than by using a serial column. When you use a serial column, PostgreSQL will create the sequence, set up the appropriate default value, and ensure that the sequence is owned by the table and column in question. From the fine manual:
pg_get_serial_sequence(table_name, column_name)
get name of the sequence that a serial or bigserial column uses
But you're not using serial or bigserial so pg_get_serial_sequence won't help.
You can remedy this by doing:
alter sequence new_user_messages_id owned by user_messages.id
I'm not sure if this is a complete solution and someone (hi Erwin) will probably fill in the missing bits.
You can save yourself some trouble here by using serial as the data type of your id column. That will create and hook up the sequence for you.
For example:
=> create sequence seq_test_id;
=> create table seq_test (id integer not null default nextval('seq_test_id'::regclass));
=> select pg_catalog.pg_get_serial_sequence('seq_test','id');
pg_get_serial_sequence
------------------------
(1 row)
=> alter sequence seq_test_id owned by seq_test.id;
=> select pg_catalog.pg_get_serial_sequence('seq_test','id');
pg_get_serial_sequence
------------------------
public.seq_test_id
(1 row)

Rails won't use sequence for primary key?

For one reason or another the pre-existing Postgres schema I'm using with my Rails app doesn't have a default sequence set for a table's primary key, so I am required to query for it every time I want to create a new row.
I have set_sequence_name "seq_people_id" in my model, but whenever I call Person.new Postgres complains to me because Rails is executing the insert query without the ID (which is marked as NOT NULL in the schema).
How do I tell Rails to always use the sequence when creating new records?
Postgres 8.1.4
ActiveRecord 3.0.3
Rails 2.3.10
Here's what I get when I run psql and \d foo:
Table "public.foo"
Column | Type | Modifiers
--------+---------------+------------------------------------------------------
id | integer | not null default nextval('foo_id_seq'::regclass)
(etc.)
I'd check the following:
Verify the actual sequence name is the same as what you reference (people_id_seq vs. seq_people_id)
Verify the table's default is similar to what I have above
(just checking) is the primary key's field named "id" ?
Did you create the table using a migration or by hand? If the latter, try creating a table with a migration, specifying the same fields as in your people table. Does it work properly? Compare the tables.

How to convert a table column to another data type

I have a column with the type of Varchar in my Postgres database which I meant to be integers... and now I want to change them, unfortunately this doesn't seem to work using my rails migration.
change_column :table1, :columnB, :integer
Which seems to output this SQL:
ALTER TABLE table1 ALTER COLUMN columnB TYPE integer
So I tried doing this:
execute 'ALTER TABLE table1 ALTER COLUMN columnB TYPE integer USING CAST(columnB AS INTEGER)'
but cast doesn't work in this instance because some of the column are null...
any ideas?
Error:
PGError: ERROR: invalid input syntax for integer: ""
: ALTER TABLE table1 ALTER COLUMN columnB TYPE integer USING CAST(columnB AS INTEGER)
Postgres v8.3
It sounds like the problem is that you have empty strings in your table. You'll need to handle those, probably with a case statement, such as:
execute %{ALTER TABLE "table1" ALTER COLUMN columnB TYPE integer USING CAST(CASE columnB WHEN '' THEN NULL ELSE columnB END AS INTEGER)}
Update: completely rewritten based on updated question.
NULLs shouldnt be a problem here.
Tell us your postgresql version and your error message.
Besides, why are you quoting identifiers ? Be aware that unquoted identifiers are converted to lowercase (default behaviour), so there might be a problem with your "columnB" in your query - it appears quoted first, unquoted in the cast.
Update: Before converting a column to integer, you must be sure that all you values are convertible. In this case, it means that columnB should contains only digits (or null).
You can check this by something like
select columnB from table where not columnB ~ E'^[0-9]+$';
If you want your empty strings to be converted to NULL integers, then run first
UPDATE table set columnB = NULL WHERE columnB = '';

Resources