active_record_upsert
active_record_upsert copied to clipboard
ActiveRecord::StatementInvalid: PG::InternalError: ERROR: virtual tuple table slot does not have system attributes
Code:
class WebSession < ActiveRecord::Base
self.primary_key = :id
upsert_keys [:tenant_id, :session_id]
belongs_to :tenant
end
WebSession.upsert!(tenant: tenant_id, session_id: session_id, value: {})
SQL generated:
INSERT INTO "web_sessions"
("tenant_id", "session_id", "value", "created_at", "updated_at") VALUES ('9b893bf4-bb94-4721-a6e8-03b2bd55d81e', '893f5cc3-d31a-4751-8daa-7c9acfd23ad9', '{}', '2020-09-30 07:57:45.535047', '2020-09-30 07:57:45.535047')
ON CONFLICT ("tenant_id","session_id")
DO UPDATE SET "tenant_id" = '9b893bf4-bb94-4721-a6e8-03b2bd55d81e', "session_id" = '893f5cc3-d31a-4751-8daa-7c9acfd23ad9', "value" = '{}', "updated_at" = '2020-09-30 07:57:45.535047'
RETURNING *, (xmax = 0) AS _upsert_created_record
Error from PG:
ActiveRecord::StatementInvalid: PG::InternalError: ERROR: virtual tuple table slot does not have system attributes
Removing the (xmax = 0) AS _upsert_created_record
solves the issue.
Reasons why my setup is weird:
- I'm using a composite primary
(id, tenant_id)
- The table is partitioned by
tenant_id
CREATE TABLE web_sessions (
id uuid NOT NULL DEFAULT uuid_generate_v4(),
tenant_id uuid NOT NULL,
session_id uuid NOT NULL,
value jsonb NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
PRIMARY KEY (id, tenant_id)
) PARTITION BY LIST (tenant_id);
CREATE UNIQUE INDEX idx_session_ids ON web_sessions (tenant_id, session_id);
Version: 0.9.5 Rails: 5.2.4.4 Ruby 2.7.1p83 Postgres: 12.2
(Reminds me, perhaps it' relevant to learn which PostgreSQL version this happens on?) https://www.postgresql.org/message-id/20190725015448.e5a3rwa22kpnzfe3%40alap3.anarazel.de - I casually browsed this email list, which mentions work on something which had some clues about the xmax
property.
If you want to dive in to the "support composite keys" scenarios, be my guest. PRs welcome.