ActiveRecordModel.group(:attribute).count with postgres - ruby-on-rails

When trying to run such code in Postgres I always get errors of this kind:
Caused by PG::GroupingError: ERROR: column "<table name>.<some random column>" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...ments" GROUP BY "<table_name>"."<:attribute>" ORDER BY ...

There was something on the default scope that was preventing this to work. I managed to sort this out by using ActiveRecordModel.unscoped.group(:attribute).count

Related

ActiveRecord update error - illegal zero-length identifier

I'm running simple Rails + ActiveRecord program, where I want to take records from the database, where column "transfered_at" is null, and update it with the current time.
orders_ora = Orders.where(transfered_at: nil)
orders_ora.each do |order_ora|
puts order_ora.name
order_ora.update(transfered_at: Time.now)
end
However, it does not allow me to do that. Here is the error that I'm getting:
OCIError: ORA-01741: illegal zero-length identifier: UPDATE
"ORDERS" SET "TRANSFERED_AT" = :a1 WHERE
"ORDERS"."" IS NULL (ActiveRecord::StatementInvalid)
What am I missing?
Edit: I need to use this inside the loop because I'm doing other calculations inside it. And time format does not seems to be the problem, because I'm trying to update another column which type is "number", and I'm getting the same error.
If I try to do it like this:
order_ora.inspection_id = 333
order_ora.save
it also gives the same error as before.
Why do you loop through the results? You can do it in a single query:
Orders.where(transfered_at: nil).update(transfered_at: Time.now)
What could be a problem is that the Time.now is not in the correct format for your table? Use strftime in that case:
Orders.where(transfered_at: nil).update(transfered_at: Time.now.strftime('%H:%M') )
I found answer to this myself, it was not related to the code.
The problem was that my table did not have a PK, and it looks like ActiveRecords uses it to generate SQL statements.

Prepend DISTINCT ON in select statement in an active record scope

I am trying to use distinct on in rails with a scope, I've created a method in my model like this:
def self.fetch_most_recent_by_user(scope)
scope.where(guid: scope.except(:select).select("DISTINCT ON (eld_logs.user_id) user_id, eld_logs.guid").order("user_id, eld_logs.created_at desc").map(&:guid))
end
When I execute this I get and error like:
TestModel.fetch_most_recent_by_user(TestModel.includes(:user))
ERROR: syntax error at or near "DISTINCT"
LINE 1: SELECT guid, DISTINCT ON (user_id) user_id...
On searching on DISTINCT ON I found out that it should be the first element in a select statement for postgres to make it work.
I want to prepend the DISTINCT ON in the select statement. I have tried clearing the old select statements using except(:select) which I got from here, but it doesn't work because the includes(:user) prepends users attributes first while doing a left join.
I am using Rails 4.0.13 and Postgres 9.4.12. Any help is appreciated.
I found that if the includes was meddling with the distinct my sub query, because which DISTINCT ON failed. I modified my method to this and it works:
def self.fetch_most_recent_eld_log_by_user(scope, include_associations = { })
scope.where(guid: scope.except(:select).select("DISTINCT ON (eld_logs.user_id) eld_logs.user_id, eld_logs.guid").order("eld_logs.user_id, eld_logs.created_at desc").map(&:guid))
.includes(include_associations)
end
Still it'll be good if someone can provide a way to prepend something in the select statement of active record scope.

Rails 3 - .each works, .find_each fails -> ActiveRecord::JDBCError: ERROR: operator does not exist: character varying >= integer

