Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-28 Thread Piotr Stefaniak

On 2016-03-28 11:33, Aleksander Alekseev wrote:

Hello, Piotr.

Thanks for report. But I'm having some difficulties reproducing issues
you described.


Oh, if you want backtraces then either set a conditional breakpoint or 
add your own Assert like I did.



Also it would be a good idea to include these steps to regression tests.


I agree and I generally think that the more test cases touch previously 
not covered code paths the better, even if it had to be run as a 
different make(1) target. Although it seems that at least some people 
would agree (see [1]), the "make check" split somehow isn't happening.


[1] ca+tgmoymofe94+3wg3spg9sqajkv4sixjey+rdrmamye-vq...@mail.gmail.com



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-28 Thread Aleksander Alekseev
Hello, Piotr.

Thanks for report. But I'm having some difficulties reproducing issues
you described.

I compiled PostgreSQL from master branch on FreeBSD 10.2 using this
command:

```
CC=/usr/local/bin/gcc49 CFLAGS="-O0 -g" \
  ./configure --enable-cassert --enable-debug \
  --prefix=/home/eax/postgresql-install \
  && gmake clean && gmake -j2 -s
```

Then I run reinit.sh:

```
#!/usr/bin/env bash

P=~/postgresql-install

pkill -9 postgres
make install

rm -rf $P/data
$P/bin/initdb -D $P/data

echo "max_prepared_transactions = 100" >> $P/data/postgresql.conf
echo "wal_level = hot_standby" >> $P/data/postgresql.conf
echo "wal_keep_segments = 128" >> $P/data/postgresql.conf
echo "max_connections = 10" >> $P/data/postgresql.conf
echo "listen_addresses = '*'" >> $P/data/postgresql.conf

echo '' > $P/data/logfile

echo "host all all 0.0.0.0/0 trust" >> $P/data/pg_hba.conf
echo "host replication all 0.0.0.0/0 trust" >> $P/data/pg_hba.conf
echo "local replication all trust" >> $P/data/pg_hba.conf

$P/bin/pg_ctl -w -D $P/data -l $P/data/logfile start
$P/bin/createdb `whoami`
$P/bin/psql -c "create table test(k int primary key, v text);"
```

..., connected to PostgreSQL using psql, in second terminal I attached
to the backend process using gdb710 and input `c`. Now in psql:

```
eax=# create table tt5(x int);
CREATE TABLE
eax=# create table b_star(x int);
CREATE TABLE
eax=# insert into b_star values (1), (2), (3);
INSERT 0 3
eax=# insert into tt5 values (2), (3), (4), (5);
INSERT 0 4
eax=# select 1
eax-# from public.tt5 as subq_0
eax-# where EXISTS (
eax(#select 1
eax(#from public.b_star as ref_0
eax(#where false
eax(# );
 ?column? 
--
(0 rows)

eax=# select 1
eax-# from unnest('{}'::boolean[]) a (x)
eax-# left join (
eax(#select *
eax(#from unnest('{}'::boolean[])
eax(#where false
eax(# ) b (x) on a.x = b.x;
 ?column? 
--
(0 rows)

```

Everything seems to work, no stacktraces in gdb.

Could you please provide more concrete steps to reproduce these
issues i.e, OS and compiler version, compilation flags (or package
version), cluster config, database schema, etc? These steps are required
at least to make sure that fixed code really fixes a problem. Also it
would be a good idea to include these steps to regression tests.

-- 
Best regards,
Aleksander Alekseev
http://eax.me/


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-27 Thread Tom Lane
Piotr Stefaniak  writes:
> On the exact same note, something like this (again reduced from what 
> sqlsmith produced):
> leads to vardata.rel->tuples being zero here:
>   if (vardata.rel)
>   ndistinct *= vardata.rel->rows / vardata.rel->tuples;

Ugh.  That's a bit worse because it'll be 0/0, ie you get a NaN.
Thanks for the report.

regards, tom lane


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-27 Thread Tom Lane
Piotr Stefaniak  writes:
> I'm not saying this is necessarily a bug since the whole function deals 
> with floats, but perhaps it's interesting to note that ndistinct can be 
> 0 in src/backend/utils/adt/selfuncs.c:estimate_hash_bucketsize:

I think it's basically cosmetic unless you've got a machine that traps
zero divide, but still that's good to fix.  Thanks for the report!

regards, tom lane


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-27 Thread Piotr Stefaniak

On 2016-03-26 19:29, Piotr Stefaniak wrote:

