这是一个 SQL 片段:
CREATE TABLE jsonb_null (
id bigserial PRIMARY KEY,
value jsonb
);
INSERT INTO jsonb_null (value) VALUES ('"null"'), ('null'), (NULL);
SELECT id, value, jsonb_typeof(value) FROM jsonb_null ORDER BY id;
输出以下内容:
id | value | jsonb_typeof
----+--------+--------------
1 | "null" | string
2 | null | null
3 | |
(3 rows)
我想要选项 (2),其中有一个空的 jsonb 值。我怎样才能插入这个?
如果我们使用 ActiveRecord 选择一个值,这是一个失败的示例。它不一定与插入有关,但表明了问题。
require 'bundler/inline'
gemfile(true) do
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails'
gem 'pg'
end
require 'active_record'
require 'minitest/autorun'
require 'logger'
# `CREATE DATABASE rails_test;`
ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: 'rails_test')
ActiveRecord::Base.logger = Logger.new($stdout)
ActiveRecord::Base.connection.execute(<<~SQL)
DROP TABLE IF EXISTS jsonb_nulls;
CREATE TABLE jsonb_nulls (
id bigserial PRIMARY KEY,
value jsonb
);
INSERT INTO jsonb_nulls (id, value) VALUES (1, '"null"'), (2, 'null'), (3, NULL);
SQL
class JsonbNull < ActiveRecord::Base; end
class JsonbNullTest < Minitest::Test
def test_jsonb_null
refute_equal JsonbNull.find(2).value, JsonbNull.find(3).value
end
end
虽然 Postgres 对于 SQL null 和 JSONB null 有不同的类型,但 Ruby 数据库驱动程序没有,并且会将两者都转换为 nil。这就是测试通过并且应该会通过的原因。
如果要查询 JSONB null,请使用
jsonb_typeof = 'null'
。这不是您可以使用查询接口生成的查询,但您可以使用 SQL 字符串或 Arel 来完成。
JsonbNull.where("jsonb_typeof(value) = 'null'")
使用常规 ActiveRecord 方法(例如
create
)创建具有 JSONB null 值的记录将非常困难。
ActiveRecord 确实不遗余力地保护您免受自己的愚蠢行为的影响,并且会逃避您抛出的任何内容,以避免潜在的 SQL 注入攻击。这甚至包括诸如
Arel::Nodes::SqlLiteral
之类的类型,这些类型通常被查询方法视为可信。
irb(main):007:0> JsonbNull.create!(value: Arel.sql("'null'::jsonb")) TRANSACTION (0.3ms) BEGIN JsonbNull Create (0.3ms) INSERT INTO "jsonb_nulls" ("value", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["value", "\"'null'::jsonb\""], ["created_at", "2024-04-03 13:30:30.928161"], ["updated_at", "2024-04-03 13:30:30.928161"]] TRANSACTION (9.5ms) COMMIT
要实现这一点,您需要使用较低级别的方法并自己构建插入语句。
我会考虑是否有更简单的方法来实现你的目标。