mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-21 11:09:17 +00:00
#2701 -[DDL] Postgres DDL generation for table partitioning with schema - helper method to add partitions does not work
This also removes the helper partition_init() stored function as it isn't really needed now that postgres has default partition support (since PG11 actually, partition_init predates PG11).
This commit is contained in:
@@ -812,7 +812,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return the SQL to create an initial partition for the given table.
|
||||
*/
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String singlePrimaryKey) {
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ public final class SplitName {
|
||||
}
|
||||
|
||||
private static String[] split(String name, boolean last) {
|
||||
|
||||
int pos = last ? name.lastIndexOf('.') : name.indexOf('.');
|
||||
if (pos == -1) {
|
||||
if (last) {
|
||||
|
||||
@@ -238,7 +238,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
if (!databasePlatform.tablePartitionsExist(connection, tableName)) {
|
||||
log.info("No table partitions for table {}", tableName);
|
||||
PartitionMeta meta = table.getPartitionMeta();
|
||||
String initPart = databasePlatform.tablePartitionInit(tableName, meta.getMode(), meta.getProperty(), table.singlePrimaryKey());
|
||||
String initPart = databasePlatform.tablePartitionInit(tableName, meta.getMode());
|
||||
sb.append(initPart).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
+15
-48
@@ -17,6 +17,7 @@ begin
|
||||
period_start timestamptz,
|
||||
period_end timestamptz,
|
||||
period_name text,
|
||||
schema_name text,
|
||||
base_name text,
|
||||
part_name text
|
||||
);
|
||||
@@ -34,7 +35,11 @@ language plpgsql
|
||||
set timezone to 'UTC'
|
||||
as $$
|
||||
begin
|
||||
execute format('create table if not exists %I partition of %I for values from (''%s'') TO (''%s'')', meta.part_name, meta.base_name, meta.period_start, meta.period_end);
|
||||
if (meta.schema_name = '') then
|
||||
execute format('create table if not exists %I partition of %I for values from (''%s'') TO (''%s'')', meta.part_name, meta.base_name, meta.period_start, meta.period_end);
|
||||
else
|
||||
execute format('create table if not exists %I partition of %I.%I for values from (''%s'') TO (''%s'')', meta.part_name, meta.schema_name, meta.base_name, meta.period_start, meta.period_end);
|
||||
end if;
|
||||
return meta.part_name;
|
||||
end;
|
||||
$$;
|
||||
@@ -49,7 +54,8 @@ $$;
|
||||
create or replace function _partition_meta(
|
||||
mode text,
|
||||
asOf date,
|
||||
baseName text)
|
||||
baseName text,
|
||||
schemaName text default '')
|
||||
returns partition_meta
|
||||
language plpgsql
|
||||
set timezone to 'UTC'
|
||||
@@ -81,8 +87,8 @@ begin
|
||||
select asOfUtc, asOfUtc + interval '1 month' into meta.period_start, meta.period_end;
|
||||
end if;
|
||||
|
||||
select partName, baseName, format('%s_%s', baseName, partName)
|
||||
into meta.period_name, meta.base_name, meta.part_name;
|
||||
select partName, schemaName, baseName, format('%s_%s', baseName, partName)
|
||||
into meta.period_name, meta.schema_name, meta.base_name, meta.part_name;
|
||||
|
||||
return meta;
|
||||
end;
|
||||
@@ -133,70 +139,31 @@ $$;
|
||||
-- Function: partition
|
||||
--
|
||||
-- Helper to ensure we create partitions into the future as needed for day, week, month
|
||||
-- and year based partitioning. Typically we call this periodically (e.g. every day).
|
||||
-- and year based partitioning. Typically, we call this periodically (e.g. every day).
|
||||
--
|
||||
-- Examples:
|
||||
--
|
||||
-- select partition('week', 'trip', 4);
|
||||
-- select partition('week', 'trip', 4);
|
||||
-- select partition('month', 'event', 1);
|
||||
-- select partition('year', 'log', 1, 'my_schema');
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
create or replace function partition(
|
||||
mode text, -- one of 'day','week','month','year'
|
||||
baseName text, -- base table name
|
||||
partitionCount integer default 0, -- number of additional partitions
|
||||
schemaName text default '', -- schema
|
||||
fromDate date default current_date) -- date to create first partition for
|
||||
returns text
|
||||
language plpgsql
|
||||
set timezone to 'UTC'
|
||||
as $$
|
||||
begin
|
||||
perform _partition_create(_partition_meta(mode, poDate, baseName))
|
||||
perform _partition_create(_partition_meta(mode, poDate, baseName, schemaName))
|
||||
from _partition_over(mode, fromDate, partitionCount) poDate;
|
||||
return 'done';
|
||||
end;
|
||||
$$;
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
-- Function: partition_init
|
||||
--
|
||||
-- Similar to partition but allows the first partition to be bigger with an explicit
|
||||
-- initDate typically to allow back dated rows to go into the initial partition.
|
||||
--
|
||||
-- Examples:
|
||||
--
|
||||
-- select partition_init(date '2001-01-01', 'week', 'event');
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
create or replace function partition_init(
|
||||
initDate date, -- first partition period start date
|
||||
mode text, -- one of 'day','week','month','year'
|
||||
baseName text, -- base table name
|
||||
partitionCount integer default 0, -- number of additional partitions
|
||||
fromDate date default current_date) -- date to create first partition for
|
||||
returns text
|
||||
language plpgsql
|
||||
set timezone to 'UTC'
|
||||
as $$
|
||||
declare
|
||||
meta partition_meta;
|
||||
begin
|
||||
-- override the period start for the first partition
|
||||
meta = _partition_meta(mode, fromDate, baseName);
|
||||
meta.period_start = initDate;
|
||||
perform _partition_create(meta);
|
||||
|
||||
if (partitionCount > 0) then
|
||||
-- create additional partitions normally
|
||||
fromDate = fromDate + interval '1 day';
|
||||
perform _partition_create(_partition_meta(mode, poDate, baseName))
|
||||
from _partition_over(mode, fromDate, partitionCount) poDate;
|
||||
end if;
|
||||
|
||||
return 'done';
|
||||
end;
|
||||
$$;
|
||||
</ddl-script>
|
||||
|
||||
</extra-ddl>
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
import io.ebean.util.SplitName;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
@@ -163,11 +164,23 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
* Only use this if extra-ddl doesn't have some initial partitions defined (which it should).
|
||||
*/
|
||||
@Override
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String pkey) {
|
||||
// default partition required pg11 but this is only used for testing but bumped test docker container to pg11 by default
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode) {
|
||||
// default partition required pg11 but this is only used for testing but bumped test docker container to pg14 by default
|
||||
String[] schemaTable = SplitName.split(tableName);
|
||||
|
||||
String baseTable;
|
||||
String plusSchema;
|
||||
if (schemaTable[0] == null) {
|
||||
plusSchema = "";
|
||||
baseTable = tableName;
|
||||
} else {
|
||||
// table in an explicit schema
|
||||
plusSchema = ",'" + schemaTable[0] + "'";
|
||||
baseTable = schemaTable[1];
|
||||
}
|
||||
return
|
||||
"create table " + tableName + "_default" + " partition of " + tableName + " default;\n" +
|
||||
"select partition('" + mode.name().toLowerCase() + "','" + tableName + "',1);";
|
||||
"select partition('" + mode.name().toLowerCase() + "','" + baseTable + "',1" + plusSchema + ");";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+19
-9
@@ -1,12 +1,11 @@
|
||||
package io.ebean.platform.postgres;
|
||||
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static io.ebean.Query.LockType.*;
|
||||
@@ -14,11 +13,10 @@ import static io.ebean.Query.LockWait.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class PostgresPlatformTest {
|
||||
class PostgresPlatformTest {
|
||||
|
||||
@Test
|
||||
public void testUuidType() {
|
||||
|
||||
void testUuidType() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
platform.configure(new PlatformConfig());
|
||||
|
||||
@@ -29,8 +27,21 @@ public class PostgresPlatformTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void default_forUpdate_expect_noKeyUsed() {
|
||||
void tablePartitionInit() {
|
||||
String sql = new PostgresPlatform().tablePartitionInit("foo", PartitionMode.WEEK);
|
||||
assertThat(sql).isEqualTo("create table foo_default partition of foo default;\n" +
|
||||
"select partition('week','foo',1);");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tablePartitionInit_withSchema() {
|
||||
String sql = new PostgresPlatform().tablePartitionInit("bar.foo", PartitionMode.WEEK);
|
||||
assertThat(sql).isEqualTo("create table bar.foo_default partition of bar.foo default;\n" +
|
||||
"select partition('week','foo',1,'bar');");
|
||||
}
|
||||
|
||||
@Test
|
||||
void default_forUpdate_expect_noKeyUsed() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
|
||||
PlatformConfig config = new PlatformConfig();
|
||||
@@ -58,8 +69,7 @@ public class PostgresPlatformTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lockWithKey_forUpdate() {
|
||||
|
||||
void lockWithKey_forUpdate() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
|
||||
PlatformConfig config = new PlatformConfig();
|
||||
|
||||
Reference in New Issue
Block a user