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 1hbojv-0000yL-Ge for psycopg@arkaria.postgresql.org; Fri, 14 Jun 2019 16:07:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hboju-0004bC-8z for psycopg@arkaria.postgresql.org; Fri, 14 Jun 2019 16:07:42 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hbojs-0004WF-LG for psycopg@lists.postgresql.org; Fri, 14 Jun 2019 16:07:42 +0000 Received: from [66.111.4.27] (helo=out3-smtp.messagingengine.com) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hbojk-0003V6-8z for psycopg@postgresql.org; Fri, 14 Jun 2019 16:07:40 +0000 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 0635E20A0E; Fri, 14 Jun 2019 12:07:11 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Fri, 14 Jun 2019 12:07:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type:content-transfer-encoding; s=fm3; bh=n aoSKD9TnBF1yD8ILS8wpB954lLBXgrIbODBM+5AvSQ=; b=H1wIWEPMjC5ZUA72g AZ2Q4B+nccaqr2L2TINpQDxgDn6sAhEIh5z6ECP8yibr+wMtCfkj7ssxRfC/okwP hUsmh5JyIZPfLbMJ5je8kqOUFlxzi4AESlZOOTM/9r06wvTqbazkmhO9u13PfXUb NrO3wUFp2rS5icuS21twnAZwbrbZiDAyEEx/pMZp6yhwKsuTcQjtZgFy+5y4rA3m wGcMdUD8C3pOr8RIwDSNq/JgGjbV62qJMP3NZM+GZ07mctWsyHD7gMqeyIPLpsI7 aCE+2ruSxgBAVk/mYEuXxFIof4QwzuOboWNS6OiDTBonssaLK9dquJQK2lnSSEyS v50NQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=naoSKD9TnBF1yD8ILS8wpB954lLBXgrIbODBM+5Av SQ=; b=B7gT8gRWMBuC0+mCwcJzkkuNjz93UnYWhnndW3/tGKV2iSiqQ5A9sBpnP 33jKaD4fSG2pC+Yg/w0JBBC+nWQXmWBvOVdrYaG54yawtG6f8B6jSUHWwEPl+PxQ uurhWgt2re7X706oCU/2QCYOZ0A9gjg40ElGQzUw+rLcmaClqRTCEItwmjtFw4VM P1jRoIUTNXDRRGpeTFETYyPpArW6S8viarkn+uMlYAd7wfRj9jo64jNbvWo+mhTJ uGLJkzUjvSgRmonsMZFVSsEJp0SREqCm0JkVoESd7yMvhFzaRoMcVeOOlGRK5HSs 2YQ+hZjm+wyt+kuKhfphN5CScQbwA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduuddrudeiuddgleekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepuffvfhfhkffffgggjggtgfesthejredttdefjeenucfhrhhomheptegurhhi rghnucfmlhgrvhgvrhcuoegrughrihgrnhdrkhhlrghvvghrsegrkhhlrghvvghrrdgtoh hmqeenucfkphepjeegrdelgedrjeefrddvvddvnecurfgrrhgrmhepmhgrihhlfhhrohhm pegrughrihgrnhdrkhhlrghvvghrsegrkhhlrghvvghrrdgtohhmnecuvehluhhsthgvrh fuihiivgeptd X-ME-Proxy: Received: from ranger.suse (unknown [74.94.73.222]) by mail.messagingengine.com (Postfix) with ESMTPA id F2D2B380073; Fri, 14 Jun 2019 12:07:09 -0400 (EDT) Subject: Re: Creating dynamically-typed tables using psycopg2's built-in formatting To: Daniel Cohen , psycopg@postgresql.org References: From: Adrian Klaver Message-ID: <356f506e-1cbd-be9a-0fd6-bc1e50d9c9e1@aklaver.com> Date: Fri, 14 Jun 2019 09:07:09 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Host-Lookup-Failed: Reverse DNS lookup failed for 66.111.4.27 (deferred) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On 6/13/19 12:28 PM, Daniel Cohen wrote: > Hi! > > I'm working on a project in Python that interacts with a PostgreSQL data > warehouse, and I'm using the psycopg2 API. I am looking to create > dynamically-typed tables. > > For example, I would like to be able to execute the following code: > > |frompsycopg2 importconnect,sql connection > =connect(host="host",port="port",database="database",user="user",password="pw")defcreate_table(tbl_name,col_name,col_type):query > =sql.SQL("CREATE TABLE {} ({} > {})".format(sql.Identifier(tbl_name),sql.Identifier(col_name),sql.Identifier(column_type)))connection.execute(query)create_table('animals','name','VARCHAR')| > > and end up with a table named "animals" that contains a column "name" of > type VARCHAR. However, when I attempt to run this, I get an error: > *'type "VARCHAR" does not exist'*. I assume psycopg2's built-in > formatter is putting double quotes around the VARCHAR type when there > should not be any. Normally, I would just work around this myself, but > the documentation is/very/clear that Python string concatenation should > never be used for fear of SQL injection attacks. Security is a concern > for this project, so I would like to know if it's possible to create > dynamically-typed tables in this fashion using pyscopg2, and if not, > whether there exists another third-party API that can do so securely. > > A second issue I've had is that when creating tables with a similar > methodology, the sql.Identifier() function does not perform as I expect > it to. When I use it to dynamically feed in table names, for example, I > get varying results. See below:| > | > > |CREATE TABLE tbl AS SELECT * FROM other_tbl;| > > in raw SQL creates a table called tbl, whereas > > |cursor.execute(sql.SQL("CREATE TABLE {} AS SELECT * FROM > other_tbl").format(sql.Identifier(tbl))| > > creates a table called "tbl". The two are different, and I'm not seeing it: cursor.execute(sql.SQL("CREATE TABLE {} AS SELECT * FROM t1").format(sql.Identifier("tbl"))) test_(aklaver)> \d ... public | t1 | table | aklaver public | tbl | table | aklaver ... The question then becomes how is the variable tbl in your script being assigned to? > > |SELECT * FROM tbl;| > > || > > returns a totally different table than > > SELECT * FROM "tbl"; > > Please let me know if I can fix either of these problems; I want to be > able to dynamically feed types into SQL queries, and I want the tables > created to be of the form tbl not "tbl". Thank you! > > Danny > > -- Adrian Klaver adrian.klaver@aklaver.com