]> granicus.if.org Git - postgresql/commitdiff
Fix jit compilation bug on wide tables.
authorAndres Freund <andres@anarazel.de>
Tue, 27 Nov 2018 18:07:03 +0000 (10:07 -0800)
committerAndres Freund <andres@anarazel.de>
Tue, 27 Nov 2018 18:07:03 +0000 (10:07 -0800)
The function generated to perform JIT compiled tuple deforming failed
when HeapTupleHeader's t_hoff was bigger than a signed int8. I'd
failed to realize that LLVM's getelementptr would treat an int8 index
argument as signed, rather than unsigned.  That means that a hoff
larger than 127 would result in a negative offset being applied.  Fix
that by widening the index to 32bit.

Add a testcase with a wide table. Don't drop it, as it seems useful to
verify other tools deal properly with wide tables.

Thanks to Justin Pryzby for both reporting a bug and then reducing it
to a reproducible testcase!

Reported-By: Justin Pryzby
Author: Andres Freund
Discussion: https://postgr.es/m/20181115223959.GB10913@telsasoft.com
Backpatch: 11, just as jit compilation was

src/backend/jit/llvm/llvmjit_deform.c
src/test/regress/expected/create_table.out
src/test/regress/expected/sanity_check.out
src/test/regress/sql/create_table.sql

index 4111bf0a54beebfe2a5d59938972f2add0c0c217..d168eae087311b3301d4bd7753a5185312433e44 100644 (file)
@@ -248,10 +248,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
                                                        v_infomask2,
                                                        "maxatt");
 
+       /*
+        * Need to zext, as getelementptr otherwise treats hoff as a signed 8bit
+        * integer, which'd yield a negative offset for t_hoff > 127.
+        */
        v_hoff =
-               l_load_struct_gep(b, v_tuplep,
-                                                 FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
-                                                 "t_hoff");
+               LLVMBuildZExt(b,
+                                         l_load_struct_gep(b, v_tuplep,
+                                                                               FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
+                                                                               ""),
+                                         LLVMInt32Type(), "t_hoff");
 
        v_tupdata_base =
                LLVMBuildGEP(b,
index e92748c1ea0396644c2589236121db772cdc8c98..b26b4e7b6d9bb0f975b4d835c3a72c17a76970b3 100644 (file)
@@ -261,6 +261,16 @@ ERROR:  relation "as_select1" already exists
 CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 NOTICE:  relation "as_select1" already exists, skipping
 DROP TABLE as_select1;
+-- create an extra wide table to test for issues related to that
+-- (temporarily hide query, to avoid the long CREATE TABLE stmt)
+\set ECHO none
+INSERT INTO extra_wide_table(firstc, lastc) VALUES('first col', 'last col');
+SELECT firstc, lastc FROM extra_wide_table;
+  firstc   |  lastc   
+-----------+----------
+ first col | last col
+(1 row)
+
 -- check that tables with oids cannot be created anymore
 CREATE TABLE withoid() WITH OIDS;
 ERROR:  syntax error at or near "OIDS"
index c77060d36c1cb960cf03f77e9099643abac50d55..009a89fc1ad4d6d4247bdd8de4ab363c679c4e5e 100644 (file)
@@ -44,6 +44,7 @@ dupindexcols|t
 e_star|f
 emp|f
 equipment_r|f
+extra_wide_table|f
 f_star|f
 fast_emp4000|t
 float4_tbl|f
index 90cc1a578f37d795c3e0da94938e722bade1e954..c6f048f8c2acadfdff4b9c5ef4812fd6fccfd6f5 100644 (file)
@@ -277,6 +277,16 @@ CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 DROP TABLE as_select1;
 
+-- create an extra wide table to test for issues related to that
+-- (temporarily hide query, to avoid the long CREATE TABLE stmt)
+\set ECHO none
+SELECT 'CREATE TABLE extra_wide_table(firstc text, '|| array_to_string(array_agg('c'||i||' bool'),',')||', lastc text);'
+FROM generate_series(1, 1100) g(i)
+\gexec
+\set ECHO all
+INSERT INTO extra_wide_table(firstc, lastc) VALUES('first col', 'last col');
+SELECT firstc, lastc FROM extra_wide_table;
+
 -- check that tables with oids cannot be created anymore
 CREATE TABLE withoid() WITH OIDS;
 CREATE TABLE withoid() WITH (oids);