[英]Naming SQL queries in Rails / ActiveRecord
When using Rails with ActiveRecord (and PostgreSQL), executing "simple" queries adds a name to them, eg calling当使用带有 ActiveRecord(和 PostgreSQL)的 Rails 时,执行“简单”查询会为其添加一个名称,例如调用
Article.all
# => Article Load (2.6ms) SELECT "articles".* FROM "articles"
names the query Article Load
.命名查询Article Load
。 However, when executing slightly more complex queries, no name is being generated, as for example with但是,当执行稍微复杂的查询时,不会生成名称,例如
Article.group(:article_group_id).count
# => (1.2ms) SELECT COUNT(*) AS count_all, "articles"."article_group_id" AS articles_article_group_id FROM "articles" GROUP BY "articles"."article_group_id"
I can add a name if executing a custom query using the execute
method:如果使用execute
方法执行自定义查询,我可以添加名称:
ActiveRecord::Base.connection.execute("SELECT * FROM articles", "My custom query name")
# => My custom query name (2.5ms) SELECT * FROM articles
But is there a way to add a custom name to a query built with the ActiveRecord-methods?但是有没有办法为使用 ActiveRecord 方法构建的查询添加自定义名称?
If you wonder why: The name is useful for all kinds of monitoring, eg when looking at slow queries in AppSignal.如果您想知道原因:该名称对各种监控都很有用,例如在查看 AppSignal 中的慢查询时。
Since you just want to custom query name for monitoring purpose, so i think you only need to change the query name
in the ActiveRecord::ConnectionAdapters#log
method, this method is the one log the sql query that be executed, include the query name
.由于您只想自定义查询名称以进行监控,所以我认为您只需在ActiveRecord::ConnectionAdapters#log
方法中更改query name
,此方法是执行 sql 查询的一个日志,包括query name
.
Here is my solution:这是我的解决方案:
# lib/active_record/base.rb
# note that MUST be base.rb
# otherwise you need to add initializer to extend Rails core
#
module ActiveRecord
module ConnectionAdapters
class AbstractAdapter
attr_accessor :log_tag
private
alias old_log log
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
if name != 'SCHEMA'
name = @log_tag
@log_tag = nil # reset
end
old_log(sql, name, binds, type_casted_binds, statement_name) do
yield
end
end
end
end
module QueryMethods
def log_tag(tag_name) # class method
spawn.log_tag(tag_name)
self
end
end
module Querying
delegate :log_tag, to: :all
end
class Relation
def log_tag(tag_name) # instance method
conn = klass.connection
conn.log_tag = tag_name
self
end
end
end
Demo演示
Task.log_tag("DEMO").group(:status).count
# DEMO (0.7ms) SELECT COUNT(*) AS count_all, "tasks"."status" AS tasks_status FROM "tasks" GROUP BY "tasks"."status"
Task.where(status: 6).log_tag("SIX").first(20)
# SIX (0.8ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."status" = ? ORDER BY "tasks"."id" ASC LIMIT ?
Task.where(status: 6).first(20)
# (0.8ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."status" = ? ORDER BY "tasks"."id" ASC LIMIT ?
Note笔记
In case you want to fix query name
for specific query, you can use a hash with key is the whole the specific sql string (or hash of whole sql, such as the way Rails core cache query: query_signature = ActiveSupport::Digest.hexdigest(to_sql)
) and the value is the query name
you want. In case you want to fix query name
for specific query, you can use a hash with key is the whole the specific sql string (or hash of whole sql, such as the way Rails core cache query: query_signature = ActiveSupport::Digest.hexdigest(to_sql)
) 并且值是您想要的query name
。
# set up before hand
ActiveRecord::ConnectionAdapters::LogTags[Product.where...to_sql] = "DEMO"
# AbstractAdapter
LogTags = Hash.new
def log(sql, name...)
name = LogTags[sql]
# ...
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.