1CREATE TABLE test_tablesample (id int, name text) WITH (fillfactor=10);
2-- use fillfactor so we don't have to load too much data to get multiple pages
3INSERT INTO test_tablesample
4  SELECT i, repeat(i::text, 200) FROM generate_series(0, 9) s(i);
5SELECT t.id FROM test_tablesample AS t TABLESAMPLE SYSTEM (50) REPEATABLE (0);
6 id
7----
8  3
9  4
10  5
11  6
12  7
13  8
14(6 rows)
15
16SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (100.0/11) REPEATABLE (0);
17 id
18----
19(0 rows)
20
21SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0);
22 id
23----
24  3
25  4
26  5
27  6
28  7
29  8
30(6 rows)
31
32SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (50) REPEATABLE (0);
33 id
34----
35  4
36  5
37  6
38  7
39  8
40(5 rows)
41
42SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (5.5) REPEATABLE (0);
43 id
44----
45  7
46(1 row)
47
48-- 100% should give repeatable count results (ie, all rows) in any case
49SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100);
50 count
51-------
52    10
53(1 row)
54
55SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100) REPEATABLE (1+2);
56 count
57-------
58    10
59(1 row)
60
61SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100) REPEATABLE (0.4);
62 count
63-------
64    10
65(1 row)
66
67CREATE VIEW test_tablesample_v1 AS
68  SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (10*2) REPEATABLE (2);
69CREATE VIEW test_tablesample_v2 AS
70  SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (99);
71\d+ test_tablesample_v1
72                     View "public.test_tablesample_v1"
73 Column |  Type   | Collation | Nullable | Default | Storage | Description
74--------+---------+-----------+----------+---------+---------+-------------
75 id     | integer |           |          |         | plain   |
76View definition:
77 SELECT test_tablesample.id
78   FROM test_tablesample TABLESAMPLE system ((10 * 2)) REPEATABLE (2);
79
80\d+ test_tablesample_v2
81                     View "public.test_tablesample_v2"
82 Column |  Type   | Collation | Nullable | Default | Storage | Description
83--------+---------+-----------+----------+---------+---------+-------------
84 id     | integer |           |          |         | plain   |
85View definition:
86 SELECT test_tablesample.id
87   FROM test_tablesample TABLESAMPLE system (99);
88
89-- check a sampled query doesn't affect cursor in progress
90BEGIN;
91DECLARE tablesample_cur CURSOR FOR
92  SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0);
93FETCH FIRST FROM tablesample_cur;
94 id
95----
96  3
97(1 row)
98
99FETCH NEXT FROM tablesample_cur;
100 id
101----
102  4
103(1 row)
104
105FETCH NEXT FROM tablesample_cur;
106 id
107----
108  5
109(1 row)
110
111SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0);
112 id
113----
114  3
115  4
116  5
117  6
118  7
119  8
120(6 rows)
121
122FETCH NEXT FROM tablesample_cur;
123 id
124----
125  6
126(1 row)
127
128FETCH NEXT FROM tablesample_cur;
129 id
130----
131  7
132(1 row)
133
134FETCH NEXT FROM tablesample_cur;
135 id
136----
137  8
138(1 row)
139
140FETCH FIRST FROM tablesample_cur;
141 id
142----
143  3
144(1 row)
145
146FETCH NEXT FROM tablesample_cur;
147 id
148----
149  4
150(1 row)
151
152FETCH NEXT FROM tablesample_cur;
153 id
154----
155  5
156(1 row)
157
158FETCH NEXT FROM tablesample_cur;
159 id
160----
161  6
162(1 row)
163
164FETCH NEXT FROM tablesample_cur;
165 id
166----
167  7
168(1 row)
169
170FETCH NEXT FROM tablesample_cur;
171 id
172----
173  8
174(1 row)
175
176CLOSE tablesample_cur;
177END;
178EXPLAIN (COSTS OFF)
179  SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (2);
180                             QUERY PLAN
181--------------------------------------------------------------------
182 Sample Scan on test_tablesample
183   Sampling: system ('50'::real) REPEATABLE ('2'::double precision)
184(2 rows)
185
186EXPLAIN (COSTS OFF)
187  SELECT * FROM test_tablesample_v1;
188                             QUERY PLAN
189--------------------------------------------------------------------
190 Sample Scan on test_tablesample
191   Sampling: system ('20'::real) REPEATABLE ('2'::double precision)
192(2 rows)
193
194-- check inheritance behavior
195explain (costs off)
196  select count(*) from person tablesample bernoulli (100);
197                   QUERY PLAN
198-------------------------------------------------
199 Aggregate
200   ->  Append
201         ->  Sample Scan on person person_1
202               Sampling: bernoulli ('100'::real)
203         ->  Sample Scan on emp person_2
204               Sampling: bernoulli ('100'::real)
205         ->  Sample Scan on student person_3
206               Sampling: bernoulli ('100'::real)
207         ->  Sample Scan on stud_emp person_4
208               Sampling: bernoulli ('100'::real)
209(10 rows)
210
211select count(*) from person tablesample bernoulli (100);
212 count
213-------
214    58
215(1 row)
216
217select count(*) from person;
218 count
219-------
220    58
221(1 row)
222
223-- check that collations get assigned within the tablesample arguments
224SELECT count(*) FROM test_tablesample TABLESAMPLE bernoulli (('1'::text < '0'::text)::int);
225 count
226-------
227     0
228(1 row)
229
230-- check behavior during rescans, as well as correct handling of min/max pct
231select * from
232  (values (0),(100)) v(pct),
233  lateral (select count(*) from tenk1 tablesample bernoulli (pct)) ss;
234 pct | count
235-----+-------
236   0 |     0
237 100 | 10000
238(2 rows)
239
240select * from
241  (values (0),(100)) v(pct),
242  lateral (select count(*) from tenk1 tablesample system (pct)) ss;
243 pct | count
244-----+-------
245   0 |     0
246 100 | 10000
247(2 rows)
248
249explain (costs off)
250select pct, count(unique1) from
251  (values (0),(100)) v(pct),
252  lateral (select * from tenk1 tablesample bernoulli (pct)) ss
253  group by pct;
254                       QUERY PLAN
255--------------------------------------------------------
256 HashAggregate
257   Group Key: "*VALUES*".column1
258   ->  Nested Loop
259         ->  Values Scan on "*VALUES*"
260         ->  Sample Scan on tenk1
261               Sampling: bernoulli ("*VALUES*".column1)
262(6 rows)
263
264select pct, count(unique1) from
265  (values (0),(100)) v(pct),
266  lateral (select * from tenk1 tablesample bernoulli (pct)) ss
267  group by pct;
268 pct | count
269-----+-------
270 100 | 10000
271(1 row)
272
273select pct, count(unique1) from
274  (values (0),(100)) v(pct),
275  lateral (select * from tenk1 tablesample system (pct)) ss
276  group by pct;
277 pct | count
278-----+-------
279 100 | 10000
280(1 row)
281
282-- errors
283SELECT id FROM test_tablesample TABLESAMPLE FOOBAR (1);
284ERROR:  tablesample method foobar does not exist
285LINE 1: SELECT id FROM test_tablesample TABLESAMPLE FOOBAR (1);
286                                                    ^
287SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (NULL);
288ERROR:  TABLESAMPLE parameter cannot be null
289SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (NULL);
290ERROR:  TABLESAMPLE REPEATABLE parameter cannot be null
291SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (-1);
292ERROR:  sample percentage must be between 0 and 100
293SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (200);
294ERROR:  sample percentage must be between 0 and 100
295SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (-1);
296ERROR:  sample percentage must be between 0 and 100
297SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (200);
298ERROR:  sample percentage must be between 0 and 100
299SELECT id FROM test_tablesample_v1 TABLESAMPLE BERNOULLI (1);
300ERROR:  TABLESAMPLE clause can only be applied to tables and materialized views
301LINE 1: SELECT id FROM test_tablesample_v1 TABLESAMPLE BERNOULLI (1)...
302                       ^
303INSERT INTO test_tablesample_v1 VALUES(1);
304ERROR:  cannot insert into view "test_tablesample_v1"
305DETAIL:  Views containing TABLESAMPLE are not automatically updatable.
306HINT:  To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.
307WITH query_select AS (SELECT * FROM test_tablesample)
308SELECT * FROM query_select TABLESAMPLE BERNOULLI (5.5) REPEATABLE (1);
309ERROR:  TABLESAMPLE clause can only be applied to tables and materialized views
310LINE 2: SELECT * FROM query_select TABLESAMPLE BERNOULLI (5.5) REPEA...
311                      ^
312SELECT q.* FROM (SELECT * FROM test_tablesample) as q TABLESAMPLE BERNOULLI (5);
313ERROR:  syntax error at or near "TABLESAMPLE"
314LINE 1: ...CT q.* FROM (SELECT * FROM test_tablesample) as q TABLESAMPL...
315                                                             ^
316-- check partitioned tables support tablesample
317create table parted_sample (a int) partition by list (a);
318create table parted_sample_1 partition of parted_sample for values in (1);
319create table parted_sample_2 partition of parted_sample for values in (2);
320explain (costs off)
321  select * from parted_sample tablesample bernoulli (100);
322                QUERY PLAN
323-------------------------------------------
324 Append
325   ->  Sample Scan on parted_sample_1
326         Sampling: bernoulli ('100'::real)
327   ->  Sample Scan on parted_sample_2
328         Sampling: bernoulli ('100'::real)
329(5 rows)
330
331drop table parted_sample, parted_sample_1, parted_sample_2;
332