ID | IEP-123 |
Author | Mikhail Pochatkin |
Sponsor | Mikhail Pochatkin |
Created | |
Status | DRAFT |
In addition o SQL DDL commands, provide a simple, low-feature and type-safe Java API for initial tables generation from POJO.
Support custom annotations and simple builders. This feature should work seamlessly with existing Mapper interface (keyValueView and
recordView). It will give developers the ability to work in the way they used to - create tables from POJO and build indexes without
forcing them to use SQL for basic operations.
This proposal is successor of `QueryEntity` and `CacheConfiguration.setIndexedTypes()` which was supported by AI2
Apache Ignite is very idiomatic in Java, while `QueryEntity` in AI 2.x is technically low value - it's a convenient way
to work with tables and pojo mapping. Besides, AI 3.x already has table keyValueViews that maps pojo but lacks features
to easily instantiate tables.
We are not trying to achieve functionality of altering tables, schema migration tools and track changes, just a simple
self-sufficient way of initial schema generation from POJO classes (prototyping, testing etc. purposes).
Statements, properties, expressions should be covered:
- CREATE ZONE
- CREATE TABLE
- CREATE INDEX
- DROP ZONE/TABLE/INDEX
- Column definition, length, precision, scale, nullability, defaults.
@Target(TYPE) @Retention(RUNTIME) public @interface Table { String name() default ""; Index[] indexes() default {}; IndexType primaryKeyType() default IndexType.DEFAULT; ColocateBy colocateBy() default @ColocateBy(columnList = ""); Class<?> zone() default DefaultZone.class; } public interface DefaultZone { /*marker inerface*/ } public enum SortOrder { DEFAULT, // order declaration in command will be omitted ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST, DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST, } @Target({}) @Retention(RUNTIME) public @interface Col { // Specifies column in other annotations String name(); SortOrder sort() default SortOrder.DEFAULT; } @Target({}) @Retention(RUNTIME) public @interface Index { String name() default ""; Col[] columns(); IndexType type() default IndexType.DEFAULT; } public enum IndexType { TREE, HASH, DEFAULT // index type declaration in command will be omitted } @Target({}) @Retention(RUNTIME) public @interface ColocateBy { Col[] columns(); } @Target(FIELD) @Retention(RUNTIME) public @interface Id { SortOrder sort() default SortOrder.DEFAULT; // order declaration will be omitted } @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Column { String name() default ""; boolean nullable() default true; int length() default -1; int precision() default -1; int scale() default -1; String columnDefinition() default ""; } @Target(TYPE) @Retention(RUNTIME) public @interface Zone { String name(); int partitions() default -1; int replicas() default -1; int dataNodesAutoAdjust() default -1; int dataNodesAutoAdjustScaleUp() default -1; int dataNodesAutoAdjustScaleDown() default -1; String filter() default ""; ZoneEngine engine() default ZoneEngine.DEFAULT; String dataregion() default ""; } public enum ZoneEngine { AIMEM, ROCKSDB, DEFAULT // zone engine declaration in dll will be omitted }
// kvView example @Zone( name = "zone_test", partitions = 2, engine = ZoneEngine.ROCKSDB ) class ZoneTest {} class PojoKey { @Id Integer id; @Id(sort = DESC) @Column(name = "id_str", length = 20) String idStr; } @Table( name = "kv_pojo_test", zone = ZoneTest.class, colocateBy = @ColocateBy(columns = { @Col(name = "f_name"), @Col(name = "l_name") }), indexes = { @Index(name = "ix_test", columns = { @Col(name = "f_name"), @Col(name = "l_name", sort = DESC_NULLS_LAST) }) } ) class PojoValue { @Column(name = "f_name") String firstName; @Column(name = "l_name") String lastName; String str; } // execute to create table ignite.catalog().create(PojoKey.class, PojoValue.class).execute(); // example defining KV pojo, compatible with keyValueView ignite.tables().table("kv_pojo_test").keyValueView(PojoKey.class, PojoValue.class) // is equivalent to multi-statement CREATE ZONE IF NOT EXISTS zone_test ENGINE ROCKSDB WITH PARTITIONS=2; CREATE TABLE IF NOT EXISTS kv_pojo_test ( id int, id_str varchar(20), f_name varchar, l_name varchar, str varchar, PRIMARY KEY (id, id_str desc) ) COLOCATE BY (f_name, l_name) WITH PRIMARY_ZONE='ZONE_TEST'; CREATE INDEX ix_test (f_name, l_name desc nulls last);
// recordView example @Table( name = "pojo_test", zone = ZoneTest.class, colocateBy = @ColocateBy(columns = { @Col(name = "f_name"), @Col(name = "l_name") }), indexes = { @Index(name = "ix_test", columns = { @Col(name = "f_name"), @Col(name = "l_name", sort = DESC_NULLS_LAST) } } ) class Pojo { @Id Integer id; @Id(sort = DESC) @Column(name = "id_str", length = 20) String idStr; @Column(name = "f_name") String firstName; @Column(name = "l_name") String lastName; String str; } // execute to create table ignite.catalog().create(Pojo.class).execute(); // example defining single pojo, compatible with recordView ignite.tables().table("kv_pojo_test").recordView(Pojo.class)
// example of using builder alternative to @Table annotation class Pojo { @Id Integer id; @Id(sort = DESC) @Column(name = "id_str", length = 20) String idStr; @Column(name = "f_name") String firstName; @Column(name = "l_name") String lastName; String str; } ignite.catalog() .create(ZoneDefinition.builder("zone_test") .partitions(2)) .execute(); ignite.catalog() .create(TableDefinition.builder("pojo_test") .ifNotExists() .colocateBy("id", "id_str") .zone("zone_test") .recordView(Pojo.class) // .keyValueView(Key.class, Value.class) .build()) .execute();
No any risks
[AI2 Query Entities](https://ignite.apache.org/docs/latest/SQL/indexes)
- [AI3 Epic IGNITE-21410]( - IGNITE-21410Getting issue details... STATUS )