mirror of https://github.com/citusdata/citus.git
commit
29d340331e
|
@ -21,6 +21,7 @@
|
||||||
#include "access/nbtree.h"
|
#include "access/nbtree.h"
|
||||||
#include "catalog/pg_am.h"
|
#include "catalog/pg_am.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
|
#include "distributed/listutils.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#if PG_VERSION_NUM >= 120000
|
#if PG_VERSION_NUM >= 120000
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
|
@ -46,6 +47,13 @@ struct TableReadState
|
||||||
TupleDesc tupleDescriptor;
|
TupleDesc tupleDescriptor;
|
||||||
Relation relation;
|
Relation relation;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following are used for tables with zero columns, or when no
|
||||||
|
* columns are projected.
|
||||||
|
*/
|
||||||
|
uint64 totalRowCount;
|
||||||
|
uint64 readRowCount;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of Var pointers for columns in the query. We use this both for
|
* List of Var pointers for columns in the query. We use this both for
|
||||||
* getting vector of projected columns, and also when we want to build
|
* getting vector of projected columns, and also when we want to build
|
||||||
|
@ -112,6 +120,13 @@ ColumnarBeginRead(Relation relation, TupleDesc tupleDescriptor,
|
||||||
List *projectedColumnList, List *whereClauseList)
|
List *projectedColumnList, List *whereClauseList)
|
||||||
{
|
{
|
||||||
List *stripeList = StripesForRelfilenode(relation->rd_node);
|
List *stripeList = StripesForRelfilenode(relation->rd_node);
|
||||||
|
StripeMetadata *stripeMetadata = NULL;
|
||||||
|
|
||||||
|
uint64 totalRowCount = 0;
|
||||||
|
foreach_ptr(stripeMetadata, stripeList)
|
||||||
|
{
|
||||||
|
totalRowCount += stripeMetadata->rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We allocate all stripe specific data in the stripeReadContext, and reset
|
* We allocate all stripe specific data in the stripeReadContext, and reset
|
||||||
|
@ -135,6 +150,8 @@ ColumnarBeginRead(Relation relation, TupleDesc tupleDescriptor,
|
||||||
readState->stripeReadContext = stripeReadContext;
|
readState->stripeReadContext = stripeReadContext;
|
||||||
readState->chunkData = NULL;
|
readState->chunkData = NULL;
|
||||||
readState->deserializedChunkIndex = -1;
|
readState->deserializedChunkIndex = -1;
|
||||||
|
readState->readRowCount = 0;
|
||||||
|
readState->totalRowCount = totalRowCount;
|
||||||
|
|
||||||
return readState;
|
return readState;
|
||||||
}
|
}
|
||||||
|
@ -151,6 +168,26 @@ ColumnarReadNextRow(TableReadState *readState, Datum *columnValues, bool *column
|
||||||
StripeMetadata *stripeMetadata = readState->currentStripeMetadata;
|
StripeMetadata *stripeMetadata = readState->currentStripeMetadata;
|
||||||
MemoryContext oldContext = NULL;
|
MemoryContext oldContext = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We rely on first column's metadata in rest of this function. So for zero
|
||||||
|
* column tables we just return "true" for totalRowCount times. We do the
|
||||||
|
* same when no columns are projected.
|
||||||
|
*/
|
||||||
|
if (readState->projectedColumnList == NIL)
|
||||||
|
{
|
||||||
|
if (readState->totalRowCount == readState->readRowCount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int columnCount = readState->tupleDescriptor->natts;
|
||||||
|
memset(columnNulls, 1, sizeof(bool) * columnCount);
|
||||||
|
readState->readRowCount++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no stripes are loaded, load the next non-empty stripe. Note that when
|
* If no stripes are loaded, load the next non-empty stripe. Note that when
|
||||||
* loading stripes, we skip over chunks whose contents can be filtered with
|
* loading stripes, we skip over chunks whose contents can be filtered with
|
||||||
|
|
|
@ -240,5 +240,99 @@ SELECT * FROM test_gen_ex;
|
||||||
3 | 4
|
3 | 4
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
|
-- check removing all columns while having some data to simulate
|
||||||
|
-- table with non-zero rows but zero-columns.
|
||||||
|
-- https://github.com/citusdata/citus/issues/4626
|
||||||
|
BEGIN;
|
||||||
|
create table local(y int);
|
||||||
|
insert into local values (1), (2);
|
||||||
|
alter table local drop column y;
|
||||||
|
CREATE TABLE zero_col_columnar (like local) USING COLUMNAR;
|
||||||
|
ALTER TABLE local RENAME TO local_xxxxx;
|
||||||
|
INSERT INTO zero_col_columnar SELECT * FROM local_xxxxx;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
SELECT count(*) FROM zero_col_columnar;
|
||||||
|
count
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (costs off, summary off) SELECT * FROM zero_col_columnar;
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Custom Scan (ColumnarScan) on zero_col_columnar
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
SELECT count(*) FROM zero_col_columnar;
|
||||||
|
count
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
5
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
EXPLAIN (costs off, summary off) SELECT * FROM zero_col_columnar;
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Custom Scan (ColumnarScan) on zero_col_columnar
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
VACUUM VERBOSE zero_col_columnar;
|
||||||
|
INFO: statistics for "zero_col_columnar":
|
||||||
|
storage id: xxxxx
|
||||||
|
total file size: 16384, total data size: 0
|
||||||
|
compression rate: 1.00x
|
||||||
|
total row count: 5, stripe count: 4, average rows per stripe: 1
|
||||||
|
chunk count: 0, containing data for dropped columns: 0
|
||||||
|
|
||||||
|
ANALYZE zero_col_columnar;
|
||||||
|
VACUUM FULL zero_col_columnar;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
TRUNCATE zero_col_columnar;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
DROP TABLE zero_col_columnar;
|
||||||
|
CREATE TABLE zero_col_columnar(a int) USING columnar;
|
||||||
|
INSERT INTO zero_col_columnar SELECT i FROM generate_series(1, 5) i;
|
||||||
|
alter table zero_col_columnar drop column a;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
VACUUM VERBOSE zero_col_columnar;
|
||||||
|
INFO: statistics for "zero_col_columnar":
|
||||||
|
storage id: xxxxx
|
||||||
|
total file size: 49152, total data size: 60
|
||||||
|
compression rate: 0.40x
|
||||||
|
total row count: 8, stripe count: 4, average rows per stripe: 2
|
||||||
|
chunk count: 4, containing data for dropped columns: 4, zstd compressed: 4
|
||||||
|
|
||||||
|
ANALYZE zero_col_columnar;
|
||||||
|
VACUUM FULL zero_col_columnar;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
--
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA columnar_alter CASCADE;
|
DROP SCHEMA columnar_alter CASCADE;
|
||||||
|
|
|
@ -123,5 +123,60 @@ INSERT INTO test_gen_ex VALUES (1), (2), (3);
|
||||||
ALTER TABLE test_gen_ex ADD COLUMN y int generated always as (x+1) stored;
|
ALTER TABLE test_gen_ex ADD COLUMN y int generated always as (x+1) stored;
|
||||||
SELECT * FROM test_gen_ex;
|
SELECT * FROM test_gen_ex;
|
||||||
|
|
||||||
|
|
||||||
|
-- check removing all columns while having some data to simulate
|
||||||
|
-- table with non-zero rows but zero-columns.
|
||||||
|
-- https://github.com/citusdata/citus/issues/4626
|
||||||
|
BEGIN;
|
||||||
|
create table local(y int);
|
||||||
|
insert into local values (1), (2);
|
||||||
|
alter table local drop column y;
|
||||||
|
|
||||||
|
CREATE TABLE zero_col_columnar (like local) USING COLUMNAR;
|
||||||
|
ALTER TABLE local RENAME TO local_xxxxx;
|
||||||
|
INSERT INTO zero_col_columnar SELECT * FROM local_xxxxx;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
SELECT count(*) FROM zero_col_columnar;
|
||||||
|
EXPLAIN (costs off, summary off) SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
SELECT count(*) FROM zero_col_columnar;
|
||||||
|
EXPLAIN (costs off, summary off) SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
VACUUM VERBOSE zero_col_columnar;
|
||||||
|
ANALYZE zero_col_columnar;
|
||||||
|
VACUUM FULL zero_col_columnar;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
TRUNCATE zero_col_columnar;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
DROP TABLE zero_col_columnar;
|
||||||
|
|
||||||
|
CREATE TABLE zero_col_columnar(a int) USING columnar;
|
||||||
|
INSERT INTO zero_col_columnar SELECT i FROM generate_series(1, 5) i;
|
||||||
|
alter table zero_col_columnar drop column a;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
INSERT INTO zero_col_columnar DEFAULT VALUES;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
|
VACUUM VERBOSE zero_col_columnar;
|
||||||
|
ANALYZE zero_col_columnar;
|
||||||
|
VACUUM FULL zero_col_columnar;
|
||||||
|
|
||||||
|
SELECT * FROM zero_col_columnar;
|
||||||
|
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA columnar_alter CASCADE;
|
DROP SCHEMA columnar_alter CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue