Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sp7Vt-00GkRt-Bf for pgsql-hackers@arkaria.postgresql.org; Fri, 13 Sep 2024 14:43:10 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1sp7Vs-004Brx-RU for pgsql-hackers@arkaria.postgresql.org; Fri, 13 Sep 2024 14:43:08 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sp7Vs-004BrQ-DI for pgsql-hackers@lists.postgresql.org; Fri, 13 Sep 2024 14:43:08 +0000 Received: from mail-vk1-xa34.google.com ([2607:f8b0:4864:20::a34]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1sp7Vp-000yhS-Bn for pgsql-hackers@postgresql.org; Fri, 13 Sep 2024 14:43:07 +0000 Received: by mail-vk1-xa34.google.com with SMTP id 71dfb90a1353d-502b405aa6dso650017e0c.2 for ; Fri, 13 Sep 2024 07:43:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1726238584; x=1726843384; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=MStrTa66tFQQe0eIJKS0BE5zwrgylIjU12IHIxJg63U=; b=ICfhfAM+5aotbZNdwEFOkzBifExN73nF/W6M9DgIeWOdncT8Uhjw2xl1YBnqNTGizZ r2zOQ4rwl5jpwST9rm9uPm0QIgcewGng6N1ItJMkdO1SW0Z0JPEjYkNLefeXmRQAVPqW 9EPaJeH7IMxAQwiYHRsDomjiMJ3GIftMv8rYjBU7gGdbeR+Ujbb7l7pGMbZtoMkyvw63 1xv1rFmCaFetFgGGejK8WcBIe4a9mIgy5tqUfYZ9AQnhGrT3u0BUac4z6CEhK1t3AH3r of3C7X7eypLhFA3NOKOgobTryJt0i5ZueeV1/IwlLsVj0EL6uzNK10hMVjQYPnmACy5p 3rsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726238584; x=1726843384; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MStrTa66tFQQe0eIJKS0BE5zwrgylIjU12IHIxJg63U=; b=WssfD/vnHyBi6OZJTXzqTQThKkMzx3MHmrfnYv0wLq0NvU5xzLv07DbaD1GwQ5bC+3 4IH6ufglFqW0R9XYPGWL3MbMRpuIAFrT2d34K7ckmm7Omzh9fK5ukPFfPLrOQBAvPFql BlIv/v5bx/RNEgw94EK3G4Bd3GokPcKwDXXoKrGDOLYTkubqnk680t0lu8u6o4v5EEdA i3rI0puP+YdEFtm8hc/gZHSdKgYatDIzk1pSm0O7DAspH50UFsldBilsaZhUB00J6ZyY eI5lj04qakkdpmtWM1bPm8MZdtJYZBJ5eaqlWtEH/2OupW0qyY24tel53gDmscmUlET+ W+3A== X-Forwarded-Encrypted: i=1; AJvYcCW0B2wFZMULrUZ0bnAP1xNsN0SleC4z+ZYuSsWIx6mdTPqPDC23oiXAjMKc4yo7zM3qGb9ePbgu6pE4eLmm@postgresql.org X-Gm-Message-State: AOJu0Yw/HJaNsjCgjohrOuI8mgGoGi7M/0Oo+7QN0luB8flIIK21zQ0X xh0xhJATRnsNCThQA9h7EOUukLUakdMLIo2E1ENrKTe7oxc8v6ZFsBhfChZJGvQHshNfdfmEOvb 5y2blemg+tOdtQYSi0+CINiqv2uM= X-Google-Smtp-Source: AGHT+IHW3y5Tmo3BPtuXLbVMq3/DW5MQbc+0lBq2T2JokXxtlBEtQz3pCkkzSXYV5qMkFHFgvs9Dc9j84qWB4gX2ApU= X-Received: by 2002:a05:6122:3b12:b0:4f6:aa3e:aa3e with SMTP id 71dfb90a1353d-5032d4ec54fmr5164372e0c.11.1726238584466; Fri, 13 Sep 2024 07:43:04 -0700 (PDT) MIME-Version: 1.0 References: <8620df11-96e4-4ca3-8f3c-33a479260961@joeconway.com> <4162f7f7-6fd6-4720-98e2-89f80e3de2ed@joeconway.com> <153b71b8-b6fb-4930-aaff-a7334cb3f6d6@joeconway.com> <8ef5f5d6-38db-4624-8eef-2d96c9eba9d4@joeconway.com> In-Reply-To: From: jian he Date: Fri, 13 Sep 2024 22:42:00 +0800 Message-ID: Subject: Re: Emitting JSON to file using COPY TO To: Joe Conway Cc: "Andrey M. Borodin" , Dean Rasheed , Daniel Verite , Andrew Dunstan , Davin Shearer , PostgreSQL-development Content-Type: multipart/mixed; boundary="000000000000a018430622013d53" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000a018430622013d53 Content-Type: text/plain; charset="UTF-8" Hi. in ExecutePlan we have: for (;;) { ResetPerTupleExprContext(estate); slot = ExecProcNode(planstate); if (!TupIsNull(slot)) { if((slot != NULL) && (slot->tts_tupleDescriptor != NULL) && (slot->tts_tupleDescriptor->natts > 0) && (slot->tts_tupleDescriptor->attrs->attname.data[0] == '\0')) elog(INFO, "%s:%d %s this slot first attribute attname is null", __FILE_NAME__, __LINE__, __func__); } if (TupIsNull(slot)) break; if (sendTuples) { if (!dest->receiveSlot(slot, dest)) break; } dest->receiveSlot(slot, dest) is responsible for sending values to destination, for COPY TO it will call copy_dest_receive, CopyOneRowTo. For the copy to format json, we need to make sure in "dest->receiveSlot(slot, dest))", the slot->tts_tupleDescriptor has proper information. because we *use* slot->tts_tupleDescriptor->attrs->attname as the json key. For example, if (slot->tts_tupleDescriptor->attrs->attname.data[0] == '\0') then output json may look like: {"":12} which is not what we want. in ExecutePlan i use elog(INFO, "%s:%d %s this slot first attribute attname is null", __FILE_NAME__, __LINE__, __func__); to find sql queries that attribute name is not good. based on that, i found out many COPY TO (FORMAT JSON) queries will either error out or the output json key be empty string if in CopyOneRowTo we didn't copy the cstate->queryDesc->tupDesc to the slot->tts_tupleDescriptor You can test it yourself. first `git am v12-0001-introduce-json-format-for-COPY-TO.patch` after that, comment out the memcpy call in CopyOneRowTo, just like the following: if(!cstate->rel) { // memcpy(TupleDescAttr(slot->tts_tupleDescriptor, 0), // TupleDescAttr(cstate->queryDesc->tupDesc, 0), // cstate->queryDesc->tupDesc->natts * sizeof(FormData_pg_attribute)); build and test with the attached script. you will see COPY TO FORMAT JSON, lots of cases where the json key becomes an empty string. I think this thread related issues has been resolved. --000000000000a018430622013d53 Content-Type: application/sql; name="scratch31.sql" Content-Disposition: attachment; filename="scratch31.sql" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_m10t5pk20 c2NyZWF0ZSB0eXBlIGNvbXBvc3R5cGUgYXMgKHggaW50LCB5IHZhcmNoYXIpOwoKY3JlYXRlIG9y IHJlcGxhY2UgZnVuY3Rpb24gY29tcG9zKCkgcmV0dXJucyBjb21wb3N0eXBlIGFzICQkCmJlZ2lu CiAgcmV0dXJuICgxLCAnaGVsbG8nKTsKZW5kOwokJCBsYW5ndWFnZSBwbHBnc3FsOwoKY3JlYXRl IG9yIHJlcGxhY2UgZnVuY3Rpb24gY29tcG9zMSgpIHJldHVybnMgY29tcG9zdHlwZSBhcyAkJApi ZWdpbgogIHJldHVybiAoMSwgJ2hlbGxvJzo6dmFyY2hhcik7CmVuZDsKJCQgbGFuZ3VhZ2UgcGxw Z3NxbDsKCmNyZWF0ZSBvciByZXBsYWNlIGZ1bmN0aW9uIGYyKCkgcmV0dXJucyBzZXRvZiBpbnQg YXMgJCQKYmVnaW4KICByZXR1cm4gcXVlcnkgc2VsZWN0IDEgdW5pb24gYWxsIHNlbGVjdCAyOwpl bmQ7CiQkIGxhbmd1YWdlIHBscGdzcWw7CgpjcmVhdGUgb3IgcmVwbGFjZSBmdW5jdGlvbiBmMygp IHJldHVybnMgc2V0b2YgaW50IGFzICQkCmJlZ2luCiAgcmV0dXJuIHF1ZXJ5IHNlbGVjdCAxIHVu aW9uIHNlbGVjdCAyOwplbmQ7CiQkIGxhbmd1YWdlIHBscGdzcWw7CgpjcmVhdGUgb3IgcmVwbGFj ZSBmdW5jdGlvbiBmNChpbiBpIGludCwgb3V0IGogaW50KSByZXR1cm5zIHNldG9mIGludCBhcyAk JApiZWdpbgogIGogOj0gaSsxOwogIHJldHVybiBuZXh0OwogIGogOj0gaSsyOwogIHJldHVybiBu ZXh0OwogIHJldHVybjsKZW5kJCQgbGFuZ3VhZ2UgcGxwZ3NxbDsKCmNyZWF0ZSBvciByZXBsYWNl IGZ1bmN0aW9uIHJldHVybnNyZWNvcmQoaW50KSByZXR1cm5zIHJlY29yZCBsYW5ndWFnZSBwbHBn c3FsIGFzCiQkCmJlZ2luCnJldHVybiByb3coJDEsJDErMSk7CmVuZCAkJDsKCmNyZWF0ZSBvciBy ZXBsYWNlIGZ1bmN0aW9uIG15X2YzKGEgaW50ZWdlcikKcmV0dXJucyB0YWJsZSh4eHl5IGludCkg bGFuZ3VhZ2UgcGxwZ3NxbCBhcwokZnVuY3Rpb24kCmJlZ2luCiAgICByZXR1cm4gcXVlcnkgc2Vs ZWN0IGE7CmVuZDsKJGZ1bmN0aW9uJDsKCgoKCmNvcHkoU0VMRUNUICogRlJPTSBnZW5lcmF0ZV9z ZXJpZXMoJys0NTY3ODkwMTIzNDU2Nzg5Jzo6aW50OCwgJys0NTY3ODkwMTIzNDU2Nzk5Jzo6aW50 OCkpIHRvIHN0ZG91dCAoZm9ybWF0IGpzb24pOwpjb3B5KHNlbGVjdCAqIGZyb20gbXlfZjMoMSkp IHRvIHN0ZG91dCAoZm9ybWF0IGpzb24pOwpjb3B5KHNlbGVjdCBteV9mMygxKSkgdG8gc3Rkb3V0 IChmb3JtYXQganNvbik7CmNvcHkoc2VsZWN0ICogZnJvbSBmMigpKSB0byBzdGRvdXQgKGZvcm1h dCBqc29uKTsKY29weShzZWxlY3QgKiBmcm9tIGYzKCkpIHRvIHN0ZG91dCAoZm9ybWF0IGpzb24p Owpjb3B5KHNlbGVjdCAqIGZyb20gZjQoMTEpKSB0byBzdGRvdXQgKGZvcm1hdCBqc29uKTsKY29w eShzZWxlY3QgY29tcG9zMSgpKSB0byBzdGRvdXQgKGZvcm1hdCBqc29uKTsKY29weShzZWxlY3Qg KiBmcm9tIGNvbXBvczEoKSkgdG8gc3Rkb3V0IChmb3JtYXQganNvbik7CmNvcHkoc2VsZWN0ICog ZnJvbSByZXR1cm5zcmVjb3JkKDQyKSBhcyByKHh4eDEgaW50LCB6MSBpbnQpKSB0byBzdGRvdXQg KGZvcm1hdCBqc29uKTs= --000000000000a018430622013d53--