I'm not saying this is necessarily a bug since the whole function deals
with floats, but perhaps it's interesting to note that ndistinct can be
0 in src/backend/utils/adt/selfuncs.c:estimate_hash_bucketsize:


On the exact same note, something like this (again reduced from what 
sqlsmith produced):


select 1
from unnest('{}'::boolean[]) a (x)
left join (
  select *
  from unnest('{}'::boolean[])
  where false
) b (x) on a.x = b.x;

leads to vardata.rel->tuples being zero here:
if (vardata.rel)
ndistinct *= vardata.rel->rows / vardata.rel->tuples;

Back-trace attached.

#0  estimate_hash_bucketsize (root=0xf3cf98, hashkey=0xf44398, nbuckets=1024) 
at src/backend/utils/adt/selfuncs.c:3543
#1  0x007141a4 in final_cost_hashjoin (root=0xf3cf98, path=0xf47118, 
workspace=0x7fffd950, sjinfo=0xf45460, semifactors=0x7fffdae8) at 
src/backend/optimizer/path/costsize.c:2856
#2  0x0075c134 in create_hashjoin_path (root=0xf3cf98, 
joinrel=0xf46438, jointype=JOIN_LEFT, workspace=0x7fffd950, 
sjinfo=0xf45460, semifactors=0x7fffdae8, outer_path=0xf461a0, 
inner_path=0xf45a98, restrict_clauses=0xf466f0, required_outer=0x0, 
hashclauses=0xf471d8) at src/backend/optimizer/util/pathnode.c:2133
#3  0x0072074a in try_hashjoin_path (root=0xf3cf98, joinrel=0xf46438, 
outer_path=0xf461a0, inner_path=0xf45a98, hashclauses=0xf471d8, 
jointype=JOIN_LEFT, extra=0x7fffdad0) at 
src/backend/optimizer/path/joinpath.c:523
#4  0x007219e2 in hash_inner_and_outer (root=0xf3cf98, 
joinrel=0xf46438, outerrel=0xf44cd0, innerrel=0xf44fa8, jointype=JOIN_LEFT, 
extra=0x7fffdad0) at src/backend/optimizer/path/joinpath.c:1403
#5  0x00720058 in add_paths_to_joinrel (root=0xf3cf98, 
joinrel=0xf46438, outerrel=0xf44cd0, innerrel=0xf44fa8, jointype=JOIN_LEFT, 
sjinfo=0xf45460, restrictlist=0xf466f0) at 
src/backend/optimizer/path/joinpath.c:211
#6  0x00722e38 in make_join_rel (root=0xf3cf98, rel1=0xf44cd0, 
rel2=0xf44fa8) at src/backend/optimizer/path/joinrels.c:771
#7  0x007222dd in make_rels_by_clause_joins (root=0xf3cf98, 
old_rel=0xf44cd0, other_rels=0xf463b8) at 
src/backend/optimizer/path/joinrels.c:274
#8  0x00721f86 in join_search_one_level (root=0xf3cf98, level=2) at 
src/backend/optimizer/path/joinrels.c:96
#9  0x0070dc4d in standard_join_search (root=0xf3cf98, levels_needed=2, 
initial_rels=0xf46380) at src/backend/optimizer/path/allpaths.c:2124
#10 0x0070dbc6 in make_rel_from_joinlist (root=0xf3cf98, 
joinlist=0xf452c8) at src/backend/optimizer/path/allpaths.c:2055
#11 0x0070b304 in make_one_rel (root=0xf3cf98, joinlist=0xf452c8) at 
src/backend/optimizer/path/allpaths.c:175
#12 0x007352be in query_planner (root=0xf3cf98, tlist=0xf440b8, 
qp_callback=0x739ec7 , qp_extra=0x7fffde10) at 
src/backend/optimizer/plan/planmain.c:246
#13 0x00737d89 in grouping_planner (root=0xf3cf98, inheritance_update=0 
'\000', tuple_fraction=0) at src/backend/optimizer/plan/planner.c:1673
#14 0x00736535 in subquery_planner (glob=0xf3ad88, parse=0xf3a458, 
parent_root=0x0, hasRecursion=0 '\000', tuple_fraction=0) at 
src/backend/optimizer/plan/planner.c:758
#15 0x00735688 in standard_planner (parse=0xf3a458, cursorOptions=256, 
boundParams=0x0) at src/backend/optimizer/plan/planner.c:307
#16 0x007353ca in planner (parse=0xf3a458, cursorOptions=256, 
boundParams=0x0) at src/backend/optimizer/plan/planner.c:177
#17 0x00800d28 in pg_plan_query (querytree=0xf3a458, cursorOptions=256, 
boundParams=0x0) at src/backend/tcop/postgres.c:798
#18 0x00800ddb in pg_plan_queries (querytrees=0xf3cf60, 
cursorOptions=256, boundParams=0x0) at src/backend/tcop/postgres.c:857
#19 0x00801080 in exec_simple_query (query_string=0xf077a8 "select 
1\nfrom unnest('{}'::boolean[]) a (x)\nleft join (\n  select *\n  from 
unnest('{}'::boolean[])\n  where false\n) b (x) on a.x = b.x;") at 
src/backend/tcop/postgres.c:1022
#20 0x00805342 in PostgresMain (argc=1, argv=0xe958d0, dbname=0xe95730 
"postgres", username=0xe95710 "me") at src/backend/tcop/postgres.c:4059
#21 0x0077ed31 in BackendRun (port=0xeb2950) at 
src/backend/postmaster/postmaster.c:4258
#22 0x0077e495 in BackendStartup (port=0xeb2950) at 
src/backend/postmaster/postmaster.c:3932
#23 0x0077ac19 in ServerLoop () at 
src/backend/postmaster/postmaster.c:1690
#24 0x0077a24e in PostmasterMain (argc=3, argv=0xe94850) at 
src/backend/postmaster/postmaster.c:1298
#25 0x006c6216 in main (argc=3, argv=0xe94850) at 
src/backend/main/main.c:228
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-26 Thread Piotr Stefaniak
I'm not saying this is necessarily a bug since the whole function deals 
with floats, but perhaps it's interesting to note that ndistinct can be 
0 in src/backend/utils/adt/selfuncs.c:estimate_hash_bucketsize:

