Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iu3Af-0005Ph-HW for pgsql-hackers@arkaria.postgresql.org; Tue, 21 Jan 2020 23:42:57 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1iu39e-00018e-UE for pgsql-hackers@arkaria.postgresql.org; Tue, 21 Jan 2020 23:41:54 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iu39e-00018W-Dm for pgsql-hackers@lists.postgresql.org; Tue, 21 Jan 2020 23:41:54 +0000 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1iu39W-0001pw-Hp for pgsql-hackers@lists.postgresql.org; Tue, 21 Jan 2020 23:41:52 +0000 Received: by mail-wr1-x443.google.com with SMTP id z7so5298741wrl.13 for ; Tue, 21 Jan 2020 15:41:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=8U1LC/md8iSn6kqbzLvhPeAsP+gvcgq+0Whn0+R5KWo=; b=0Rw7/HLWa9XQW0bUMHf0RLwNuMQ6D3Y4RaZAUnSOgILUPHx81FMV1j8QM3PuSRaS+0 3i6LUOtjYOpZ1vAwtUudqmInxGbxI+kS2i4E+ouUUW9bpTqokIvo46b2ZyeYDl4zw1Qb argeueIvL04yh4PJcGff7ekeYtJW5mKwS0ejvvhxzMzU6EUldlULZ7Yrk2N8WDm+x17p /Ng+wnH2FizeH5xVwikBXv6fDEMkfilAuw/QKlUJajZHbGTEkUPz3YKAAQgLceb0snc9 O3zBFi545R2u6p29hoKnJ8wvixYPnjZCIwxw3z4RLX7tFCGAMzVKwJN88ZxlZTjkqnGP 384Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=8U1LC/md8iSn6kqbzLvhPeAsP+gvcgq+0Whn0+R5KWo=; b=HTrNPdwyMHVclL73RX++3NFx4cTOQv5J0vTzzmVRHOE2EHNTP+p9j3ijUDnHHoOEhX 2Cr3zadKxTKc8tGRz6Czg0OWFpbHvWWR67wPMSUxi/s9FLbQi9lciZJ2waT74xyFlIo0 0ZRFcF+sDbRfEmreT/9FTcnWzn9Vb9JaR7e5uxsJjwgjGLn3HlUfIAsYlAk0FkzgyMtv DpACSZO7cV3GXnmYjd3B5J0H/XakoOCfMUJTC/ePsUflh8eF/Ny5uhwvFy4Wy4A6NOj3 bOhQEEX3buBsyLP85S8QbvvaasmAqPhlZHB4ei9+lASwZyZjZ2002SyTgLrymIXnTU7i VbBw== X-Gm-Message-State: APjAAAVB5KT603sKhf4HycvBbbkeWRkgaH5ssYlUx/tgj+fNjDxOFtuF fC4cOVbjy5zxB0lpoTacOC9qcc8Il0+Fyia7 X-Google-Smtp-Source: APXvYqyVHoAy6tO4CBDTxLUjwJbTWzII7fPUL8FU40MO3QArkmyJ3zuVmxA2TJI/u5GEedlr/1wnWA== X-Received: by 2002:adf:e641:: with SMTP id b1mr7550070wrn.34.1579650104312; Tue, 21 Jan 2020 15:41:44 -0800 (PST) Received: from localhost (ip-86-49-253-92.net.upcbroadband.cz. [86.49.253.92]) by smtp.gmail.com with ESMTPSA id y17sm1397728wma.36.2020.01.21.15.41.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Jan 2020 15:41:43 -0800 (PST) Date: Wed, 22 Jan 2020 00:41:41 +0100 From: Tomas Vondra To: Pavel Stehule Cc: Philippe BEAUDOIN , PostgreSQL Hackers Subject: Re: proposal: schema variables Message-ID: <20200121234141.se4v2hygsiy3lffx@development> References: <157772317031.1198.14690129684698137065.pgcf@coridan.postgresql.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, I did a quick review of this patch today, so let me share a couple of comments. Firstly, the patch is pretty large - it has ~270kB. Not the largest patch ever, but large. I think breaking the patch into smaller pieces would significantly improve the chnce of it getting committed. Is it possible to break the patch into smaller pieces that could be applied incrementally? For example, we could move the "transactional" behavior into a separate patch, but it's not clear to me how much code would that actually move to that second patch. Any other parts that could be moved to a separate patch? I see one of the main contention points was a rather long discussion about transactional vs. non-transactional behavior. I agree with Pavel's position that the non-transactional behavior should be the default, simply because it's better aligned with what the other databases are doing (and supporting migrations seems like one of the main use cases for this feature). I do understand it may not be suitable for some other use cases, mentioned by Fabien, but IMHO it's fine to require explicit specification of transactional behavior. Well, we can't have both as default, and I don't think there's an obvious reason why it should be the other way around. Now, a bunch of comments about the code (some of that nitpicking): 1) This hunk in doc/src/sgml/catalogs.sgml still talks about "table creation" instead of schema creation: vartypmod int4 vartypmod records type-specific data supplied at table creation time (for example, the maximum length of a varchar column). It is passed to type-specific input functions and length coercion functions. The value will generally be -1 for types that do not need vartypmod. 2) This hunk in doc/src/sgml/ref/alter_default_privileges.sgml uses "role_name" instead of "variable_name" GRANT { READ | WRITE | ALL [ PRIVILEGES ] } ON VARIABLES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] 3) I find the syntax in create_variable.sgml a bit too over-complicated: CREATE [ { TEMPORARY | TEMP } ] [ { TRANSACTIONAL | TRANSACTION } ] VARIABLE [ IF NOT EXISTS ] name [ AS ] data_type ] [ COLLATE collation ] [ NOT NULL ] [ DEFAULT default_expr ] [ { ON COMMIT DROP | ON { TRANSACTIONAL | TRANSACTION } END RESET } ] Do we really need both TRANSACTION and TRANSACTIONAL? Why not just one that we already have in the grammar (i.e. TRANSACTION)? 4) I think we should rename schemavariable.h to schema_variable.h. 5) objectaddress.c has extra line after 'break;' in one switch. 6) The comment is wrong: /* * Find the ObjectAddress for a type or domain */ static ObjectAddress get_object_address_variable(List *object, bool missing_ok) 7) I think the code/comments are really inconsistent in talking about "variables" and "schema variables". For example in objectaddress.c we do these two things: case OCLASS_VARIABLE: appendStringInfoString(&buffer, "schema variable"); break; vs. case DEFACLOBJ_VARIABLE: appendStringInfoString(&buffer, " on variables"); break; That's going to be confusing for people. 8) I'm rather confused by CMD_PLAN_UTILITY, which seems to be defined merely to support LET. I'm not sure why that's necessary (Why wouldn't CMD_UTILITY be sufficient?). Having to add conditions checking for CMD_PLAN_UTILITY to various places in planner.c is rather annoying, and I wonder how likely it's this will unnecessarily break external code in extensions etc. 9) This comment in planner.c seems obsolete (not updated to reflect addition of the CMD_PLAN_UTILITY check): /* * If this is an INSERT/UPDATE/DELETE, and we're not being called from * inheritance_planner, add the ModifyTable node. */ if (parse->commandType != CMD_SELECT && parse->commandType != CMD_PLAN_UTILITY && !inheritance_update) 10) I kinda wonder what happens when a function is used in a WHERE condition, but it depends on a variable and alsu mutates it on each call ... 11) I think Query->hasSchemaVariable (in analyze.c) should be renamed to hasSchemaVariables (which reflects the other fields referring to things like window functions etc.) 12) I find it rather suspicious that we make decisions in utility.c solely based on commandType (whether it's CMD_UTILITY or not). IMO it's pretty strange/ugly that T_LetStmt can be both CMD_UTILITY and CMD_PLAN_UTILITY: case T_LetStmt: { if (pstmt->commandType == CMD_UTILITY) doLetStmtReset(pstmt); else { Assert(pstmt->commandType == CMD_PLAN_UTILITY); doLetStmtEval(pstmt, params, queryEnv, queryString); } if (completionTag) strcpy(completionTag, "LET"); } break; 13) Not sure why we moved DO_TABLE in addBoundaryDependencies (pg_dump.c), seems unnecessary: case DO_CONVERSION: - case DO_TABLE: + case DO_VARIABLE: case DO_ATTRDEF: + case DO_TABLE: case DO_PROCLANG: 14) namespace.c defines VariableIsVisible twice: extern bool VariableIsVisible(Oid relid); ... extern bool VariableIsVisible(Oid varid); 15) I'd say lookup_variable and identify_variable should use camelcase just like the other functions in the same file. regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services