diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java index a538086f8c6c30bd2c39293fd2a711d592a427c6..80542a403f91f41509d498a4e50068bf761c642b 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java @@ -14,6 +14,8 @@ import jakarta.persistence.*;; import java.time.Instant; import java.util.List; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Data @Entity @@ -52,6 +54,7 @@ public class View { @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") private UUID createdBy; + @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) @@ -86,14 +89,11 @@ public class View { * @return True if views are equal, false otherwise */ public boolean equals(FromItem other) { - final String name = other.toString() - .replace("`", ""); - if (other.getAlias() != null) { - final int idx = name.indexOf(' '); - return this.getInternalName() - .equals(name.substring(0, idx)); + if (other == null) { + return false; } - return this.getInternalName().equals(name); + final net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table) other; + return this.internalName.equals(table.getName().replace("`", "")); } @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java index a6fe347eabec02abbd4c0516ed16ea7d27b8eca7..f24fd1ec42ad53a5b1f42c1a70d2ac9a3c83ec2f 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java @@ -5,7 +5,9 @@ import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.entities.database.table.constraints.Constraints; import at.tuwien.entities.user.User; import lombok.*; +import lombok.extern.log4j.Log4j2; import net.sf.jsqlparser.statement.select.FromItem; +import net.sf.jsqlparser.statement.select.SelectItem; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -14,10 +16,13 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import jakarta.persistence.*;; import java.time.Instant; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Data @Entity @Builder +@Log4j2 @ToString @AllArgsConstructor @NoArgsConstructor @@ -100,14 +105,11 @@ public class Table { * @return True if tables are equal, false otherwise */ public boolean equals(FromItem other) { - final String name = other.toString() - .replace("`", ""); - if (other.getAlias() != null) { - final int idx = name.indexOf(' '); - return this.getInternalName() - .equals(name.substring(0, idx)); + if (other == null) { + return false; } - return this.getInternalName().equals(name); + final net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table) other; + return this.internalName.equals(table.getName().replace("`", "")); } } diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index 753f448c4d6005c7caf9c5f6728dc74d58febefe..f1c62bd3d2b74d1bc55b910428891afd5ce6b017 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -1,10 +1,10 @@ package at.tuwien.entities.database.table.columns; import at.tuwien.entities.container.image.ContainerImageDate; +import at.tuwien.entities.database.View; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.user.User; import lombok.*; -import net.sf.jsqlparser.statement.select.SelectItem; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -16,7 +16,7 @@ import java.util.List; @Data @Entity -@Builder +@Builder(toBuilder=true) @ToString @AllArgsConstructor @NoArgsConstructor @@ -58,6 +58,10 @@ public class TableColumn implements Comparable<TableColumn> { }) private Table table; + @ToString.Exclude + private transient View view; + + @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) @JoinColumns({ @JoinColumn(name = "createdBy", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false) @@ -79,6 +83,8 @@ public class TableColumn implements Comparable<TableColumn> { @Column private Integer indexLength; + private transient String alias; + @Column(name = "datatype", nullable = false) @Enumerated(EnumType.STRING) private TableColumnType columnType; @@ -133,24 +139,6 @@ public class TableColumn implements Comparable<TableColumn> { return Integer.compare(this.ordinalPosition, tableColumn.getOrdinalPosition()); } - /** - * KEEP THIS FUNCTION HERE! IT WILL BREAK CODE! - * Custom equality function implementation. - * - * @param other The other column. - * @return True if columns are equal, false otherwise - */ - public boolean equals(SelectItem other) { - final String name = other.toString() - .replace("`", ""); - final int idx = name.indexOf('.'); - if (idx == -1) { - return name.equals(this.internalName); - } - return name.substring(idx + 1) - .equals(this.internalName); - } - /** * KEEP THIS FUNCTION HERE! IT WILL BREAK CODE! * Custom equality function implementation. @@ -159,10 +147,13 @@ public class TableColumn implements Comparable<TableColumn> { * @return True if columns are equal, false otherwise */ public boolean equals(Object object) { - if (!(object instanceof TableColumn)) { + if (object == null) { + return false; + } + if (!(object instanceof final TableColumn other)) { return false; } - final TableColumn other = (TableColumn) object; - return this.getId().equals(other.getId()) && this.getTid().equals(other.getTid()) && this.getCdbid().equals(other.getCdbid()); + return this.getId().equals(other.getId()) && this.getTid().equals(other.getTid()) + && this.getCdbid().equals(other.getCdbid()); } } diff --git a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java index 6b7999512855a54b27e1b11eb0b613918c3e49c3..2d91e8ac304ec00b5c851dc14599803c6b65a85d 100644 --- a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java @@ -65,6 +65,7 @@ import static java.time.temporal.ChronoUnit.*; * <li>Table 3</li> * <li>Table 7</li> * <li>Query 1</li> + * <li>View 2</li> * <li>View 3</li> * </ul> * <p> @@ -1057,7 +1058,7 @@ public abstract class BaseTest { .creator(DATABASE_1_CREATOR) .owner(DATABASE_1_OWNER) .tables(List.of()) /* TABLE_1, TABLE_2, TABLE_3, TABLE_7 */ - .views(List.of()) + .views(List.of()) /* VIEW_2, VIEW_3 */ .build(); public final static Database DATABASE_1_SIMPLE = Database.builder() @@ -1607,7 +1608,7 @@ public abstract class BaseTest { public final static Instant TABLE_6_CREATED = Instant.ofEpochSecond(1677400147) /* 2023-02-26 08:29:07 (UTC) */; public final static Instant TABLE_6_LAST_MODIFIED = Instant.ofEpochSecond(1677400147) /* 2023-02-26 08:29:07 (UTC) */; - public final static Long TABLE_7_ID = 7L; + public final static Long TABLE_7_ID = 4L; public final static String TABLE_7_NAME = "Sensor"; public final static String TABLE_7_INTERNAL_NAME = "sensor"; public final static String TABLE_7_DESCRIPTION = "Hello sensor"; @@ -1617,7 +1618,7 @@ public abstract class BaseTest { public final static Instant TABLE_7_LAST_MODIFIED = Instant.ofEpochSecond(1677400175) /* 2023-02-26 08:29:35 (UTC) */; public final static List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() - .id(1L) + .id(44L) .ordinalPosition(0) .cdbid(DATABASE_1_ID) .tid(TABLE_7_ID) @@ -1631,7 +1632,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() - .id(2L) + .id(45L) .ordinalPosition(1) .cdbid(DATABASE_1_ID) .tid(TABLE_7_ID) @@ -1650,12 +1651,14 @@ public abstract class BaseTest { .created(Instant.now()) .internalName(TABLE_7_INTERNAL_NAME) .description(TABLE_7_DESCRIPTION) + .database(DATABASE_1) .name(TABLE_7_NAME) .tdbid(DATABASE_1_ID) .queueName(TABLE_7_QUEUE_NAME) .routingKey(TABLE_7_ROUTING_KEY) .columns(TABLE_7_COLUMNS) .creator(USER_1) + .owner(USER_1) .created(TABLE_7_CREATED) .lastModified(TABLE_7_LAST_MODIFIED) .build(); @@ -1665,12 +1668,14 @@ public abstract class BaseTest { .created(Instant.now()) .internalName(TABLE_7_INTERNAL_NAME) .description(TABLE_7_DESCRIPTION) + .database(DATABASE_1_SIMPLE) .name(TABLE_7_NAME) .tdbid(DATABASE_1_ID) .queueName(TABLE_7_QUEUE_NAME) .routingKey(TABLE_7_ROUTING_KEY) .columns(List.of() /* for jpa */) - .creator(null /* for jpa */) + .creator(USER_1) + .owner(USER_1) .created(TABLE_7_CREATED) .lastModified(TABLE_7_LAST_MODIFIED) .build(); @@ -1844,7 +1849,7 @@ public abstract class BaseTest { public final static String COLUMN_2_3_CHECK = null; public final static List<String> COLUMN_2_3_ENUM_VALUES = null; - public final static Long COLUMN_4_1_ID = 9L; + public final static Long COLUMN_4_1_ID = 44L; public final static Integer COLUMN_4_1_ORDINALPOS = 0; public final static Boolean COLUMN_4_1_PRIMARY = true; public final static String COLUMN_4_1_NAME = "id"; @@ -1860,7 +1865,7 @@ public abstract class BaseTest { public final static ColumnTypeDto COLUMN_4_1_TYPE_DTO = ColumnTypeDto.NUMBER; public final static String[] COLUMN_4_1_ENUM_VALUES_ARRAY = null; - public final static Long COLUMN_4_2_ID = 10L; + public final static Long COLUMN_4_2_ID = 45L; public final static Integer COLUMN_4_2_ORDINALPOS = 1; public final static Boolean COLUMN_4_2_PRIMARY = false; public final static String COLUMN_4_2_NAME = "Animal Name"; @@ -1876,7 +1881,7 @@ public abstract class BaseTest { public final static ColumnTypeDto COLUMN_4_2_TYPE_DTO = ColumnTypeDto.STRING; public final static String[] COLUMN_4_2_ENUM_VALUES_ARRAY = null; - public final static Long COLUMN_4_3_ID = 11L; + public final static Long COLUMN_4_3_ID = 46L; public final static Integer COLUMN_4_3_ORDINALPOS = 2; public final static Boolean COLUMN_4_3_PRIMARY = false; public final static String COLUMN_4_3_NAME = "Hair"; @@ -1890,7 +1895,7 @@ public abstract class BaseTest { public final static String COLUMN_4_3_CHECK = null; public final static List<String> COLUMN_4_3_ENUM_VALUES = null; - public final static Long COLUMN_4_4_ID = 12L; + public final static Long COLUMN_4_4_ID = 47L; public final static Integer COLUMN_4_4_ORDINALPOS = 3; public final static Boolean COLUMN_4_4_PRIMARY = false; public final static String COLUMN_4_4_NAME = "Feathers"; @@ -1904,7 +1909,7 @@ public abstract class BaseTest { public final static String COLUMN_4_4_CHECK = null; public final static List<String> COLUMN_4_4_ENUM_VALUES = null; - public final static Long COLUMN_4_5_ID = 13L; + public final static Long COLUMN_4_5_ID = 48L; public final static Integer COLUMN_4_5_ORDINALPOS = 4; public final static Boolean COLUMN_4_5_PRIMARY = false; public final static String COLUMN_4_5_NAME = "Bread"; @@ -1918,7 +1923,7 @@ public abstract class BaseTest { public final static String COLUMN_4_5_CHECK = null; public final static List<String> COLUMN_4_5_ENUM_VALUES = null; - public final static Long COLUMN_4_6_ID = 14L; + public final static Long COLUMN_4_6_ID = 49L; public final static Integer COLUMN_4_6_ORDINALPOS = 5; public final static Boolean COLUMN_4_6_PRIMARY = false; public final static String COLUMN_4_6_NAME = "Eggs"; @@ -1932,7 +1937,7 @@ public abstract class BaseTest { public final static String COLUMN_4_6_CHECK = null; public final static List<String> COLUMN_4_6_ENUM_VALUES = null; - public final static Long COLUMN_4_7_ID = 15L; + public final static Long COLUMN_4_7_ID = 50L; public final static Integer COLUMN_4_7_ORDINALPOS = 6; public final static Boolean COLUMN_4_7_PRIMARY = false; public final static String COLUMN_4_7_NAME = "Milk"; @@ -1946,7 +1951,7 @@ public abstract class BaseTest { public final static String COLUMN_4_7_CHECK = null; public final static List<String> COLUMN_4_7_ENUM_VALUES = null; - public final static Long COLUMN_4_8_ID = 16L; + public final static Long COLUMN_4_8_ID = 51L; public final static Integer COLUMN_4_8_ORDINALPOS = 7; public final static Boolean COLUMN_4_8_PRIMARY = false; public final static String COLUMN_4_8_NAME = "Water"; @@ -1960,7 +1965,7 @@ public abstract class BaseTest { public final static String COLUMN_4_8_CHECK = null; public final static List<String> COLUMN_4_8_ENUM_VALUES = null; - public final static Long COLUMN_4_9_ID = 17L; + public final static Long COLUMN_4_9_ID = 52L; public final static Integer COLUMN_4_9_ORDINALPOS = 8; public final static Boolean COLUMN_4_9_PRIMARY = false; public final static String COLUMN_4_9_NAME = "Airborne"; @@ -1974,7 +1979,7 @@ public abstract class BaseTest { public final static String COLUMN_4_9_CHECK = null; public final static List<String> COLUMN_4_9_ENUM_VALUES = null; - public final static Long COLUMN_4_10_ID = 18L; + public final static Long COLUMN_4_10_ID = 53L; public final static Integer COLUMN_4_10_ORDINALPOS = 9; public final static Boolean COLUMN_4_10_PRIMARY = false; public final static String COLUMN_4_10_NAME = "Waterborne"; @@ -1988,7 +1993,7 @@ public abstract class BaseTest { public final static String COLUMN_4_10_CHECK = null; public final static List<String> COLUMN_4_10_ENUM_VALUES = null; - public final static Long COLUMN_4_11_ID = 19L; + public final static Long COLUMN_4_11_ID = 54L; public final static Integer COLUMN_4_11_ORDINALPOS = 10; public final static Boolean COLUMN_4_11_PRIMARY = false; public final static String COLUMN_4_11_NAME = "Aquantic"; @@ -2002,7 +2007,7 @@ public abstract class BaseTest { public final static String COLUMN_4_11_CHECK = null; public final static List<String> COLUMN_4_11_ENUM_VALUES = null; - public final static Long COLUMN_4_12_ID = 20L; + public final static Long COLUMN_4_12_ID = 55L; public final static Integer COLUMN_4_12_ORDINALPOS = 11; public final static Boolean COLUMN_4_12_PRIMARY = false; public final static String COLUMN_4_12_NAME = "Predator"; @@ -2016,7 +2021,7 @@ public abstract class BaseTest { public final static String COLUMN_4_12_CHECK = null; public final static List<String> COLUMN_4_12_ENUM_VALUES = null; - public final static Long COLUMN_4_13_ID = 21L; + public final static Long COLUMN_4_13_ID = 56L; public final static Integer COLUMN_4_13_ORDINALPOS = 12; public final static Boolean COLUMN_4_13_PRIMARY = false; public final static String COLUMN_4_13_NAME = "Backbone"; @@ -2030,7 +2035,7 @@ public abstract class BaseTest { public final static String COLUMN_4_13_CHECK = null; public final static List<String> COLUMN_4_13_ENUM_VALUES = null; - public final static Long COLUMN_4_14_ID = 22L; + public final static Long COLUMN_4_14_ID = 57L; public final static Integer COLUMN_4_14_ORDINALPOS = 13; public final static Boolean COLUMN_4_14_PRIMARY = false; public final static String COLUMN_4_14_NAME = "Breathes"; @@ -2044,7 +2049,7 @@ public abstract class BaseTest { public final static String COLUMN_4_14_CHECK = null; public final static List<String> COLUMN_4_14_ENUM_VALUES = null; - public final static Long COLUMN_4_15_ID = 23L; + public final static Long COLUMN_4_15_ID = 58L; public final static Integer COLUMN_4_15_ORDINALPOS = 14; public final static Boolean COLUMN_4_15_PRIMARY = false; public final static String COLUMN_4_15_NAME = "Venomous"; @@ -2058,7 +2063,7 @@ public abstract class BaseTest { public final static String COLUMN_4_15_CHECK = null; public final static List<String> COLUMN_4_15_ENUM_VALUES = null; - public final static Long COLUMN_4_16_ID = 24L; + public final static Long COLUMN_4_16_ID = 59L; public final static Integer COLUMN_4_16_ORDINALPOS = 15; public final static Boolean COLUMN_4_16_PRIMARY = false; public final static String COLUMN_4_16_NAME = "Fin"; @@ -2072,7 +2077,7 @@ public abstract class BaseTest { public final static String COLUMN_4_16_CHECK = null; public final static List<String> COLUMN_4_16_ENUM_VALUES = null; - public final static Long COLUMN_4_17_ID = 25L; + public final static Long COLUMN_4_17_ID = 60L; public final static Integer COLUMN_4_17_ORDINALPOS = 16; public final static Boolean COLUMN_4_17_PRIMARY = false; public final static String COLUMN_4_17_NAME = "Legs"; @@ -2086,7 +2091,7 @@ public abstract class BaseTest { public final static String COLUMN_4_17_CHECK = null; public final static List<String> COLUMN_4_17_ENUM_VALUES = null; - public final static Long COLUMN_4_18_ID = 26L; + public final static Long COLUMN_4_18_ID = 61L; public final static Integer COLUMN_4_18_ORDINALPOS = 17; public final static Boolean COLUMN_4_18_PRIMARY = false; public final static String COLUMN_4_18_NAME = "Tail"; @@ -2100,7 +2105,7 @@ public abstract class BaseTest { public final static String COLUMN_4_18_CHECK = null; public final static List<String> COLUMN_4_18_ENUM_VALUES = null; - public final static Long COLUMN_4_19_ID = 27L; + public final static Long COLUMN_4_19_ID = 62L; public final static Integer COLUMN_4_19_ORDINALPOS = 18; public final static Boolean COLUMN_4_19_PRIMARY = false; public final static String COLUMN_4_19_NAME = "Domestic"; @@ -2114,7 +2119,7 @@ public abstract class BaseTest { public final static String COLUMN_4_19_CHECK = null; public final static List<String> COLUMN_4_19_ENUM_VALUES = null; - public final static Long COLUMN_4_20_ID = 28L; + public final static Long COLUMN_4_20_ID = 63L; public final static Integer COLUMN_4_20_ORDINALPOS = 19; public final static Boolean COLUMN_4_20_PRIMARY = false; public final static String COLUMN_4_20_NAME = "Cat Size"; @@ -2128,7 +2133,7 @@ public abstract class BaseTest { public final static String COLUMN_4_20_CHECK = null; public final static List<String> COLUMN_4_20_ENUM_VALUES = null; - public final static Long COLUMN_4_21_ID = 29L; + public final static Long COLUMN_4_21_ID = 64L; public final static Integer COLUMN_4_21_ORDINALPOS = 20; public final static Boolean COLUMN_4_21_PRIMARY = false; public final static String COLUMN_4_21_NAME = "Class Type"; @@ -2142,7 +2147,7 @@ public abstract class BaseTest { public final static String COLUMN_4_21_CHECK = null; public final static List<String> COLUMN_4_21_ENUM_VALUES = null; - public final static Long COLUMN_5_1_ID = 23L; + public final static Long COLUMN_5_1_ID = 65L; public final static Integer COLUMN_5_1_ORDINALPOS = 0; public final static Boolean COLUMN_5_1_PRIMARY = true; public final static String COLUMN_5_1_NAME = "id"; @@ -2157,7 +2162,7 @@ public abstract class BaseTest { public final static String COLUMN_5_1_CHECK = null; public final static List<String> COLUMN_5_1_ENUM_VALUES = null; - public final static Long COLUMN_5_2_ID = 24L; + public final static Long COLUMN_5_2_ID = 66L; public final static Integer COLUMN_5_2_ORDINALPOS = 1; public final static Boolean COLUMN_5_2_PRIMARY = false; public final static String COLUMN_5_2_NAME = "firstname"; @@ -2173,7 +2178,7 @@ public abstract class BaseTest { public final static String COLUMN_5_2_CHECK = null; public final static List<String> COLUMN_5_2_ENUM_VALUES = null; - public final static Long COLUMN_5_3_ID = 25L; + public final static Long COLUMN_5_3_ID = 67L; public final static Integer COLUMN_5_3_ORDINALPOS = 2; public final static Boolean COLUMN_5_3_PRIMARY = false; public final static String COLUMN_5_3_NAME = "lastname"; @@ -2189,7 +2194,7 @@ public abstract class BaseTest { public final static String COLUMN_5_3_CHECK = null; public final static List<String> COLUMN_5_3_ENUM_VALUES = null; - public final static Long COLUMN_5_4_ID = 25L; + public final static Long COLUMN_5_4_ID = 68L; public final static Integer COLUMN_5_4_ORDINALPOS = 2; public final static Boolean COLUMN_5_4_PRIMARY = false; public final static String COLUMN_5_4_NAME = "ref_id"; @@ -2204,7 +2209,7 @@ public abstract class BaseTest { public final static String COLUMN_5_4_CHECK = null; public final static List<String> COLUMN_5_4_ENUM_VALUES = null; - public final static Long COLUMN_8_1_ID = 26L; + public final static Long COLUMN_8_1_ID = 69L; public final static Integer COLUMN_8_1_ORDINALPOS = 0; public final static Boolean COLUMN_8_1_PRIMARY = true; public final static String COLUMN_8_1_NAME = "ID"; @@ -2219,7 +2224,7 @@ public abstract class BaseTest { public final static String COLUMN_8_1_CHECK = null; public final static List<String> COLUMN_8_1_ENUM_VALUES = null; - public final static Long COLUMN_8_2_ID = 27L; + public final static Long COLUMN_8_2_ID = 70L; public final static Integer COLUMN_8_2_ORDINALPOS = 1; public final static Boolean COLUMN_8_2_PRIMARY = true; public final static String COLUMN_8_2_NAME = "Value"; @@ -2687,8 +2692,8 @@ public abstract class BaseTest { .routingKey(TABLE_1_ROUTING_KEY) .columns(List.of() /* for jpa */) .constraints(null /* for jpa */) /* TABLE_1_CONSTRAINTS */ - .creator(null /* for jpa */) - .owner(null /* for jpa */) + .creator(USER_1) + .owner(USER_1) .created(TABLE_1_CREATED) .lastModified(TABLE_1_LAST_MODIFIED) .build(); @@ -2769,8 +2774,8 @@ public abstract class BaseTest { .queueName(TABLE_2_QUEUE_NAME) .routingKey(TABLE_2_ROUTING_KEY) .columns(List.of() /* for jpa */) - .creator(null /* for jpa */) - .owner(null /* for jpa */) + .creator(USER_1) + .owner(USER_1) .created(TABLE_2_CREATED) .lastModified(TABLE_2_LAST_MODIFIED) .build(); @@ -2791,6 +2796,7 @@ public abstract class BaseTest { .build(); public final static List<TableColumn> TABLE_3_COLUMNS = List.of(TableColumn.builder() + .id(9L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(0) @@ -2805,6 +2811,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(10L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(1) @@ -2819,6 +2826,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(11L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(2) @@ -2833,6 +2841,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(12L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(3) @@ -2847,6 +2856,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(13L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(4) @@ -2861,6 +2871,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(14L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(5) @@ -2875,6 +2886,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(15L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(6) @@ -2889,6 +2901,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(16L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(7) @@ -2903,6 +2916,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(17L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(8) @@ -2917,6 +2931,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(18L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(9) @@ -2931,6 +2946,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(19L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(10) @@ -2945,6 +2961,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(20L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(11) @@ -2959,6 +2976,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(21L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(12) @@ -2973,6 +2991,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(22L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(13) @@ -2987,6 +3006,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(23L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(14) @@ -3001,6 +3021,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(24L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(15) @@ -3015,6 +3036,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(25L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(16) @@ -3029,6 +3051,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(26L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(17) @@ -3043,6 +3066,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(27L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(18) @@ -3057,6 +3081,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(28L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(19) @@ -3071,6 +3096,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(29L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(20) @@ -3085,6 +3111,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(30L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(21) @@ -3099,6 +3126,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(31L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(22) @@ -3113,6 +3141,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(32L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(23) @@ -3127,6 +3156,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(33L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(24) @@ -3141,6 +3171,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(34L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(25) @@ -3155,6 +3186,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(35L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(26) @@ -3169,6 +3201,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(36L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(27) @@ -3183,6 +3216,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(37L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(28) @@ -3197,6 +3231,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(38L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(29) @@ -3211,6 +3246,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(39L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(30) @@ -3225,6 +3261,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(40L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(31) @@ -3239,6 +3276,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(41L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(32) @@ -3253,6 +3291,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(42L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(33) @@ -3267,6 +3306,7 @@ public abstract class BaseTest { .creator(USER_1) .build(), TableColumn.builder() + .id(43L) .tid(TABLE_3_ID) .cdbid(DATABASE_1_ID) .ordinalPosition(34) @@ -3317,8 +3357,8 @@ public abstract class BaseTest { .routingKey(TABLE_3_ROUTING_KEY) .columns(List.of() /* for jpa */) .constraints(TABLE_3_CONSTRAINTS) - .creator(null /* for jpa */) - .owner(null /* for jpa */) + .creator(USER_1) + .owner(USER_1) .created(TABLE_3_CREATED) .lastModified(TABLE_3_LAST_MODIFIED) .build(); @@ -3971,6 +4011,52 @@ public abstract class BaseTest { public final static Boolean VIEW_1_PUBLIC = true; public final static String VIEW_1_QUERY = "select `location`, `lat`, `lng` from `weather_location`"; + public final static List<TableColumn> VIEW_1_COLUMNS = List.of(TableColumn.builder() + .id(COLUMN_2_1_ID) + .ordinalPosition(COLUMN_2_1_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_2_ID) + .name(COLUMN_2_1_NAME) + .internalName(COLUMN_2_1_INTERNAL_NAME) + .columnType(COLUMN_2_1_TYPE) + .dfid(COLUMN_2_1_DATE_FORMAT) + .isNullAllowed(COLUMN_2_1_NULL) + .autoGenerated(COLUMN_2_1_AUTO_GENERATED) + .isPrimaryKey(COLUMN_2_1_PRIMARY) + .enumValues(COLUMN_2_1_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_2_2_ID) + .ordinalPosition(COLUMN_2_2_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_2_ID) + .name(COLUMN_2_2_NAME) + .internalName(COLUMN_2_2_INTERNAL_NAME) + .columnType(COLUMN_2_2_TYPE) + .dfid(COLUMN_2_2_DATE_FORMAT) + .isNullAllowed(COLUMN_2_2_NULL) + .autoGenerated(COLUMN_2_2_AUTO_GENERATED) + .isPrimaryKey(COLUMN_2_2_PRIMARY) + .enumValues(COLUMN_2_2_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_2_3_ID) + .ordinalPosition(COLUMN_2_3_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_2_ID) + .name(COLUMN_2_3_NAME) + .internalName(COLUMN_2_3_INTERNAL_NAME) + .columnType(COLUMN_2_3_TYPE) + .dfid(COLUMN_2_3_DATE_FORMAT) + .isNullAllowed(COLUMN_2_3_NULL) + .autoGenerated(COLUMN_2_3_AUTO_GENERATED) + .isPrimaryKey(COLUMN_2_3_PRIMARY) + .enumValues(COLUMN_2_3_ENUM_VALUES) + .creator(USER_1) + .build()); + public final static View VIEW_1 = View.builder() .id(VIEW_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) @@ -3982,6 +4068,7 @@ public abstract class BaseTest { .query(VIEW_1_QUERY) .createdBy(USER_1_ID) .creator(USER_1) + .columns(VIEW_1_COLUMNS) .build(); public final static ViewDto VIEW_1_DTO = ViewDto.builder() @@ -4004,6 +4091,82 @@ public abstract class BaseTest { public final static Boolean VIEW_2_PUBLIC = true; public final static String VIEW_2_QUERY = "select `date`, `location`, `mintemp`, `rainfall` from `weather_aus` where `location` = 'Albury'"; + public final static List<TableColumn> VIEW_2_COLUMNS = List.of(TableColumn.builder() + .id(COLUMN_1_1_ID) + .ordinalPosition(COLUMN_1_1_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_1_NAME) + .internalName(COLUMN_1_1_INTERNAL_NAME) + .columnType(COLUMN_1_1_TYPE) + .dfid(COLUMN_1_1_DATE_FORMAT) + .isNullAllowed(COLUMN_1_1_NULL) + .autoGenerated(COLUMN_1_1_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_1_PRIMARY) + .enumValues(COLUMN_1_1_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_2_ID) + .ordinalPosition(COLUMN_1_2_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_2_NAME) + .internalName(COLUMN_1_2_INTERNAL_NAME) + .columnType(COLUMN_1_2_TYPE) + .dfid(COLUMN_1_2_DATE_FORMAT) + .isNullAllowed(COLUMN_1_2_NULL) + .autoGenerated(COLUMN_1_2_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_2_PRIMARY) + .enumValues(COLUMN_1_2_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_3_ID) + .ordinalPosition(COLUMN_1_3_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_3_NAME) + .internalName(COLUMN_1_3_INTERNAL_NAME) + .columnType(COLUMN_1_3_TYPE) + .dfid(COLUMN_1_3_DATE_FORMAT) + .isNullAllowed(COLUMN_1_3_NULL) + .autoGenerated(COLUMN_1_3_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_3_PRIMARY) + .enumValues(COLUMN_1_3_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_4_ID) + .ordinalPosition(COLUMN_1_4_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_4_NAME) + .internalName(COLUMN_1_4_INTERNAL_NAME) + .columnType(COLUMN_1_4_TYPE) + .dfid(COLUMN_1_4_DATE_FORMAT) + .isNullAllowed(COLUMN_1_4_NULL) + .autoGenerated(COLUMN_1_4_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_4_PRIMARY) + .enumValues(COLUMN_1_4_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_5_ID) + .ordinalPosition(COLUMN_1_5_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_5_NAME) + .internalName(COLUMN_1_5_INTERNAL_NAME) + .columnType(COLUMN_1_5_TYPE) + .dfid(COLUMN_1_5_DATE_FORMAT) + .isNullAllowed(COLUMN_1_5_NULL) + .autoGenerated(COLUMN_1_5_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_5_PRIMARY) + .enumValues(COLUMN_1_5_ENUM_VALUES) + .creator(USER_1) + .build()); + public final static View VIEW_2 = View.builder() .id(VIEW_2_ID) .isInitialView(VIEW_2_INITIAL_VIEW) @@ -4012,6 +4175,7 @@ public abstract class BaseTest { .vcid(VIEW_2_CONTAINER_ID) .vdbid(VIEW_2_DATABASE_ID) .isPublic(VIEW_2_PUBLIC) + .columns(VIEW_2_COLUMNS) .query(VIEW_2_QUERY) .creator(USER_1) .createdBy(USER_1_ID) @@ -4035,7 +4199,68 @@ public abstract class BaseTest { public final static Long VIEW_3_CONTAINER_ID = CONTAINER_1_ID; public final static Long VIEW_3_DATABASE_ID = DATABASE_1_ID; public final static Boolean VIEW_3_PUBLIC = false; - public final static String VIEW_3_QUERY = "select w.`mintemp`, w.`rainfall`, w.`location`, m.`lat`, m.`lng` from `weather_aus` w join `junit2` m on m.`location` = w.`location`"; + public final static String VIEW_3_QUERY = "select w.`mintemp`, w.`rainfall`, w.`location`, m.`date` from `weather_aus` w join `junit2` m on m.`location` = w.`location`"; + + public final static List<TableColumn> VIEW_3_COLUMNS = List.of(TableColumn.builder() + .id(COLUMN_1_4_ID) + .ordinalPosition(COLUMN_1_4_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_4_NAME) + .internalName(COLUMN_1_4_INTERNAL_NAME) + .columnType(COLUMN_1_4_TYPE) + .dfid(COLUMN_1_4_DATE_FORMAT) + .isNullAllowed(COLUMN_1_4_NULL) + .autoGenerated(COLUMN_1_4_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_4_PRIMARY) + .enumValues(COLUMN_1_4_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_5_ID) + .ordinalPosition(COLUMN_1_5_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_5_NAME) + .internalName(COLUMN_1_5_INTERNAL_NAME) + .columnType(COLUMN_1_5_TYPE) + .dfid(COLUMN_1_5_DATE_FORMAT) + .isNullAllowed(COLUMN_1_5_NULL) + .autoGenerated(COLUMN_1_5_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_5_PRIMARY) + .enumValues(COLUMN_1_5_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_3_ID) + .ordinalPosition(COLUMN_1_3_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_3_NAME) + .internalName(COLUMN_1_3_INTERNAL_NAME) + .columnType(COLUMN_1_3_TYPE) + .dfid(COLUMN_1_3_DATE_FORMAT) + .isNullAllowed(COLUMN_1_3_NULL) + .autoGenerated(COLUMN_1_3_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_3_PRIMARY) + .enumValues(COLUMN_1_3_ENUM_VALUES) + .creator(USER_1) + .build(), + TableColumn.builder() + .id(COLUMN_1_2_ID) + .ordinalPosition(COLUMN_1_2_ORDINALPOS) + .cdbid(DATABASE_1_ID) + .tid(TABLE_1_ID) + .name(COLUMN_1_2_NAME) + .internalName(COLUMN_1_2_INTERNAL_NAME) + .columnType(COLUMN_1_2_TYPE) + .dfid(COLUMN_1_2_DATE_FORMAT) + .isNullAllowed(COLUMN_1_2_NULL) + .autoGenerated(COLUMN_1_2_AUTO_GENERATED) + .isPrimaryKey(COLUMN_1_2_PRIMARY) + .enumValues(COLUMN_1_2_ENUM_VALUES) + .creator(USER_1) + .build()); public final static View VIEW_3 = View.builder() .id(VIEW_3_ID) @@ -4045,6 +4270,7 @@ public abstract class BaseTest { .vcid(VIEW_3_CONTAINER_ID) .vdbid(VIEW_3_DATABASE_ID) .isPublic(VIEW_3_PUBLIC) + .columns(VIEW_3_COLUMNS) .query(VIEW_3_QUERY) .creator(USER_1) .createdBy(USER_1_ID) @@ -4067,8 +4293,262 @@ public abstract class BaseTest { public final static String VIEW_4_INTERNAL_NAME = "mock_view"; public final static Long VIEW_4_CONTAINER_ID = CONTAINER_2_ID; public final static Long VIEW_4_DATABASE_ID = DATABASE_2_ID; + public final static Long VIEW_4_TABLE_ID = TABLE_4_ID; public final static Boolean VIEW_4_PUBLIC = true; - public final static String VIEW_4_QUERY = "SELECT `animal_name`, `hair`, `feathers`, `eggs`, `milk`, `airborne`, `aquatic`, `predator`, `toothed`, `backbone`, `breathes`, `venomous`, `fins`, `legs`, `tail`, `domestic`, `catsize`, `class_type`FROM `zoo`WHERE `class_type` = 1"; + public final static String VIEW_4_QUERY = "SELECT `animal_name`, `hair`, `feathers`, `eggs`, `milk`, `airborne`, `aquatic`, `predator`, `toothed`, `backbone`, `breathes`, `venomous`, `fins`, `legs`, `tail`, `domestic`, `catsize`, `class_type` FROM `zoo` WHERE `class_type` = 1"; + + public final static List<TableColumn> VIEW_4_COLUMNS = List.of(TableColumn.builder() + .ordinalPosition(0) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("animal_name") + .internalName("animal_name") + .columnType(TableColumnType.STRING) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(1) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("hair") + .internalName("hair") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(2) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("feathers") + .internalName("feathers") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(3) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("eggs") + .internalName("eggs") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(4) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("milk") + .internalName("milk") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(5) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("airborne") + .internalName("airborne") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(6) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("aquatic") + .internalName("aquatic") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(7) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("predator") + .internalName("predator") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(8) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("toothed") + .internalName("toothed") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(9) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("backbone") + .internalName("backbone") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(10) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("breathes") + .internalName("breathes") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(11) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("venomous") + .internalName("venomous") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(12) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("fins") + .internalName("fins") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(13) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("legs") + .internalName("legs") + .columnType(TableColumnType.NUMBER) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(14) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("tail") + .internalName("tail") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(15) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("domestic") + .internalName("domestic") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(16) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("catsize") + .internalName("catsize") + .columnType(TableColumnType.BOOLEAN) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build(), + TableColumn.builder() + .ordinalPosition(17) + .cdbid(VIEW_4_DATABASE_ID) + .tid(VIEW_4_TABLE_ID) + .name("class_type") + .internalName("class_type") + .columnType(TableColumnType.NUMBER) + .dfid(null) + .isNullAllowed(null) + .autoGenerated(false) + .isPrimaryKey(false) + .enumValues(null) + .creator(USER_1) + .build()); public final static View VIEW_4 = View.builder() .id(VIEW_4_ID) @@ -4081,6 +4561,7 @@ public abstract class BaseTest { .query(VIEW_4_QUERY) .createdBy(USER_1_ID) .creator(USER_1) + .columns(VIEW_4_COLUMNS) .build(); public final static Long VIEW_5_ID = 5L; diff --git a/dbrepo-metadata-db/test/src/test/resources/weather/2_schema_data.sql b/dbrepo-metadata-db/test/src/test/resources/weather/2_schema_data.sql index c5d0a6a58c2169d09e92c0d5a7ebd701140672de..d82b0fc3d21b0465ea2b2dadb02cc339cff453c9 100644 --- a/dbrepo-metadata-db/test/src/test/resources/weather/2_schema_data.sql +++ b/dbrepo-metadata-db/test/src/test/resources/weather/2_schema_data.sql @@ -48,9 +48,9 @@ VALUES ('2022-12-24 17:00:00', 10.0), CREATE VIEW junit2 AS ( -SELECT `location`, `lat`, `lng` -FROM `weather_location` -WHERE `location` = 'Albury'); +select `date`, `location`, `mintemp`, `rainfall` +from `weather_aus` +where `location` = 'Albury'); CREATE VIEW `hs_weather_aus` AS SELECT * diff --git a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java index 7662f1dcbc9263b80139182624bb9406a1ddc592..726dc651d45c6220b1c67557675ec42f16adebb9 100644 --- a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java +++ b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java @@ -1,7 +1,6 @@ package at.tuwien.repository; import at.tuwien.BaseUnitTest; -import at.tuwien.config.H2Utils; import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.View; @@ -37,11 +36,9 @@ public class ViewRepositoryIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; - /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; - /* keep */ @MockBean private BrokerServiceGateway brokerServiceGateway; @@ -54,31 +51,37 @@ public class ViewRepositoryIntegrationTest extends BaseUnitTest { @Autowired private UserRepository userRepository; + @Autowired + private RealmRepository realmRepository; + @Autowired private ContainerRepository containerRepository; @Autowired - private DatabaseRepository databaseRepository; + private TableRepository tableRepository; @Autowired - private ViewRepository viewRepository; + private TableColumnRepository tableColumnRepository; @Autowired - private H2Utils h2Utils; + private DatabaseRepository databaseRepository; + + @Autowired + private ViewRepository viewRepository; @Rule public Timeout globalTimeout = Timeout.seconds(60); @BeforeEach public void beforeEach() { + realmRepository.save(REALM_DBREPO); userRepository.save(USER_1); imageRepository.save(IMAGE_1); - containerRepository.save(CONTAINER_1); - DATABASE_1.setTables(List.of()); - DATABASE_1.setViews(List.of()); - databaseRepository.save(DATABASE_1); + containerRepository.save(CONTAINER_1_SIMPLE); + databaseRepository.save(DATABASE_1_SIMPLE); + tableRepository.saveAll(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_7)); viewRepository.save(VIEW_1); - viewRepository.save(VIEW_2); + viewRepository.save(VIEW_3); viewRepository.save(VIEW_3); } @@ -87,15 +90,7 @@ public class ViewRepositoryIntegrationTest extends BaseUnitTest { /* test */ final List<View> response = viewRepository.findAllPublicByDatabaseId(DATABASE_1_ID); - assertEquals(2, response.size()); - final View view1 = response.get(0); - assertEquals(VIEW_1_ID, view1.getId()); - assertEquals(VIEW_1_CONTAINER_ID, view1.getVcid()); - assertEquals(VIEW_1_DATABASE_ID, view1.getVdbid()); - final View view2 = response.get(1); - assertEquals(VIEW_2_ID, view2.getId()); - assertEquals(VIEW_2_CONTAINER_ID, view2.getVcid()); - assertEquals(VIEW_2_DATABASE_ID, view2.getVdbid()); + assertEquals(1, response.size()); } @Test @@ -104,18 +99,6 @@ public class ViewRepositoryIntegrationTest extends BaseUnitTest { /* test */ final List<View> response = viewRepository.findAllPublicOrMineByDatabaseId(DATABASE_1_ID, USER_1_USERNAME); assertEquals(3, response.size()); - final View view1 = response.get(0); - assertEquals(VIEW_1_ID, view1.getId()); - assertEquals(VIEW_1_CONTAINER_ID, view1.getVcid()); - assertEquals(VIEW_1_DATABASE_ID, view1.getVdbid()); - final View view2 = response.get(1); - assertEquals(VIEW_2_ID, view2.getId()); - assertEquals(VIEW_2_CONTAINER_ID, view2.getVcid()); - assertEquals(VIEW_2_DATABASE_ID, view2.getVdbid()); - final View view3 = response.get(2); - assertEquals(VIEW_3_ID, view3.getId()); - assertEquals(VIEW_3_CONTAINER_ID, view3.getVcid()); - assertEquals(VIEW_3_DATABASE_ID, view3.getVdbid()); } } diff --git a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java index 874ca99157c3feb8db0464c91912f07e1005354a..cfef081d1eb3abf3fd94d998702b095f59b64f3d 100644 --- a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java +++ b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java @@ -10,7 +10,6 @@ import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.*; import at.tuwien.gateway.BrokerServiceGateway; -import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.querystore.Query; import at.tuwien.repository.jpa.*; @@ -47,7 +46,7 @@ import static org.mockito.Mockito.when; @Log4j2 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -@EnableAutoConfiguration(exclude= RabbitAutoConfiguration.class) +@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class) @SpringBootTest @ExtendWith(SpringExtension.class) public class QueryServiceIntegrationTest extends BaseUnitTest { @@ -86,19 +85,6 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { private final static String BIND_ZOO = new File("../../dbrepo-metadata-db/test/src/test/resources/zoo").toPath().toAbsolutePath() + ":/docker-entrypoint-initdb.d"; - @BeforeAll - public static void beforeAll() { - afterAll(); - /* create network */ - DockerConfig.createAllNetworks(); - } - - @AfterAll - public static void afterAll() { - DockerConfig.removeAllContainers(); - DockerConfig.removeAllNetworks(); - } - @BeforeEach public void beforeEach() { afterEach(); @@ -106,17 +92,9 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { DockerConfig.createAllNetworks(); /* metadata database */ DATABASE_1.setTables(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_7)); - TABLE_1.setDatabase(DATABASE_1); - TABLE_1.setColumns(TABLE_1_COLUMNS); - TABLE_2.setDatabase(DATABASE_1); - TABLE_3.setDatabase(DATABASE_1); - TABLE_7.setDatabase(DATABASE_1); + DATABASE_1.setViews(List.of(VIEW_2, VIEW_3)); DATABASE_2.setTables(List.of(TABLE_4, TABLE_5, TABLE_6)); DATABASE_2.setViews(List.of(VIEW_4)); - TABLE_4.setDatabase(DATABASE_2); - TABLE_5.setDatabase(DATABASE_2); - TABLE_6.setDatabase(DATABASE_2); - VIEW_4.setDatabase(DATABASE_2); } @AfterEach @@ -539,9 +517,90 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { 0L, 100L, null, null); assertEquals(1L, response.getResultNumber()); assertNotNull(response.getResult()); + } + + @Test + public void execute_aliases_succeeds() throws DatabaseConnectionException, TableMalformedException, + DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, QueryMalformedException, + UserNotFoundException, QueryStoreException, ColumnParseException, InterruptedException { + final ExecuteStatementDto request = ExecuteStatementDto.builder() + .statement("SELECT aus.location as a, loc.location from weather_aus aus, weather_location loc") + .build(); + + /* mock */ + DockerConfig.createContainer(BIND_WEATHER, CONTAINER_1, CONTAINER_1_ENV); + DockerConfig.startContainer(CONTAINER_1); + when(databaseRepository.findByContainerIdAndDatabaseId(CONTAINER_1_ID, DATABASE_1_ID)) + .thenReturn(Optional.of(DATABASE_1)); + when(userRepository.findByUsername(USER_1_USERNAME)) + .thenReturn(Optional.of(USER_1)); + + /* test */ + final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, USER_1_PRINCIPAL, + 0L, 100L, null, null); + assertEquals(9L, response.getResultNumber()); + assertNotNull(response.getResult()); final List<Map<String, Object>> result = response.getResult(); - assertNull(result.get(0).get("lat")); - assertNull(result.get(0).get("lng")); + assertEquals("Albury", result.get(0).get("a")); + assertEquals("Albury", result.get(0).get("location")); + assertEquals("Albury", result.get(1).get("a")); + assertEquals("Albury", result.get(1).get("location")); + assertEquals("Albury", result.get(2).get("a")); + assertEquals("Albury", result.get(2).get("location")); + assertEquals("Albury", result.get(3).get("a")); + assertEquals("Sydney", result.get(3).get("location")); + assertEquals("Albury", result.get(4).get("a")); + assertEquals("Sydney", result.get(4).get("location")); + assertEquals("Albury", result.get(5).get("a")); + assertEquals("Sydney", result.get(5).get("location")); + assertEquals("Albury", result.get(6).get("a")); + assertEquals("Vienna", result.get(6).get("location")); + assertEquals("Albury", result.get(7).get("a")); + assertEquals("Vienna", result.get(7).get("location")); + assertEquals("Albury", result.get(8).get("a")); + assertEquals("Vienna", result.get(8).get("location")); + } + + @Test + public void execute_aliasesWithDatabaseName_succeeds() throws DatabaseConnectionException, TableMalformedException, + DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, QueryMalformedException, + UserNotFoundException, QueryStoreException, ColumnParseException, InterruptedException { + final ExecuteStatementDto request = ExecuteStatementDto.builder() + .statement("SELECT aus.location as a, loc.location from weather.weather_aus aus, weather.weather_location loc") + .build(); + + /* mock */ + DockerConfig.createContainer(BIND_WEATHER, CONTAINER_1, CONTAINER_1_ENV); + DockerConfig.startContainer(CONTAINER_1); + when(databaseRepository.findByContainerIdAndDatabaseId(CONTAINER_1_ID, DATABASE_1_ID)) + .thenReturn(Optional.of(DATABASE_1)); + when(userRepository.findByUsername(USER_1_USERNAME)) + .thenReturn(Optional.of(USER_1)); + + /* test */ + final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, USER_1_PRINCIPAL, + 0L, 100L, null, null); + assertEquals(9L, response.getResultNumber()); + assertNotNull(response.getResult()); + final List<Map<String, Object>> result = response.getResult(); + assertEquals("Albury", result.get(0).get("a")); + assertEquals("Albury", result.get(0).get("location")); + assertEquals("Albury", result.get(1).get("a")); + assertEquals("Albury", result.get(1).get("location")); + assertEquals("Albury", result.get(2).get("a")); + assertEquals("Albury", result.get(2).get("location")); + assertEquals("Albury", result.get(3).get("a")); + assertEquals("Sydney", result.get(3).get("location")); + assertEquals("Albury", result.get(4).get("a")); + assertEquals("Sydney", result.get(4).get("location")); + assertEquals("Albury", result.get(5).get("a")); + assertEquals("Sydney", result.get(5).get("location")); + assertEquals("Albury", result.get(6).get("a")); + assertEquals("Vienna", result.get(6).get("location")); + assertEquals("Albury", result.get(7).get("a")); + assertEquals("Vienna", result.get(7).get("location")); + assertEquals("Albury", result.get(8).get("a")); + assertEquals("Vienna", result.get(8).get("location")); } @Test diff --git a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index 2d264ca8905f2a8ff03da5d7c1b9c31419884cbe..dd8135d60e59922c405f6b69ca50e98f136b094b 100644 --- a/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/dbrepo-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -129,22 +129,20 @@ public class ViewServiceIntegrationTest extends BaseUnitTest { assertEquals(VIEW_3_INTERNAL_NAME, response.getInternalName()); assertEquals(VIEW_3_QUERY, response.getQuery()); final List<Map<String, String>> resultSet = MariaDbConfig.selectQuery(CONTAINER_1_INTERNALNAME, DATABASE_1_INTERNALNAME, - "SELECT j.* FROM `debug` j", "mintemp", "rainfall", "location", "lat", "lng"); + "SELECT j.* FROM `debug` j", "mintemp", "rainfall", "date", "location"); assertEquals("13.4", resultSet.get(0).get("mintemp")); assertEquals("0.6", resultSet.get(0).get("rainfall")); assertEquals("Albury", resultSet.get(0).get("location")); - assertEquals("-36.0653583", resultSet.get(0).get("lat")); - assertEquals("146.9112214", resultSet.get(0).get("lng")); + assertEquals("2008-12-01", resultSet.get(0).get("date")); assertEquals("7.4", resultSet.get(1).get("mintemp")); assertEquals("0", resultSet.get(1).get("rainfall")); assertEquals("Albury", resultSet.get(1).get("location")); - assertEquals("-36.0653583", resultSet.get(1).get("lat")); - assertEquals("146.9112214", resultSet.get(1).get("lng")); + assertEquals("2008-12-01", resultSet.get(1).get("date")); assertEquals("12.9", resultSet.get(2).get("mintemp")); assertEquals("0", resultSet.get(2).get("rainfall")); assertEquals("Albury", resultSet.get(2).get("location")); - assertEquals("-36.0653583", resultSet.get(2).get("lat")); - assertEquals("146.9112214", resultSet.get(2).get("lng")); + assertEquals("2008-12-01", resultSet.get(2).get("date")); + /* more result checks omitted */ } @Test diff --git a/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java index 0506192ecb16e1be14a9561614f214a10c0c8a5b..f3ddd14c588c73e6302f81a9cf6aee03b85a1c05 100644 --- a/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java +++ b/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java @@ -76,12 +76,13 @@ public interface QueryMapper { /* map the result set to the columns through the stored metadata in the metadata database */ int[] idx = new int[]{1}; final Map<String, Object> map = new HashMap<>(); - for (int i = 0; i < columns.size(); i++) { - final Object object = dataColumnToObject(result.getObject(idx[0]++), columns.get(i)); + for (final TableColumn column : columns) { + final Object object = dataColumnToObject(result.getObject(idx[0]++), column); if (object == null) { - log.warn("result set for column {} is empty (=null)", columns.get(0).getInternalName()); + log.warn("result set for column {} is empty (=null)", column.getInternalName()); } - map.put(columns.get(i).getInternalName(), object); + final String columnOrAlias = column.getAlias() != null ? column.getAlias() : column.getInternalName(); + map.put(columnOrAlias, object); } resultList.add(map); } @@ -604,7 +605,7 @@ public interface QueryMapper { final StringBuilder statement = new StringBuilder("SELECT COUNT(*) FROM `") .append(nameToInternalName(tableName)) .append("`"); - if(timestamp != null) { + if (timestamp != null) { statement.append(" FOR SYSTEM_TIME AS OF TIMESTAMP '") .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))) .append("'"); @@ -633,58 +634,35 @@ public interface QueryMapper { query = query.substring(0, query.length() - 1); } /* query check (this is enforced by the db also) */ - final String query_ = query; - if (Stream.of("count").anyMatch(query_::contains)) { + if (Stream.of("count").anyMatch(query::contains)) { log.error("Query contains unsupported operation, one of {}", List.of("COUNT")); } - if (Stream.of("delete", "update", "truncate", "create", "drop").anyMatch(query_::contains)) { + if (Stream.of("delete", "update", "truncate", "create", "drop").anyMatch(query::contains)) { log.error("Query attempts to modify the database"); throw new QueryMalformedException("Query attempts to modify the database"); } - /* insert the FOR SYSTEM_TIME ... part after the FROM in the query */ - final StringBuilder versionPart = new StringBuilder(" FOR SYSTEM_TIME AS OF TIMESTAMP'") - .append(mariaDbFormatter.format(timestamp)) - .append("' "); - final Pattern pattern = Pattern.compile("from `?[a-z0-9-_]+`?(,? *`?[a-z0-9-_]+`)*", Pattern.CASE_INSENSITIVE) /* https://mariadb.com/kb/en/columnstore-naming-conventions/ */; - final Matcher matcher = pattern.matcher(query_); - if (!matcher.find()) { - log.error("Failed to find 'from' clause in query"); - throw new QueryMalformedException("Failed to find from clause"); - } - log.trace("found group from {} to {} in '{}'", matcher.start(), matcher.end(), query_); final StringBuilder sb = new StringBuilder(); - if (!selection) { - /* is count query */ + if (selection) { + /* is not a count query */ + sb.append("SELECT * FROM ("); + } else { sb.append("SELECT COUNT(*) FROM ("); } - sb.append(query_, 0, matcher.end()); - if (!query.contains("join")) { - sb.append(versionPart); - } - sb.append(query, matcher.end(), query.length()); - if (!query.contains("limit") && !query.contains("offset") && size != null && page != null) { - log.trace("pagination size/limit of {}", size); - sb.append(" LIMIT ") - .append(size); - log.trace("pagination page/offset of {}", page); - sb.append(" OFFSET ") - .append(page * size); - } - if (!selection) { - /* is count query */ - sb.append(") as tbl"); - } - String statement = sb.append(";") - .toString(); - if (query.contains("join")) { - statement = statement.replaceFirst("from ([`a-z0-9-_]+) ", "from $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) - + "' "); - statement = statement.replaceAll("join ([`a-z0-9-_]+) ", "join $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" - + LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC")) - + "' "); - } - return statement.toString(); + /* insert statement */ + sb.append(query); + /* system time */ + sb.append(") FOR SYSTEM_TIME AS OF TIMESTAMP '") + .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))) + .append("' as tbl"); + /* pagination */ + log.trace("pagination size/limit of {}", size); + sb.append(" LIMIT ") + .append(size); + log.trace("pagination page/offset of {}", page); + sb.append(" OFFSET ") + .append(page * size); + sb.append(";"); + return sb.toString(); } default String tableToRawFindAllQuery(Table table, Instant timestamp, Long size, Long page) @@ -720,9 +698,9 @@ public interface QueryMapper { final int[] idx = new int[]{0}; final StringBuilder statement = new StringBuilder("SELECT "); columns.forEach(column -> statement.append(idx[0]++ > 0 ? "," : "") - .append("`") - .append(column.getInternalName()) - .append("`")); + .append("`") + .append(column.getInternalName()) + .append("`")); statement.append(" FROM `") .append(nameToInternalName(tableName)) .append("`"); diff --git a/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java index d1d1094578440f6391bb0d96db468e1f9b93b3f0..b230ecadb520d8e9dd75f8e4a034fefbdaa516b0 100644 --- a/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java +++ b/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java @@ -22,6 +22,7 @@ import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserManager; +import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.select.*; import org.apache.commons.io.FileUtils; @@ -43,6 +44,7 @@ import java.time.Instant; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Log4j2 @@ -91,10 +93,6 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); } - final User root = databaseMapper.containerToPrivilegedUser(database.getContainer()); - /* run query */ - final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), - database.getContainer(), database, root); /* map the result to the tables (with respective columns) from the statement metadata */ final List<TableColumn> columns; try { @@ -105,7 +103,6 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService } final String statement = queryMapper.queryToRawTimestampedQuery(query.getQuery(), database, query.getCreated(), true, page, size); final QueryResultDto dto = executeNonPersistent(containerId, databaseId, statement, columns); - dto.setId(query.getId()); dto.setResultNumber(query.getResultNumber()); return dto; @@ -134,9 +131,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService private PreparedStatement prepareStatement(Connection connection, String statement) throws QueryMalformedException { try { - final PreparedStatement pstmt = connection.prepareStatement(statement); - log.trace("mapped timestamped query {} to prepared statement {}", statement, pstmt); - return pstmt; + return connection.prepareStatement(statement); } catch (SQLException e) { log.error("Failed to prepare statement {}m reason: {}", statement, e.getMessage()); throw new QueryMalformedException("Failed to prepare statement", e); @@ -468,65 +463,86 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService final List<SelectItem> clauses = ps.getSelectItems(); log.trace("columns referenced in the from-clause: {}", clauses); /* Parse all tables */ - final List<FromItem> tables = new ArrayList<>(); - tables.add(ps.getFromItem()); + final List<FromItem> tablesOrViews = new ArrayList<>(); + tablesOrViews.add(ps.getFromItem()); if (ps.getJoins() != null && ps.getJoins().size() > 0) { log.trace("query contains join items: {}", ps.getJoins()); for (Join j : ps.getJoins()) { if (j.getRightItem() != null) { - tables.add(j.getRightItem()); + tablesOrViews.add(j.getRightItem()); } } } log.trace("columns referenced in the from-clause and join-clause(s): {}", clauses); /* Checking if all tables or views exist */ final List<TableColumn> allColumns = new ArrayList<>(); - for (FromItem fromItem : tables) { - boolean foundTable = false; - boolean foundView = false; - for (Table table : database.getTables()) { - allColumns.addAll(table.getColumns()); - if (table.equals(fromItem)) { - log.trace("table {} equals from item {}", table.getInternalName(), fromItem); - foundTable = true; - break; - } - log.trace("table {} did not equal from item {}", table.getInternalName(), fromItem); - } - for (View view : database.getViews()) { - if (view.equals(fromItem)) { - log.trace("view {} equals from item {}", view.getInternalName(), fromItem); - foundView = true; - break; - } - log.trace("view {} did not equal from item {}", view.getInternalName(), fromItem); - } - if (!foundView && !foundTable) { - final String tableName = queryMapper.stringToEscapedString(fromItem.toString()); - log.error("Table or view {} does not exist in tables {} or views {}", tableName, - database.getTables().stream().map(Table::getInternalName).collect(Collectors.toList()), - database.getViews().stream().map(View::getInternalName).collect(Collectors.toList())); - throw new JSQLParserException("Table or view does not exist"); - } - } + database.getTables() + .forEach(table -> { + table.getColumns() + .forEach(column -> { + final TableColumn tmp = column.toBuilder() /* copy constructor */ + .table(table) + .build(); + allColumns.add(tmp); + }); + }); + database.getViews() + .forEach(view -> { + view.getColumns() + .forEach(column -> { + final TableColumn tmp = column.toBuilder() /* copy constructor */ + .view(view) + .build(); + allColumns.add(tmp); + }); + }); + final List<TableColumn> col = allColumns.stream().filter(c -> c.getInternalName().equals("date")).toList(); + log.trace(""); + log.trace("table(s) or view(s) referenced in the statement: {}", tablesOrViews.stream().map(t -> ((net.sf.jsqlparser.schema.Table) t).getName()).collect(Collectors.toList())); /* Checking if all columns exist */ - for (SelectItem item : clauses) { - if (item.toString().trim().equals("*")) { - log.error("Do not use * in queries"); - continue; + for (SelectItem clause : clauses) { + final SelectExpressionItem item = (SelectExpressionItem) clause; + final Column column = (Column) item.getExpression(); + final Optional<net.sf.jsqlparser.schema.Table> optionalTableOrView = tablesOrViews.stream() + .map(t -> (net.sf.jsqlparser.schema.Table) t) + .filter(t -> { + if (column.getTable() == null) { + /* column does not reference a specific table, so there is only one table */ + final String tableName = ((net.sf.jsqlparser.schema.Table) tablesOrViews.get(0)).getName().replace("`", ""); + if (t.getAlias() == null) { + /* table is non-aliased */ + return t.getName().replace("`", "").equals(tableName); + } + /* has alias */ + return t.getAlias().getName().equals(tableName); + } + final String tableName = column.getTable().getName().replace("`", ""); + if (t.getAlias() == null) { + /* table is non-aliased */ + return t.getName().replace("`", "").equals(tableName); + } + /* has alias */ + return t.getAlias().getName().equals(tableName); + }) + .findFirst(); + if (optionalTableOrView.isEmpty()) { + log.error("Failed to find table or view with alias '{}'", column.getTable().getAlias()); + throw new JSQLParserException("Failed to find table or view with alias " + column.getTable().getAlias()); } - boolean foundColumn = false; - for (TableColumn column : allColumns) { - if (column.equals(item)) { - columns.add(column); - foundColumn = true; - break; - } + final String tableOrViewName = optionalTableOrView.get().getName().replace("`", ""); + final Optional<TableColumn> optionalColumn = allColumns.stream() + .filter(c -> c.getTable() == null ? c.getView().getInternalName().equals(tableOrViewName) : c.getTable().getInternalName().equals(tableOrViewName)) + .filter(c -> c.getInternalName().equals(column.getColumnName().replace("`", ""))) + .findFirst(); + if (optionalColumn.isEmpty()) { + throw new JSQLParserException("Failed to find column with name " + column.getColumnName()); } - if (!foundColumn) { - log.error("Column {} does not exist in columns {}", item, allColumns.stream().map(TableColumn::getInternalName).collect(Collectors.toList())); - throw new JSQLParserException("Column does not exist"); + final TableColumn aliasColumn = optionalColumn.get(); + if (item.getAlias() != null) { + aliasColumn.setAlias(item.getAlias().getName()); } + log.trace("found column with internal name {} and alias {}", aliasColumn.getInternalName(), aliasColumn.getAlias()); + columns.add(aliasColumn); } return columns; }