/*
 * Initial estimate of bucketsize fraction is 1/nbuckets as long as the
 * number of buckets is less than the expected number of distinct 
values;
 * otherwise it is 1/ndistinct.
 */
if (ndistinct > nbuckets)
estfract = 1.0 / nbuckets;
else
estfract = 1.0 / ndistinct;

for this query:
select subq_0.c1 as c0
from (
  select ref_0.a as c0, (select NULL::integer from 
information_schema.user_defined_types limit 1 offset 1) as c1

  from public.rtest_nothn3 as ref_0
  limit 130
) as subq_0
left join (
  select sample_0.x as c0
  from public.insert_tbl as sample_0
  where false
) as subq_1 on subq_0.c1 = subq_1.c0;


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-26 Thread Tom Lane
Piotr Stefaniak  writes:
> using sqlsmith and UBSan I have found these two division by zero errors:

Hmm, thanks.  Seems there's a bit of a disagreement as to whether
path->rows is allowed to be zero or not.  It normally isn't; but
we've created an exception that provably-empty relations have zero
rowcount, so now these places had better deal with the case.

regards, tom lane


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] Two division by 0 errors in optimizer/plan/planner.c and optimizer/path/costsize.c

2016-03-26 Thread Piotr Stefaniak

Hi,

using sqlsmith and UBSan I have found these two division by zero errors:

src/backend/optimizer/plan/planner.c:4846
/* Convert absolute # of tuples to a fraction; no need to clamp */
if (tuple_fraction >= 1.0)
{
tuple_fraction /= best_path->rows;
}

and

src/backend/optimizer/path/costsize.c:3029
if (subplan->subLinkType == EXISTS_SUBLINK)
{
/* we only need to fetch 1 tuple */
sp_cost.per_tuple += plan_run_cost / plan->plan_rows;
}

The first is triggered by this query (reduced by me from the original 
query string generated by sqlsmith):


select 1
from (
  select ref_0.location as c0
  from public.city as ref_0
) as subq_0
where EXISTS (
  select 1
  from (
select sample_0.collname as c0
from pg_catalog.pg_collation as sample_0
  ) as subq_1
  right join public.tt5 as ref_2
inner join pg_catalog.pg_constraint as ref_4
on (ref_2.z = ref_4.coninhcount )
  on (subq_1.c0 = ref_4.conname ),
  lateral (
select 1
from public.shoelace_candelete as ref_5
where false
  ) as subq_2
);

