Commit 25542d77 authored by Joe Conway's avatar Joe Conway

Add partitioned table support to sepgsql

The new partitioned table capability added a new relkind, namely
RELKIND_PARTITIONED_TABLE. Update sepgsql to treat this new relkind
exactly the same way it does RELKIND_RELATION.

In addition, add regression test coverage for partitioned tables.

Issue raised by Stephen Frost and initial patch by Mike Palmiotto.
Review by Tom Lane and Robert Haas, and editorializing by me.

Discussion: https://postgr.es/m/flat/623bcaae-112e-ced0-8c22-a84f75ae0c53%40joeconway.com
parent eef8c006
...@@ -190,6 +190,7 @@ check_relation_privileges(Oid relOid, ...@@ -190,6 +190,7 @@ check_relation_privileges(Oid relOid,
switch (relkind) switch (relkind)
{ {
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
result = sepgsql_avc_check_perms(&object, result = sepgsql_avc_check_perms(&object,
SEPG_CLASS_DB_TABLE, SEPG_CLASS_DB_TABLE,
required, required,
...@@ -225,7 +226,7 @@ check_relation_privileges(Oid relOid, ...@@ -225,7 +226,7 @@ check_relation_privileges(Oid relOid,
/* /*
* Only columns owned by relations shall be checked * Only columns owned by relations shall be checked
*/ */
if (relkind != RELKIND_RELATION) if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
return true; return true;
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -787,7 +787,8 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId) ...@@ -787,7 +787,8 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId)
case RelationRelationId: case RelationRelationId:
relForm = (Form_pg_class) GETSTRUCT(tuple); relForm = (Form_pg_class) GETSTRUCT(tuple);
if (relForm->relkind == RELKIND_RELATION) if (relForm->relkind == RELKIND_RELATION ||
relForm->relkind == RELKIND_PARTITIONED_TABLE)
objtype = SELABEL_DB_TABLE; objtype = SELABEL_DB_TABLE;
else if (relForm->relkind == RELKIND_SEQUENCE) else if (relForm->relkind == RELKIND_SEQUENCE)
objtype = SELABEL_DB_SEQUENCE; objtype = SELABEL_DB_SEQUENCE;
...@@ -811,7 +812,8 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId) ...@@ -811,7 +812,8 @@ exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId)
case AttributeRelationId: case AttributeRelationId:
attForm = (Form_pg_attribute) GETSTRUCT(tuple); attForm = (Form_pg_attribute) GETSTRUCT(tuple);
if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION) if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION &&
get_rel_relkind(attForm->attrelid) != RELKIND_PARTITIONED_TABLE)
continue; /* no need to assign security label */ continue; /* no need to assign security label */
objtype = SELABEL_DB_COLUMN; objtype = SELABEL_DB_COLUMN;
......
...@@ -54,12 +54,13 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum) ...@@ -54,12 +54,13 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
ObjectAddress object; ObjectAddress object;
Form_pg_attribute attForm; Form_pg_attribute attForm;
StringInfoData audit_name; StringInfoData audit_name;
char relkind = get_rel_relkind(relOid);
/* /*
* Only attributes within regular relation have individual security * Only attributes within regular relations or partition relations have
* labels. * individual security labels.
*/ */
if (get_rel_relkind(relOid) != RELKIND_RELATION) if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
return; return;
/* /*
...@@ -135,8 +136,9 @@ sepgsql_attribute_drop(Oid relOid, AttrNumber attnum) ...@@ -135,8 +136,9 @@ sepgsql_attribute_drop(Oid relOid, AttrNumber attnum)
{ {
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
char relkind = get_rel_relkind(relOid);
if (get_rel_relkind(relOid) != RELKIND_RELATION) if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
return; return;
/* /*
...@@ -167,8 +169,9 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum, ...@@ -167,8 +169,9 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
{ {
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
char relkind = get_rel_relkind(relOid);
if (get_rel_relkind(relOid) != RELKIND_RELATION) if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot set security label on non-regular columns"))); errmsg("cannot set security label on non-regular columns")));
...@@ -209,8 +212,9 @@ sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum) ...@@ -209,8 +212,9 @@ sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
{ {
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
char relkind = get_rel_relkind(relOid);
if (get_rel_relkind(relOid) != RELKIND_RELATION) if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
return; return;
/* /*
...@@ -291,6 +295,7 @@ sepgsql_relation_post_create(Oid relOid) ...@@ -291,6 +295,7 @@ sepgsql_relation_post_create(Oid relOid)
switch (classForm->relkind) switch (classForm->relkind)
{ {
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
tclass = SEPG_CLASS_DB_TABLE; tclass = SEPG_CLASS_DB_TABLE;
break; break;
case RELKIND_SEQUENCE: case RELKIND_SEQUENCE:
...@@ -333,7 +338,8 @@ sepgsql_relation_post_create(Oid relOid) ...@@ -333,7 +338,8 @@ sepgsql_relation_post_create(Oid relOid)
true); true);
/* /*
* Assign the default security label on the new relation * Assign the default security label on the new regular or partitioned
* relation.
*/ */
object.classId = RelationRelationId; object.classId = RelationRelationId;
object.objectId = relOid; object.objectId = relOid;
...@@ -341,10 +347,10 @@ sepgsql_relation_post_create(Oid relOid) ...@@ -341,10 +347,10 @@ sepgsql_relation_post_create(Oid relOid)
SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext); SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
/* /*
* We also assigns a default security label on columns of the new regular * We also assign a default security label on columns of a new table.
* tables.
*/ */
if (classForm->relkind == RELKIND_RELATION) if (classForm->relkind == RELKIND_RELATION ||
classForm->relkind == RELKIND_PARTITIONED_TABLE)
{ {
Relation arel; Relation arel;
ScanKeyData akey; ScanKeyData akey;
...@@ -414,12 +420,12 @@ sepgsql_relation_drop(Oid relOid) ...@@ -414,12 +420,12 @@ sepgsql_relation_drop(Oid relOid)
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
uint16_t tclass = 0; uint16_t tclass = 0;
char relkind; char relkind = get_rel_relkind(relOid);
relkind = get_rel_relkind(relOid);
switch (relkind) switch (relkind)
{ {
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
tclass = SEPG_CLASS_DB_TABLE; tclass = SEPG_CLASS_DB_TABLE;
break; break;
case RELKIND_SEQUENCE: case RELKIND_SEQUENCE:
...@@ -479,7 +485,7 @@ sepgsql_relation_drop(Oid relOid) ...@@ -479,7 +485,7 @@ sepgsql_relation_drop(Oid relOid)
/* /*
* check db_column:{drop} permission * check db_column:{drop} permission
*/ */
if (relkind == RELKIND_RELATION) if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
{ {
Form_pg_attribute attForm; Form_pg_attribute attForm;
CatCList *attrList; CatCList *attrList;
...@@ -521,11 +527,10 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel) ...@@ -521,11 +527,10 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
{ {
ObjectAddress object; ObjectAddress object;
char *audit_name; char *audit_name;
char relkind; char relkind = get_rel_relkind(relOid);
uint16_t tclass = 0; uint16_t tclass = 0;
relkind = get_rel_relkind(relOid); if (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
if (relkind == RELKIND_RELATION)
tclass = SEPG_CLASS_DB_TABLE; tclass = SEPG_CLASS_DB_TABLE;
else if (relkind == RELKIND_SEQUENCE) else if (relkind == RELKIND_SEQUENCE)
tclass = SEPG_CLASS_DB_SEQUENCE; tclass = SEPG_CLASS_DB_SEQUENCE;
...@@ -585,6 +590,7 @@ sepgsql_relation_setattr(Oid relOid) ...@@ -585,6 +590,7 @@ sepgsql_relation_setattr(Oid relOid)
switch (get_rel_relkind(relOid)) switch (get_rel_relkind(relOid))
{ {
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
tclass = SEPG_CLASS_DB_TABLE; tclass = SEPG_CLASS_DB_TABLE;
break; break;
case RELKIND_SEQUENCE: case RELKIND_SEQUENCE:
......
...@@ -32,6 +32,15 @@ CREATE TABLE regtest_table_2 (c text) inherits (regtest_table_1); ...@@ -32,6 +32,15 @@ CREATE TABLE regtest_table_2 (c text) inherits (regtest_table_1);
CREATE TABLE regtest_table_3 (x int primary key, y text); CREATE TABLE regtest_table_3 (x int primary key, y text);
---
-- partitioned table parent
CREATE TABLE regtest_ptable_1 (o int, p text) PARTITION BY RANGE (o);
-- partitioned table children
CREATE TABLE regtest_ptable_1_ones PARTITION OF regtest_ptable_1 FOR VALUES FROM ('0') TO ('10');
CREATE TABLE regtest_ptable_1_tens PARTITION OF regtest_ptable_1 FOR VALUES FROM ('10') TO ('100');
---
CREATE SEQUENCE regtest_seq_1; CREATE SEQUENCE regtest_seq_1;
CREATE VIEW regtest_view_1 AS SELECT * FROM regtest_table_1 WHERE a > 0; CREATE VIEW regtest_view_1 AS SELECT * FROM regtest_table_1 WHERE a > 0;
...@@ -55,6 +64,8 @@ ALTER SCHEMA regtest_schema_1 OWNER TO regress_sepgsql_test_user; ...@@ -55,6 +64,8 @@ ALTER SCHEMA regtest_schema_1 OWNER TO regress_sepgsql_test_user;
ALTER SCHEMA regtest_schema_1 OWNER TO regress_sepgsql_test_user; ALTER SCHEMA regtest_schema_1 OWNER TO regress_sepgsql_test_user;
ALTER TABLE regtest_table_1 OWNER TO regress_sepgsql_test_user; ALTER TABLE regtest_table_1 OWNER TO regress_sepgsql_test_user;
ALTER TABLE regtest_table_1 OWNER TO regress_sepgsql_test_user; ALTER TABLE regtest_table_1 OWNER TO regress_sepgsql_test_user;
ALTER TABLE regtest_ptable_1 OWNER TO regress_sepgsql_test_user;
ALTER TABLE regtest_ptable_1_ones OWNER TO regress_sepgsql_test_user;
ALTER SEQUENCE regtest_seq_1 OWNER TO regress_sepgsql_test_user; ALTER SEQUENCE regtest_seq_1 OWNER TO regress_sepgsql_test_user;
ALTER SEQUENCE regtest_seq_1 OWNER TO regress_sepgsql_test_user; ALTER SEQUENCE regtest_seq_1 OWNER TO regress_sepgsql_test_user;
ALTER VIEW regtest_view_1 OWNER TO regress_sepgsql_test_user; ALTER VIEW regtest_view_1 OWNER TO regress_sepgsql_test_user;
...@@ -66,6 +77,8 @@ ALTER FUNCTION regtest_func_1(text) OWNER TO regress_sepgsql_test_user; ...@@ -66,6 +77,8 @@ ALTER FUNCTION regtest_func_1(text) OWNER TO regress_sepgsql_test_user;
-- ALTER xxx SET SCHEMA -- ALTER xxx SET SCHEMA
-- --
ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2; ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2;
ALTER TABLE regtest_ptable_1 SET SCHEMA regtest_schema_2;
ALTER TABLE regtest_ptable_1_ones SET SCHEMA regtest_schema_2;
ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2; ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2;
ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2; ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2;
ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2; ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
...@@ -76,6 +89,14 @@ ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2; ...@@ -76,6 +89,14 @@ ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
ALTER DATABASE sepgsql_test_regression_1 RENAME TO sepgsql_test_regression; ALTER DATABASE sepgsql_test_regression_1 RENAME TO sepgsql_test_regression;
ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema; ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema;
ALTER TABLE regtest_table_1 RENAME TO regtest_table; ALTER TABLE regtest_table_1 RENAME TO regtest_table;
---
-- partitioned table parent
ALTER TABLE regtest_ptable_1 RENAME TO regtest_ptable;
-- partitioned table child
ALTER TABLE regtest_ptable_1_ones RENAME TO regtest_table_part;
---
ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq; ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq;
ALTER VIEW regtest_view_1 RENAME TO regtest_view; ALTER VIEW regtest_view_1 RENAME TO regtest_view;
ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func; ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func;
...@@ -121,6 +142,50 @@ ALTER TABLE regtest_table_2 NO INHERIT regtest_table; -- not supported ...@@ -121,6 +142,50 @@ ALTER TABLE regtest_table_2 NO INHERIT regtest_table; -- not supported
ALTER TABLE regtest_table_2 INHERIT regtest_table; -- not supported ALTER TABLE regtest_table_2 INHERIT regtest_table; -- not supported
ALTER TABLE regtest_table SET TABLESPACE pg_default; ALTER TABLE regtest_table SET TABLESPACE pg_default;
---
-- partitioned table parent
ALTER TABLE regtest_ptable ADD COLUMN d float;
ALTER TABLE regtest_ptable DROP COLUMN d;
ALTER TABLE regtest_ptable ALTER p SET DEFAULT 'abcd'; -- not supported by sepgsql
ALTER TABLE regtest_ptable ALTER p SET DEFAULT 'XYZ'; -- not supported by sepgsql
ALTER TABLE regtest_ptable ALTER p DROP DEFAULT; -- not supported by sepgsql
ALTER TABLE regtest_ptable ALTER p SET NOT NULL;
ALTER TABLE regtest_ptable ALTER p DROP NOT NULL;
ALTER TABLE regtest_ptable ALTER p SET STATISTICS -1;
ALTER TABLE regtest_ptable ALTER p SET (n_distinct = 999);
ALTER TABLE regtest_ptable ALTER p SET STORAGE PLAIN;
ALTER TABLE regtest_ptable ADD CONSTRAINT test_ck CHECK (p like '%abc%') NOT VALID; -- not supported by sepgsql
ALTER TABLE regtest_ptable DROP CONSTRAINT test_ck; -- not supported by sepgsql
ALTER TABLE regtest_ptable SET WITH OIDS;
ALTER TABLE regtest_ptable SET WITHOUT OIDS;
ALTER TABLE regtest_ptable SET TABLESPACE pg_default;
-- partitioned table child
ALTER TABLE regtest_table_part ALTER p SET DEFAULT 'abcd'; -- not supported by sepgsql
ALTER TABLE regtest_table_part ALTER p SET DEFAULT 'XYZ'; -- not supported by sepgsql
ALTER TABLE regtest_table_part ALTER p DROP DEFAULT; -- not supported by sepgsql
ALTER TABLE regtest_table_part ALTER p SET NOT NULL;
ALTER TABLE regtest_table_part ALTER p DROP NOT NULL;
ALTER TABLE regtest_table_part ALTER p SET STATISTICS -1;
ALTER TABLE regtest_table_part ALTER p SET (n_distinct = 999);
ALTER TABLE regtest_table_part ALTER p SET STORAGE PLAIN;
ALTER TABLE regtest_table_part ADD CONSTRAINT test_ck CHECK (p like '%abc%') NOT VALID; -- not supported by sepgsql
ALTER TABLE regtest_table_part VALIDATE CONSTRAINT test_ck; -- not supported by sepgsql
ALTER TABLE regtest_table_part DROP CONSTRAINT test_ck; -- not supported by sepgsql
CREATE TRIGGER regtest_part_test_trig BEFORE UPDATE ON regtest_table_part
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
ALTER TABLE regtest_table_part DISABLE TRIGGER regtest_part_test_trig; -- not supported by sepgsql
ALTER TABLE regtest_table_part ENABLE TRIGGER regtest_part_test_trig; -- not supported by sepgsql
ALTER TABLE regtest_table_part SET (fillfactor = 75);
ALTER TABLE regtest_table_part RESET (fillfactor);
ALTER TABLE regtest_table_part SET TABLESPACE pg_default;
---
ALTER VIEW regtest_view SET (security_barrier); ALTER VIEW regtest_view SET (security_barrier);
ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000; ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000;
......
...@@ -32,13 +32,21 @@ ALTER TABLE regtest_table ADD COLUMN z int; ...@@ -32,13 +32,21 @@ ALTER TABLE regtest_table ADD COLUMN z int;
CREATE TABLE regtest_table_2 (a int) WITH OIDS; CREATE TABLE regtest_table_2 (a int) WITH OIDS;
CREATE TABLE regtest_ptable (a int) PARTITION BY RANGE (a);
CREATE TABLE regtest_ptable_ones PARTITION OF regtest_ptable FOR VALUES FROM ('0') TO ('10');
CREATE TABLE regtest_ptable_tens PARTITION OF regtest_ptable FOR VALUES FROM ('10') TO ('100');
ALTER TABLE regtest_ptable ADD COLUMN q int;
-- corresponding toast table should not have label and permission checks -- corresponding toast table should not have label and permission checks
ALTER TABLE regtest_table_2 ADD COLUMN b text; ALTER TABLE regtest_table_2 ADD COLUMN b text;
-- VACUUM FULL internally create a new table and swap them later. -- VACUUM FULL internally create a new table and swap them later.
VACUUM FULL regtest_table; VACUUM FULL regtest_table;
VACUUM FULL regtest_ptable;
CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100; CREATE VIEW regtest_view AS SELECT * FROM regtest_table WHERE x < 100;
CREATE VIEW regtest_pview AS SELECT * FROM regtest_ptable WHERE a < 99;
CREATE SEQUENCE regtest_seq; CREATE SEQUENCE regtest_seq;
...@@ -57,8 +65,12 @@ SET SESSION AUTHORIZATION regress_sepgsql_test_user; ...@@ -57,8 +65,12 @@ SET SESSION AUTHORIZATION regress_sepgsql_test_user;
SET search_path = regtest_schema, public; SET search_path = regtest_schema, public;
CREATE TABLE regtest_table_3 (x int, y serial); CREATE TABLE regtest_table_3 (x int, y serial);
CREATE TABLE regtest_ptable_3 (o int, p serial) PARTITION BY RANGE (o);
CREATE TABLE regtest_ptable_3_ones PARTITION OF regtest_ptable_3 FOR VALUES FROM ('0') to ('10');
CREATE TABLE regtest_ptable_3_tens PARTITION OF regtest_ptable_3 FOR VALUES FROM ('10') to ('100');
CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y; CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y;
CREATE VIEW regtest_pview_2 AS SELECT * FROM regtest_ptable_3 WHERE o < p;
CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE plpgsql CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE plpgsql
AS 'BEGIN RETURN $1 * $1 < 100; END'; AS 'BEGIN RETURN $1 * $1 < 100; END';
...@@ -77,6 +89,18 @@ ALTER TABLE regtest_table_4 ...@@ -77,6 +89,18 @@ ALTER TABLE regtest_table_4
ADD CONSTRAINT regtest_tbl4_con EXCLUDE USING btree (z WITH =); ADD CONSTRAINT regtest_tbl4_con EXCLUDE USING btree (z WITH =);
DROP TABLE regtest_table_4 CASCADE; DROP TABLE regtest_table_4 CASCADE;
-- For partitioned tables
CREATE TABLE regtest_ptable_4 (x int, y int, z int) PARTITION BY RANGE (x);
CREATE TABLE regtest_ptable_4_ones PARTITION OF regtest_ptable_4 FOR VALUES FROM ('0') TO ('10');
CREATE INDEX regtest_pindex_tbl4_y ON regtest_ptable_4_ones(y);
CREATE INDEX regtest_pindex_tbl4_z ON regtest_ptable_4_ones(z);
ALTER TABLE regtest_ptable_4 ALTER COLUMN y TYPE float;
DROP INDEX regtest_pindex_tbl4_y;
ALTER TABLE regtest_ptable_4_ones
ADD CONSTRAINT regtest_ptbl4_con EXCLUDE USING btree (z WITH =);
DROP TABLE regtest_ptable_4 CASCADE;
-- --
-- DROP Permission checks (with clean-up) -- DROP Permission checks (with clean-up)
-- --
...@@ -90,7 +114,10 @@ DROP VIEW regtest_view; ...@@ -90,7 +114,10 @@ DROP VIEW regtest_view;
ALTER TABLE regtest_table DROP COLUMN y; ALTER TABLE regtest_table DROP COLUMN y;
ALTER TABLE regtest_table_2 SET WITHOUT OIDS; ALTER TABLE regtest_table_2 SET WITHOUT OIDS;
ALTER TABLE regtest_ptable DROP COLUMN q CASCADE;
DROP TABLE regtest_table; DROP TABLE regtest_table;
DROP TABLE regtest_ptable CASCADE;
DROP OWNED BY regress_sepgsql_test_user; DROP OWNED BY regress_sepgsql_test_user;
......
...@@ -27,6 +27,26 @@ SECURITY LABEL ON COLUMN t5.e IS 'system_u:object_r:sepgsql_table_t:s0'; ...@@ -27,6 +27,26 @@ SECURITY LABEL ON COLUMN t5.e IS 'system_u:object_r:sepgsql_table_t:s0';
SECURITY LABEL ON COLUMN t5.f IS 'system_u:object_r:sepgsql_ro_table_t:s0'; SECURITY LABEL ON COLUMN t5.f IS 'system_u:object_r:sepgsql_ro_table_t:s0';
SECURITY LABEL ON COLUMN t5.g IS 'system_u:object_r:sepgsql_secret_table_t:s0'; SECURITY LABEL ON COLUMN t5.g IS 'system_u:object_r:sepgsql_secret_table_t:s0';
---
-- partitioned table parent
CREATE TABLE t1p (o int, p text, q text) PARTITION BY RANGE (o);
SECURITY LABEL ON TABLE t1p IS 'system_u:object_r:sepgsql_table_t:s0';
SECURITY LABEL ON COLUMN t1p.o IS 'system_u:object_r:sepgsql_table_t:s0';
SECURITY LABEL ON COLUMN t1p.p IS 'system_u:object_r:sepgsql_ro_table_t:s0';
SECURITY LABEL ON COLUMN t1p.q IS 'system_u:object_r:sepgsql_secret_table_t:s0';
-- partitioned table children
CREATE TABLE t1p_ones PARTITION OF t1p FOR VALUES FROM ('0') TO ('10');
SECURITY LABEL ON COLUMN t1p_ones.o IS 'system_u:object_r:sepgsql_table_t:s0';
SECURITY LABEL ON COLUMN t1p_ones.p IS 'system_u:object_r:sepgsql_ro_table_t:s0';
SECURITY LABEL ON COLUMN t1p_ones.q IS 'system_u:object_r:sepgsql_secret_table_t:s0';
CREATE TABLE t1p_tens PARTITION OF t1p FOR VALUES FROM ('10') TO ('100');
SECURITY LABEL ON COLUMN t1p_tens.o IS 'system_u:object_r:sepgsql_table_t:s0';
SECURITY LABEL ON COLUMN t1p_tens.p IS 'system_u:object_r:sepgsql_ro_table_t:s0';
SECURITY LABEL ON COLUMN t1p_tens.q IS 'system_u:object_r:sepgsql_secret_table_t:s0';
---
CREATE TABLE customer (cid int primary key, cname text, ccredit text); CREATE TABLE customer (cid int primary key, cname text, ccredit text);
SECURITY LABEL ON COLUMN customer.ccredit IS 'system_u:object_r:sepgsql_secret_table_t:s0'; SECURITY LABEL ON COLUMN customer.ccredit IS 'system_u:object_r:sepgsql_secret_table_t:s0';
INSERT INTO customer VALUES (1, 'Taro', '1111-2222-3333-4444'), INSERT INTO customer VALUES (1, 'Taro', '1111-2222-3333-4444'),
...@@ -40,13 +60,22 @@ SECURITY LABEL ON FUNCTION customer_credit(int) ...@@ -40,13 +60,22 @@ SECURITY LABEL ON FUNCTION customer_credit(int)
SELECT objtype, objname, label FROM pg_seclabels SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux' WHERE provider = 'selinux'
AND objtype in ('table', 'column') AND objtype in ('table', 'column')
AND objname in ('t1', 't2', 't3', 't4', 't5', 't5.e', 't5.f', 't5.g') AND objname in ('t1', 't2', 't3', 't4',
't5', 't5.e', 't5.f', 't5.g',
't1p', 't1p.o', 't1p.p', 't1p.q',
't1p_ones', 't1p_ones.o', 't1p_ones.p', 't1p_ones.q',
't1p_tens', 't1p_tens.o', 't1p_tens.p', 't1p_tens.q')
ORDER BY objname; ORDER BY objname;
CREATE SCHEMA my_schema_1; CREATE SCHEMA my_schema_1;
CREATE TABLE my_schema_1.ts1 (a int, b text); CREATE TABLE my_schema_1.ts1 (a int, b text);
CREATE TABLE my_schema_1.pts1 (o int, p text) PARTITION BY RANGE (o);
CREATE TABLE my_schema_1.pts1_ones PARTITION OF my_schema_1.pts1 FOR VALUES FROM ('0') to ('10');
CREATE SCHEMA my_schema_2; CREATE SCHEMA my_schema_2;
CREATE TABLE my_schema_2.ts2 (x int, y text); CREATE TABLE my_schema_2.ts2 (x int, y text);
CREATE TABLE my_schema_2.pts2 (o int, p text) PARTITION BY RANGE (o);
CREATE TABLE my_schema_2.pts2_tens PARTITION OF my_schema_2.pts2 FOR VALUES FROM ('10') to ('100');
SECURITY LABEL ON SCHEMA my_schema_2 SECURITY LABEL ON SCHEMA my_schema_2
IS 'system_u:object_r:sepgsql_regtest_invisible_schema_t:s0'; IS 'system_u:object_r:sepgsql_regtest_invisible_schema_t:s0';
...@@ -67,12 +96,36 @@ SELECT * FROM t4; -- failed ...@@ -67,12 +96,36 @@ SELECT * FROM t4; -- failed
SELECT * FROM t5; -- failed SELECT * FROM t5; -- failed
SELECT e,f FROM t5; -- ok SELECT e,f FROM t5; -- ok
---
-- partitioned table parent
SELECT * FROM t1p; -- failed
SELECT o,p FROM t1p; -- ok
--partitioned table children
SELECT * FROM t1p_ones; -- failed
SELECT o FROM t1p_ones; -- ok
SELECT o,p FROM t1p_ones; -- ok
SELECT * FROM t1p_tens; -- failed
SELECT o FROM t1p_tens; -- ok
SELECT o,p FROM t1p_tens; -- ok
---
SELECT * FROM customer; -- failed SELECT * FROM customer; -- failed
SELECT cid, cname, customer_credit(cid) FROM customer; -- ok SELECT cid, cname, customer_credit(cid) FROM customer; -- ok
SELECT count(*) FROM t5; -- ok SELECT count(*) FROM t5; -- ok
SELECT count(*) FROM t5 WHERE g IS NULL; -- failed SELECT count(*) FROM t5 WHERE g IS NULL; -- failed
---
-- partitioned table parent
SELECT count(*) FROM t1p; -- ok
SELECT count(*) FROM t1p WHERE q IS NULL; -- failed
-- partitioned table children
SELECT count(*) FROM t1p_ones; -- ok
SELECT count(*) FROM t1p_ones WHERE q IS NULL; -- failed
SELECT count(*) FROM t1p_tens; -- ok
SELECT count(*) FROM t1p_tens WHERE q IS NULL; -- failed
---
INSERT INTO t1 VALUES (4, 'abc'); -- ok INSERT INTO t1 VALUES (4, 'abc'); -- ok
INSERT INTO t2 VALUES (4, 'xyz'); -- failed INSERT INTO t2 VALUES (4, 'xyz'); -- failed
INSERT INTO t3 VALUES (4, 'stu'); -- ok INSERT INTO t3 VALUES (4, 'stu'); -- ok
...@@ -81,6 +134,19 @@ INSERT INTO t5 VALUES (1,2,3); -- failed ...@@ -81,6 +134,19 @@ INSERT INTO t5 VALUES (1,2,3); -- failed
INSERT INTO t5 (e,f) VALUES ('abc', 'def'); -- failed INSERT INTO t5 (e,f) VALUES ('abc', 'def'); -- failed
INSERT INTO t5 (e) VALUES ('abc'); -- ok INSERT INTO t5 (e) VALUES ('abc'); -- ok
---
-- partitioned table parent
INSERT INTO t1p (o,p) VALUES (9, 'mno'); -- failed
INSERT INTO t1p (o) VALUES (9); -- ok
INSERT INTO t1p (o,p) VALUES (99, 'pqr'); -- failed
INSERT INTO t1p (o) VALUES (99); -- ok
-- partitioned table children
INSERT INTO t1p_ones (o,p) VALUES (9, 'mno'); -- failed
INSERT INTO t1p_ones (o) VALUES (9); -- ok
INSERT INTO t1p_tens (o,p) VALUES (99, 'pqr'); -- failed
INSERT INTO t1p_tens (o) VALUES (99); -- ok
---
UPDATE t1 SET b = b || '_upd'; -- ok UPDATE t1 SET b = b || '_upd'; -- ok
UPDATE t2 SET y = y || '_upd'; -- failed UPDATE t2 SET y = y || '_upd'; -- failed
UPDATE t3 SET t = t || '_upd'; -- failed UPDATE t3 SET t = t || '_upd'; -- failed
...@@ -89,6 +155,21 @@ UPDATE t5 SET e = 'xyz'; -- ok ...@@ -89,6 +155,21 @@ UPDATE t5 SET e = 'xyz'; -- ok
UPDATE t5 SET e = f || '_upd'; -- ok UPDATE t5 SET e = f || '_upd'; -- ok
UPDATE t5 SET e = g || '_upd'; -- failed UPDATE t5 SET e = g || '_upd'; -- failed
---
-- partitioned table parent
UPDATE t1p SET o = 9 WHERE o < 10; -- ok
UPDATE t1p SET o = 99 WHERE o >= 10; -- ok
UPDATE t1p SET o = ascii(COALESCE(p,'upd'))%10 WHERE o < 10; -- ok
UPDATE t1p SET o = ascii(COALESCE(q,'upd'))%100 WHERE o >= 10; -- failed
-- partitioned table children
UPDATE t1p_ones SET o = 9; -- ok
UPDATE t1p_ones SET o = ascii(COALESCE(p,'upd'))%10; -- ok
UPDATE t1p_ones SET o = ascii(COALESCE(q,'upd'))%10; -- failed
UPDATE t1p_tens SET o = 99; -- ok
UPDATE t1p_tens SET o = ascii(COALESCE(p,'upd'))%100; -- ok
UPDATE t1p_tens SET o = ascii(COALESCE(q,'upd'))%100; -- failed
---
DELETE FROM t1; -- ok DELETE FROM t1; -- ok
DELETE FROM t2; -- failed DELETE FROM t2; -- failed
DELETE FROM t3; -- failed DELETE FROM t3; -- failed
...@@ -97,6 +178,18 @@ DELETE FROM t5; -- ok ...@@ -97,6 +178,18 @@ DELETE FROM t5; -- ok
DELETE FROM t5 WHERE f IS NULL; -- ok DELETE FROM t5 WHERE f IS NULL; -- ok
DELETE FROM t5 WHERE g IS NULL; -- failed DELETE FROM t5 WHERE g IS NULL; -- failed
---
-- partitioned table parent
DELETE FROM t1p; -- ok
DELETE FROM t1p WHERE p IS NULL; -- ok
DELETE FROM t1p WHERE q IS NULL; -- failed
-- partitioned table children
DELETE FROM t1p_ones WHERE p IS NULL; -- ok
DELETE FROM t1p_ones WHERE q IS NULL; -- failed;
DELETE FROM t1p_tens WHERE p IS NULL; -- ok
DELETE FROM t1p_tens WHERE q IS NULL; -- failed
---
-- --
-- COPY TO/FROM statements -- COPY TO/FROM statements
-- --
...@@ -107,6 +200,17 @@ COPY t4 TO '/dev/null'; -- failed ...@@ -107,6 +200,17 @@ COPY t4 TO '/dev/null'; -- failed
COPY t5 TO '/dev/null'; -- failed COPY t5 TO '/dev/null'; -- failed
COPY t5(e,f) TO '/dev/null'; -- ok COPY t5(e,f) TO '/dev/null'; -- ok
---
-- partitioned table parent
COPY (SELECT * FROM t1p) TO '/dev/null'; -- failed
COPY (SELECT (o,p) FROM t1p) TO '/dev/null'; -- ok
-- partitioned table children
COPY t1p_ones TO '/dev/null'; -- failed
COPY t1p_ones(o,p) TO '/dev/null'; -- ok
COPY t1p_tens TO '/dev/null'; -- failed
COPY t1p_tens(o,p) TO '/dev/null'; -- ok
---
COPY t1 FROM '/dev/null'; -- ok COPY t1 FROM '/dev/null'; -- ok
COPY t2 FROM '/dev/null'; -- failed COPY t2 FROM '/dev/null'; -- failed
COPY t3 FROM '/dev/null'; -- ok COPY t3 FROM '/dev/null'; -- ok
...@@ -115,6 +219,17 @@ COPY t5 FROM '/dev/null'; -- failed ...@@ -115,6 +219,17 @@ COPY t5 FROM '/dev/null'; -- failed
COPY t5 (e,f) FROM '/dev/null'; -- failed COPY t5 (e,f) FROM '/dev/null'; -- failed
COPY t5 (e) FROM '/dev/null'; -- ok COPY t5 (e) FROM '/dev/null'; -- ok
---
-- partitioned table parent
COPY t1p FROM '/dev/null'; -- failed
COPY t1p (o) FROM '/dev/null'; -- ok
-- partitioned table children
COPY t1p_ones FROM '/dev/null'; -- failed
COPY t1p_ones (o) FROM '/dev/null'; -- ok
COPY t1p_tens FROM '/dev/null'; -- failed
COPY t1p_tens (o) FROM '/dev/null'; -- ok
---
-- --
-- Schema search path -- Schema search path
-- --
...@@ -132,6 +247,7 @@ DROP TABLE IF EXISTS t2 CASCADE; ...@@ -132,6 +247,7 @@ DROP TABLE IF EXISTS t2 CASCADE;
DROP TABLE IF EXISTS t3 CASCADE; DROP TABLE IF EXISTS t3 CASCADE;
DROP TABLE IF EXISTS t4 CASCADE; DROP TABLE IF EXISTS t4 CASCADE;
DROP TABLE IF EXISTS t5 CASCADE; DROP TABLE IF EXISTS t5 CASCADE;
DROP TABLE IF EXISTS t1p CASCADE;
DROP TABLE IF EXISTS customer CASCADE; DROP TABLE IF EXISTS customer CASCADE;
DROP SCHEMA IF EXISTS my_schema_1 CASCADE; DROP SCHEMA IF EXISTS my_schema_1 CASCADE;
DROP SCHEMA IF EXISTS my_schema_2 CASCADE; DROP SCHEMA IF EXISTS my_schema_2 CASCADE;
...@@ -64,6 +64,22 @@ INSERT INTO var_tbl VALUES (2,'xxx'), (3,'yyy'), (4,'zzz'), (5,'xyz'); ...@@ -64,6 +64,22 @@ INSERT INTO var_tbl VALUES (2,'xxx'), (3,'yyy'), (4,'zzz'), (5,'xyz');
SECURITY LABEL ON TABLE var_tbl SECURITY LABEL ON TABLE var_tbl
IS 'system_u:object_r:sepgsql_regtest_var_table_t:s0'; IS 'system_u:object_r:sepgsql_regtest_var_table_t:s0';
CREATE TABLE foo_ptbl(o int, p text) PARTITION BY RANGE (o);
CREATE TABLE foo_ptbl_ones PARTITION OF foo_ptbl FOR VALUES FROM ('0') TO ('10');
CREATE TABLE foo_ptbl_tens PARTITION OF foo_ptbl FOR VALUES FROM ('10') TO ('100');
INSERT INTO foo_ptbl VALUES (0, 'aaa'), (9,'bbb'), (10,'ccc'), (99,'ddd');
SECURITY LABEL ON TABLE foo_ptbl
IS 'system_u:object_r:sepgsql_regtest_foo_table_t:s0';
CREATE TABLE var_ptbl(q int, r text) PARTITION BY RANGE (q);
CREATE TABLE var_ptbl_ones PARTITION OF var_ptbl FOR VALUES FROM ('0') TO ('10');
CREATE TABLE var_ptbl_tens PARTITION OF var_ptbl FOR VALUES FROM ('10') TO ('100');
INSERT INTO var_ptbl VALUES (0,'xxx'), (9,'yyy'), (10,'zzz'), (99,'xyz');
SECURITY LABEL ON TABLE var_ptbl
IS 'system_u:object_r:sepgsql_regtest_var_table_t:s0';
-- --
-- Tests for default labeling behavior -- Tests for default labeling behavior
-- --
...@@ -75,10 +91,30 @@ INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu'); ...@@ -75,10 +91,30 @@ INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
CREATE TABLE t4 (m int, n text); CREATE TABLE t4 (m int, n text);
INSERT INTO t4 VALUES (1,'mmm'), (2,'nnn'), (3,'ooo'); INSERT INTO t4 VALUES (1,'mmm'), (2,'nnn'), (3,'ooo');
-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
CREATE TABLE tpart (o int, p text) PARTITION BY RANGE (o);
CREATE TABLE tpart_ones PARTITION OF tpart FOR VALUES FROM ('0') TO ('10');
-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_dba_t:s0
CREATE TABLE tpart_tens PARTITION OF tpart FOR VALUES FROM ('10') TO ('100');
INSERT INTO tpart VALUES (0, 'aaa');
INSERT INTO tpart VALUES (9, 'bbb');
INSERT INTO tpart VALUES (99, 'ccc');
SELECT objtype, objname, label FROM pg_seclabels SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux' AND objtype = 'table' AND objname in ('t1', 't2', 't3'); WHERE provider = 'selinux' AND objtype = 'table' AND objname in ('t1', 't2', 't3',
'tpart',
'tpart_ones',
'tpart_tens')
ORDER BY objname ASC;
SELECT objtype, objname, label FROM pg_seclabels SELECT objtype, objname, label FROM pg_seclabels
WHERE provider = 'selinux' AND objtype = 'column' AND (objname like 't3.%' OR objname like 't4.%'); WHERE provider = 'selinux' AND objtype = 'column' AND (objname like 't3.%'
OR objname like 't4.%'
OR objname like 'tpart.%'
OR objname like 'tpart_ones.%'
OR objname like 'tpart_tens.%')
ORDER BY objname ASC;
-- --
-- Tests for SECURITY LABEL -- Tests for SECURITY LABEL
...@@ -92,6 +128,14 @@ SECURITY LABEL ON COLUMN t2 ...@@ -92,6 +128,14 @@ SECURITY LABEL ON COLUMN t2
IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- be failed IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- be failed
SECURITY LABEL ON COLUMN t2.b SECURITY LABEL ON COLUMN t2.b
IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
SECURITY LABEL ON TABLE tpart
IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
SECURITY LABEL ON TABLE tpart
IS 'invalid security context'; -- failed
SECURITY LABEL ON COLUMN tpart
IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- failed
SECURITY LABEL ON COLUMN tpart.o
IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
-- --
-- Tests for Trusted Procedures -- Tests for Trusted Procedures
...@@ -198,8 +242,10 @@ SELECT auth_func('foo', 'acbd18db4cc2f85cedef654fccc4a4d8'); ...@@ -198,8 +242,10 @@ SELECT auth_func('foo', 'acbd18db4cc2f85cedef654fccc4a4d8');
SELECT sepgsql_getcon(); SELECT sepgsql_getcon();
SELECT * FROM foo_tbl; -- OK SELECT * FROM foo_tbl; -- OK
SELECT * FROM foo_ptbl; -- OK
SELECT * FROM var_tbl; -- failed SELECT * FROM var_tbl; -- failed
SELECT * FROM var_ptbl; -- failed
SELECT * FROM auth_tbl; -- failed SELECT * FROM auth_tbl; -- failed
...@@ -208,8 +254,10 @@ SELECT sepgsql_getcon(); ...@@ -208,8 +254,10 @@ SELECT sepgsql_getcon();
-- the pooler cannot touch these tables directly -- the pooler cannot touch these tables directly
SELECT * FROM foo_tbl; -- failed SELECT * FROM foo_tbl; -- failed
SELECT * FROM foo_ptbl; -- failed
SELECT * FROM var_tbl; -- failed SELECT * FROM var_tbl; -- failed
SELECT * FROM var_ptbl; -- failed
-- switch to "var" -- switch to "var"
SELECT auth_func('var', 'b2145aac704ce76dbe1ac7adac535b23'); SELECT auth_func('var', 'b2145aac704ce76dbe1ac7adac535b23');
...@@ -217,8 +265,10 @@ SELECT auth_func('var', 'b2145aac704ce76dbe1ac7adac535b23'); ...@@ -217,8 +265,10 @@ SELECT auth_func('var', 'b2145aac704ce76dbe1ac7adac535b23');
SELECT sepgsql_getcon(); SELECT sepgsql_getcon();
SELECT * FROM foo_tbl; -- failed SELECT * FROM foo_tbl; -- failed
SELECT * FROM foo_ptbl; -- failed
SELECT * FROM var_tbl; -- OK SELECT * FROM var_tbl; -- OK
SELECT * FROM var_ptbl; -- OK
SELECT * FROM auth_tbl; -- failed SELECT * FROM auth_tbl; -- failed
...@@ -236,6 +286,7 @@ DROP TABLE IF EXISTS t1 CASCADE; ...@@ -236,6 +286,7 @@ DROP TABLE IF EXISTS t1 CASCADE;
DROP TABLE IF EXISTS t2 CASCADE; DROP TABLE IF EXISTS t2 CASCADE;
DROP TABLE IF EXISTS t3 CASCADE; DROP TABLE IF EXISTS t3 CASCADE;
DROP TABLE IF EXISTS t4 CASCADE; DROP TABLE IF EXISTS t4 CASCADE;
DROP TABLE IF EXISTS tpart CASCADE;
DROP FUNCTION IF EXISTS f1() CASCADE; DROP FUNCTION IF EXISTS f1() CASCADE;
DROP FUNCTION IF EXISTS f2() CASCADE; DROP FUNCTION IF EXISTS f2() CASCADE;
DROP FUNCTION IF EXISTS f3() CASCADE; DROP FUNCTION IF EXISTS f3() CASCADE;
......
...@@ -10,17 +10,31 @@ LOAD '$libdir/sepgsql'; -- failed ...@@ -10,17 +10,31 @@ LOAD '$libdir/sepgsql'; -- failed
CREATE TABLE t1 (x int, y text); CREATE TABLE t1 (x int, y text);
INSERT INTO t1 (SELECT x, md5(x::text) FROM generate_series(1,100) x); INSERT INTO t1 (SELECT x, md5(x::text) FROM generate_series(1,100) x);
CREATE TABLE t1p (o int, p text) PARTITION BY RANGE (o);
CREATE TABLE t1p_ones PARTITION OF t1p FOR VALUES FROM ('0') TO ('10');
CREATE TABLE t1p_tens PARTITION OF t1p FOR VALUES FROM ('10') TO ('100');
INSERT INTO t1p (SELECT x, md5(x::text) FROM generate_series(0,99) x);
SET sepgsql.debug_audit = on; SET sepgsql.debug_audit = on;
SET client_min_messages = log; SET client_min_messages = log;
-- regular function and operators -- regular function and operators
SELECT * FROM t1 WHERE x > 50 AND y like '%64%'; SELECT * FROM t1 WHERE x > 50 AND y like '%64%';
SELECT * FROM t1p WHERE o > 50 AND p like '%64%';
SELECT * FROM t1p_ones WHERE o > 50 AND p like '%64%';
SELECT * FROM t1p_tens WHERE o > 50 AND p like '%64%';
-- aggregate function -- aggregate function
SELECT MIN(x), AVG(x) FROM t1; SELECT MIN(x), AVG(x) FROM t1;
SELECT MIN(o), AVG(o) FROM t1p;
SELECT MIN(o), AVG(o) FROM t1p_ones;
SELECT MIN(o), AVG(o) FROM t1p_tens;
-- window function -- window function
SELECT row_number() OVER (order by x), * FROM t1 WHERE y like '%86%'; SELECT row_number() OVER (order by x), * FROM t1 WHERE y like '%86%';
SELECT row_number() OVER (order by o), * FROM t1p WHERE p like '%86%';
SELECT row_number() OVER (order by o), * FROM t1p_ones WHERE p like '%86%';
SELECT row_number() OVER (order by o), * FROM t1p_tens WHERE p like '%86%';
RESET sepgsql.debug_audit; RESET sepgsql.debug_audit;
RESET client_min_messages; RESET client_min_messages;
...@@ -28,3 +42,4 @@ RESET client_min_messages; ...@@ -28,3 +42,4 @@ RESET client_min_messages;
-- Cleanup -- Cleanup
-- --
DROP TABLE IF EXISTS t1 CASCADE; DROP TABLE IF EXISTS t1 CASCADE;
DROP TABLE IF EXISTS t1p CASCADE;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment