这是@Patrik 建议的方法的实现,适用于针对 PostgreSQL 的插入和更新。正则表达式可能需要根据其他数据库的 SQL 格式进行调整。
class ActiveRecord::ConnectionAdapters::AbstractAdapter
protected
def log_with_binary_truncate(sql, name="SQL", binds=[], &block)
binds = binds.map do |col, data|
if col.type == :binary && data.is_a?(String) && data.size > 27
data = "#{data[0,10]}[REDACTED #{data.size - 20} bytes]#{data[-10,10]}"
end
[col, data]
end
sql = sql.gsub(/(?<='\\x[0-9a-f]{20})[0-9a-f]{20,}?(?=[0-9a-f]{20}')/) do |match|
"[REDACTED #{match.size} chars]"
end
log_without_binary_truncate(sql, name, binds, &block)
end
alias_method_chain :log, :binary_truncate
end
我对此并不满意,但现在已经足够了。它保留二进制字符串的第一个和最后 10 个字节,并指示从中间删除了多少字节/字符。除非编辑的文本比替换的文本长,否则它不会编辑(即,如果没有至少 20 个字符要删除,那么“[REDACTED xx chars]”将比替换的文本长,所以没有意义) . 我没有进行性能测试来确定对编辑块使用贪婪或懒惰重复是否更快。我的本能是懒惰,所以我做了,但贪婪可能会更快,特别是如果 SQL 中只有一个二进制字段。