#0  get_cheapest_fractional_path (rel=0x77ec32a8, tuple_fraction=1) 
at src/backend/optimizer/plan/planner.c:4846
#1  0x007422a1 in make_subplan (root=0xf49778, 
orig_subquery=0x77f593c8, subLinkType=EXISTS_SUBLINK, subLinkId=0, 
testexpr=0x0, isTopQual=1 '\001') at 
src/backend/optimizer/plan/subselect.c:546
#2  0x0074470d in process_sublinks_mutator (node=0x77f610b0, 
context=0x7fffd900) at src/backend/optimizer/plan/subselect.c:1974
#3  0x00744670 in SS_process_sublinks (root=0xf49778, 
expr=0x77f610b0, isQual=1 '\001') at 
src/backend/optimizer/plan/subselect.c:1947
#4  0x00736621 in preprocess_expression (root=0xf49778, 
expr=0x77f610b0, kind=0) at src/backend/optimizer/plan/planner.c:848
#5  0x00736700 in preprocess_qual_conditions (root=0xf49778, 
jtnode=0xf5f790) at src/backend/optimizer/plan/planner.c:893
#6  0x00735ff3 in subquery_planner (glob=0xf3ef70, 
parse=0xf3e9a0, parent_root=0x0, hasRecursion=0 '\000', 
tuple_fraction=0) at src/backend/optimizer/plan/planner.c:600
#7  0x0073566b in standard_planner (parse=0xf3e9a0, 
cursorOptions=256, boundParams=0x0) at 
src/backend/optimizer/plan/planner.c:307
#8  0x007353ad in planner (parse=0xf3e9a0, cursorOptions=256, 
boundParams=0x0) at src/backend/optimizer/plan/planner.c:177
#9  0x00800d3b in pg_plan_query (querytree=0xf3e9a0, 
cursorOptions=256, boundParams=0x0) at src/backend/tcop/postgres.c:798
#10 0x00800dee in pg_plan_queries (querytrees=0xf53648, 
cursorOptions=256, boundParams=0x0) at src/backend/tcop/postgres.c:857
#11 0x00801093 in exec_simple_query (query_string=0xf07dd8 
"select 1\nfrom (\n  select ref_0.location as c0\n  from public.city as 
ref_0\n) as subq_0\nwhere EXISTS (\n  select 1\n  from (\nselect 
sample_0.collname as c0\nfrom pg_catalog.pg_collation as sample_0\n 
 ) as subq_1\n  right join public.tt5 as ref_2\ninner join 
pg_catalog.pg_constraint as ref_4\non (ref_2.z = ref_4.coninhcount 
)\n  on (subq_1.c0 = ref_4.conname ),\n  lateral (\nselect 1\n 
from public.shoelace_candelete as ref_5\nwhere false\n  ) as 
subq_2\n);") at src/backend/tcop/postgres.c:1022
#12 0x00805355 in PostgresMain (argc=1, argv=0xe95ee0, 
dbname=0xe95d40 "regression", username=0xe95d20 "me") at 
src/backend/tcop/postgres.c:4059
#13 0x0077ed44 in BackendRun (port=0xeb2f80) at 
src/backend/postmaster/postmaster.c:4258
#14 0x0077e4a8 in BackendStartup (port=0xeb2f80) at 
src/backend/postmaster/postmaster.c:3932
#15 0x0077ac2c in ServerLoop () at 
src/backend/postmaster/postmaster.c:1690
#16 0x0077a261 in PostmasterMain (argc=5, argv=0xe94e10) at 
src/backend/postmaster/postmaster.c:1298
#17 0x006c623c in main (argc=5, argv=0xe94e10) at 
src/backend/main/main.c:228


The second one is triggered by this (again, reduced from the original):

select 1
from public.tt5 as subq_0
where EXISTS (
  select 1
  from public.b_star as ref_0
  where false
);

#0  cost_subplan (root=0xf3e718, subplan=0xf42780, plan=0xf3fcd8) at 
src/backend/optimizer/path/costsize.c:3029
#1  0x00742eb9 in build_subplan (root=0xf3e718, plan=0xf3fcd8, 
subroot=0xf3f6a8, plan_params=0x0, subLinkType=EXISTS_SUBLINK, 
subLinkId=0, testexpr=0x0, adjust_testexpr=1 '\001', unknownEqFalse=1 
'\001') at src/backend/optimizer/plan/subselect.c:887
#2  0x007422c0 in make_subplan (root=0xf3e718, 
orig_subquery=0xf09628, subLinkType=EXISTS_SUBLINK, subLinkId=0, 
testexpr=0x0, isTopQual=1 '\001') at 
src/backend/optimizer/plan/subselect.c:551
#3  0x007446d7 in process_sublinks_mutator (node=0xf3f100, 
context=0x7fffd900) at src/backend/optimizer/plan/subselect.c:1974
#4  0x0074463a in SS_process_sublinks (root=0xf3e718, 
expr=0xf3f100,