Обсуждение: BUG #8399: inconsistent input of multidimensional arrays
The following bug has been logged on the website: Bug reference: 8399 Logged by: Alexey Borzov Email address: borz_off@cs.msu.su PostgreSQL version: 9.3rc1 Operating system: irrelevant Description: PostgreSQL documentation states: "Multidimensional arrays must have matching extents for each dimension. A mismatch causes an error..." This is not completely true: postgres=# select cast('{{1,2}, {3}}' as integer[]); ERROR: multidimensional arrays must have array expressions with matching dimensions LINE 1: select cast('{{1,2}, {3}}' as integer[]); ^ postgres=# select cast('{{1}, {2,3}}' as integer[]); int4 ------------------ {{1,NULL},{2,3}} (1 row) Trying to use an array constructor yields an expected error in both cases. Confirmed on 9.3rc1 and 9.0.13
On Tue, Aug 27, 2013 at 08:18:10AM +0000, borz_off@cs.msu.su wrote: > PostgreSQL documentation states: > > > "Multidimensional arrays must have matching extents for each dimension. A > mismatch causes an error..." > > > This is not completely true: > postgres=# select cast('{{1,2}, {3}}' as integer[]); > ERROR: multidimensional arrays must have array expressions with matching > dimensions > LINE 1: select cast('{{1,2}, {3}}' as integer[]); > ^ > postgres=# select cast('{{1}, {2,3}}' as integer[]); > int4 > ------------------ > {{1,NULL},{2,3}} > (1 row) > > > Trying to use an array constructor yields an expected error in both cases. > > > Confirmed on 9.3rc1 and 9.0.13 This is a very interesting report. The behavior you are seeing is based on this 2004 commit: commit 0e13d627bebad769498696b5fd0ac821bde5140d Author: Joe Conway <mail@joeconway.com> Date: Thu Aug 5 03:30:44 2004 +0000 Require that array literals produce "rectangular" arrays, i.e. all the subarrays of a given dimension have the same number of elements/subarrays. Also repair a longstanding undocumented (as far as I can see) ability to explicitly set array bounds in the array literal syntax. It now can deal properly with negative array indicies. Modify array_out so that arrays with non-standard lower bounds (i.e. not 1) are output with the expicit dimension syntax. This fixes a longstanding issue whereby arrays with non-default lower bounds had them changed to default after a dump/reload cycle. Modify regression tests and docs to suit, and add some minimal documentation regarding the explicit dimension syntax. Particularly, this block of code: if ((nelems_last[nest_level] != 1) && (nelems[nest_level] != nelems_last[nest_level])) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("multidimensional arrays must have " "array expressions with matching " "dimensions"))); The nelems_last array is initialized to '1', so when an array comes in that is one element, no check is made. I doubt this was intended. What I have done is to change the initalization and test to -1, which seems to fix the problem. test=> select cast('{{1}, {2, 3}}' as integer[]); ERROR: multidimensional arrays must have array expressions with matching dimensions LINE 1: select cast('{{1}, {2, 3}}' as integer[]); I was a little worried that this might break existing values stored in the database, and hence dump/reload, but it seems the arrays are extended with NULLs so it loads just fine: CREATE TABLE test(x int[]); INSERT INTO test SELECT cast('{{1}, {2, 3, 4, 5}}' AS integer[]); COPY test TO stdout; {{1,NULL,NULL,NULL},{2,3,4,5}} Patch attached. The patch controls what strings are accepted as arrays and will be an incompatibility for 9.4. Joe, does this sound right? -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + Everyone has their own god. +
Вложения
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/31/2014 05:11 PM, Bruce Momjian wrote: > On Tue, Aug 27, 2013 at 08:18:10AM +0000, borz_off@cs.msu.su > wrote: >> PostgreSQL documentation states: >> >> "Multidimensional arrays must have matching extents for each >> dimension. A mismatch causes an error..." >> >> >> This is not completely true: postgres=# select cast('{{1,2}, >> {3}}' as integer[]); ERROR: multidimensional arrays must have >> array expressions with matching dimensions LINE 1: select >> cast('{{1,2}, {3}}' as integer[]); ^ postgres=# select >> cast('{{1}, {2,3}}' as integer[]); int4 ------------------ >> {{1,NULL},{2,3}} (1 row) >> >> >> Trying to use an array constructor yields an expected error in >> both cases. > Joe, does this sound right? I believe back when that 2004 commit was made, arrays did not allow NULL elements at all. So I guess this is an unintended side effect of, or a latent bug exposed by, that change. Let me take a closer look... Joe - -- Joe Conway credativ LLC: http://www.credativ.us Linux, PostgreSQL, and general Open Source Training, Service, Consulting, & 24x7 Support -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQIcBAEBAgAGBQJS7FH1AAoJEDfy90M199hlMzUP/1e6h0UioXC7HkEgW4DLrI4v V1lVWu3BB9rmQ6RBJMTA6/wJXm28X5etGrDAt0prQPMsvffNcSxZt5gStmMbvCDo 9+90ZrIYdjNJ8GKzojXYsPj7YDzXgkroyYIYW7fUyzjsJqDt8pfR8da5qDJeWyS8 44teI7hWd4RDRK2kBZlpr6gk/J8CSawBR9Noh5PdG1M39oeep2DcdjLbj+XNZB33 by4KiGi+Al8gLLpmyCZCVCukK92MrmOrauz9gyOto6wdcMjyb+rzdLnyAPUG5B/m Kk+1UZhWSKKVi4DlujHOwzvAOlLpVMSYyPb5nwACkc2dDo42Huy3hyP83lSfaCiQ Qkfvu4XglLvio0T/Ym1+dHYAEOdxn3ZdJDK2/UUuPTZwDjQbbI1+hHdIL3cJg7eH imBSQz3aiaoOL98/CBtwOromNEeKlLzqLqVZO9qiJgWJlLgbXtJEGRjp/BKYZwYy EFwxGPL0kEyS8LcGZbGVrRWrXgYerzhYahKuVgtV26HlNeml2c7bd0g7ldM5Tzzc K8g6/sH1/Kx0DUsRsx2EiCitC9DE3mXn5ZYsWxMTYduFPR6T6qcCkNML6ZlSWhHS Oi/bcQs3sNLOyCmkcXbxPHHTfPtrX7Zenj8JPSh8tkDmup9YqmtD1QHsqySxKpK1 eDWexdJBD/Ds5waDGitk =9ygd -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/31/2014 05:46 PM, Joe Conway wrote: > On 01/31/2014 05:11 PM, Bruce Momjian wrote: >> Joe, does this sound right? > Let me take a closer look... I had forgotten how convoluted the array code is ;-) Yes, it looks correct to me, although I think I would initialize nelems_last[i] to 0 rather than -1. Joe - -- Joe Conway credativ LLC: http://www.credativ.us Linux, PostgreSQL, and general Open Source Training, Service, Consulting, & 24x7 Support -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQIcBAEBAgAGBQJS7IsEAAoJEDfy90M199hlH4YP/1ERkU0XEnZc2FWVANg8NLKk kW3rIa+Q8UUHPVPuhD1GXSXsxBBs5XwJz9rWaTB05iO678eft1FvT2IHciCMKX2m 83FFkXQEEVLr26py+zBnuOVbnmpQ2ubmbr4ZL2fG7KYRzJkPGw4YNmXVWXgyOmOQ gltB3G1q2bNvovIz8OAXkFxkDOjdxfWdbRpoT6pYTGt/wIa5AfWLYxU5v30WZXSC rr0b5rJtn6y4+L2ZsU8HptMVOklbZOkD7+Oee7h5UMB2MazBFMKksaCuBuPGXqJj 2MKtb47xccWWY1mNVF9gdPUSIXtYDDtNjlsBnbP5bWO09UOEuSmoBZd4qG4XKI4b 3dLRskgHZfT5gZVEDaF+vS/7OHI0nGPKhgfT1kNGJZpSpbo5M7lRdcX+lCO4mTkz 7JPZoWmsUqAc8n0eEX/UuwTJL/mzFzowJ0YxaVnqRooIhXwDnQjYCydSuA8mtpTP +qY4IV/4u6yK7c5tM8cOX9ZDkriXvF6yypeIvqKLzHwnu4/6D0RHIusY0fFC+GGY 1jBWHjLYywl59ThauRqWhONiqN1F0roOK0nbdwxe3mw8n+hu/wwmCpyWlPDxUaEa CFXEN5b6uLXDM3Dy0RzvyFn2o0/c9dlleZWp7L8cV+WcU7iULo0LNMli90I+FK9z Cho3QAatYJ6QovloFps/ =XbLY -----END PGP SIGNATURE-----
On Fri, Jan 31, 2014 at 09:49:56PM -0800, Joe Conway wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On 01/31/2014 05:46 PM, Joe Conway wrote: > > On 01/31/2014 05:11 PM, Bruce Momjian wrote: > >> Joe, does this sound right? > > > Let me take a closer look... > > I had forgotten how convoluted the array code is ;-) > > Yes, it looks correct to me, although I think I would initialize > nelems_last[i] to 0 rather than -1. Thanks for the review. I went with zero as you suggested. Applied patch attached. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + Everyone has their own god. +