I've got a lot (+100,000) of records I'm trying to process through a query.
I was using something like:
BigRecordPull.where(name: ['x','y','z']).each { |record| do_some_action record }
Because this isn't good from a memory management perspective, I wanted to instead use find_each as outlined here so now the code looks like this:
BigRecordPull.where(name: ['x','y','z']).find_each { |record| do_some_action record }
The issue is when I go to fire the code I get the following error:
ActiveRecord::JDBCError: ERROR: operator does not exist: character varying >= integer
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
If I review the SQL query created in the logs I get back something like:
SELECT "big_record_pull".* FROM "big_record_pull" WHERE "big_record_pull"."name" IN ('x','y','z') AND ("big_record_pull"."name" >= 0)
ActiveRecord seems to add the part, 'AND ("big_record_pull"."name" >= 0)' and that seems to be what's causing the problem. Name in this example is a varchar. The extra wrinkle is I don't control the postgresql db my rails project plugs into so I can't just re-run a migration to try and fix this issue. I'm hoping there's some sort of work around.... I'd like to avoid running raw SQL.
Extra info
In the example above, big_record_pull.name is also a foreign_key
Ok, the problem was related to a gem: composite_primary_keys-5.0.14.gem.
Solution was found, here
See lib/composite_primary_keys/relation/batches.rb:28:in `find_in_batches'
Change this block to:
self.primary_key.each do |key|
condition = case relation.columns_hash[key.to_s].type
when :string
table[key].not_eq ''
when :integer
table[key].gteq start
end
relation = relation.where(condition)
end

Rails / ActiveRecord: How to quote protected column name using #select in custom query?

Running Rails 4.0.13 with TinyTDS connected to Microsoft SQL Server 2012, I'm trying to run the following query:
sql = Model.where(:foo => bar).select(:open, :high, :low, :close).to_sql
Model.connection.execute(sql)
The problem is, the generated sql is
"SELECT open, high, low, close FROM [models]"
Which gives me an error as the column names open and close are protected.
TinyTds::Error: Incorrect syntax near the keyword 'open'
If I use #pluck, I can see the correct SQL is generated (with column names escaped):
"SELECT [models].[open], [models].[high], [models].[low], [models].[close] FROM [models]"
However, this produces an array, which is not what I want.
My question is how can i get #select to correctly quote the column names?
Thank you
I don't think you can make the select method to protect your column names when using symbols (maybe because different DBMS use different quoting identifiers), but you could pass your selection as a string :
sql = Model.where(:foo => bar).select("[open], [high], [low], [close]").to_sql
Model.connection.execute(sql)
I attempted to submit a bug report to Rails, however in doing so I saw the problem did not appear to exists using SQLite test case, this leads me to believe the issue is with the SQL Server Adapter.
Since I am on Rails 4 and not the latest version of the adapter I left it and wrote the following (horrible) method as wrapping the column names was not enough, I needed to prefix the table to prevent ambiguous column names. Yuck
def self.quote(*columns, klass)
columns.map { |col| "[#{klass.table_name}].[#{col}]" }.join(', ')
end

Postgres Query to find whether database is read-only mode

I am new to postgres. In mysql we can check whether the database is in read-only mode by triggering the below query.
SELECT ##global.read_only
Likewise can anyone pls help me with the query to do the same in postgres? I tried few things like below
SELECT schemaname||'.'||tablename FROM pg_tables
WHERE
has_table_privilege ( 'postgres', schemaname||'.'||tablename, 'select' )
AND schemaname NOT IN ( 'pg_catalog','information_schema');
But it is listing like below which I am not expecting.
?column?
----------------------------------------
public.schema_migrations
public.credential_methods
public.notifications
public.site_defaults
public.apis
public.client_applications
public.api_groups
public.operations
public.client_application_labels
public.client_application_label_values
public.roles
public.users
public.sdm_user_roles
public.permissions_roles
public.keys
public.o_two_access_tokens
public.settings
public.sdm_users
public.permissions
public.audits
public.oauth_requesttokens
public.oauth_access_tokens
public.oauth_verifiers
public.logged_exceptions
public.api_call_details
public.api_access_roles
public.api_access_users
public.login_attempts
public.system_scopes
public.keys_system_scopes
public.o_two_auth_codes
public.o_two_refresh_tokens
public.service_profiles
public.error_traces
I also tried "\du" but this one is working only in terminal but not from a ruby file.
query=ActiveRecord::Base.connection.execute("\du;")
ActiveRecord::StatementInvalid: PGError: ERROR: syntax error at or near "du"
LINE 1: du;
Thanks,
Rafiu
You probably want something of the has_*_privilege() family function for relevant tables and relevant privileges. See here. Other than that I'm not sure if postgres has a concept of read-only mode.
Well, there's also show transaction_read_only inside a read-only transaction, but that doesn't seem to be like what you're asking for. And I don't think that transaction being readonly affects privileges of the user.
I'm not sure what you expect from your query, but if you want something boolean, as in whether you have access anywhere, you can use count(*)!=0 (and, probably, not select).
If you have a multi-node instance cluster, and you have the hot standby configuration. The output of SELECT pg_is_in_recovery() can tell you if the cluster is in the read-only mode.

Resources