Skip to content

Commit 75150e3

Browse files
committed
Merge branch 'main' of github.com:hypertrace/document-store into schema_cache
2 parents 31f16e2 + a7acef1 commit 75150e3

File tree

15 files changed

+184
-32
lines changed

15 files changed

+184
-32
lines changed

document-store/src/integrationTest/java/org/hypertrace/core/documentstore/DocStoreQueryV1Test.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,26 @@ void testNotContainsAndUnnestFilters(String dataStoreName) throws IOException {
19151915
dataStoreName, iterator, "query/unwind_not_contains_filter_response.json", 2);
19161916
}
19171917

1918+
@ParameterizedTest
1919+
@ArgumentsSource(PostgresProvider.class)
1920+
public void testUnnestTopLevelArrayWithNullValue(String dataStoreName) throws IOException {
1921+
Collection collection = getFlatCollection(dataStoreName);
1922+
1923+
Query query =
1924+
Query.builder()
1925+
.addSelection(IdentifierExpression.of("item"))
1926+
.addSelection(IdentifierExpression.of("categoryTags"))
1927+
.addFromClause(UnnestExpression.of(IdentifierExpression.of("categoryTags"), true))
1928+
.setFilter(
1929+
RelationalExpression.of(
1930+
IdentifierExpression.of("item"), EQ, ConstantExpression.of("Bottle")))
1931+
.build();
1932+
1933+
Iterator<Document> iterator = collection.aggregate(query);
1934+
assertDocsAndSizeEqualWithoutOrder(
1935+
dataStoreName, iterator, "query/unnest_null_top_level_array_response.json", 1);
1936+
}
1937+
19181938
@ParameterizedTest
19191939
@ArgumentsSource(AllProvider.class)
19201940
public void testQueryV1DistinctCountWithSortingSpecs(String dataStoreName) throws IOException {
@@ -5575,6 +5595,49 @@ void testNotInOnUnnestedArray(String dataStoreName) throws Exception {
55755595
assertEquals(12, count, "Should return unnested locations not matching the filter");
55765596
}
55775597

5598+
@ParameterizedTest
5599+
@ArgumentsSource(PostgresProvider.class)
5600+
public void testUnnestNestedArrayWithNullValue(String dataStoreName) throws IOException {
5601+
Collection collection = getFlatCollection(dataStoreName);
5602+
5603+
Query query =
5604+
Query.builder()
5605+
.addSelection(IdentifierExpression.of("item"))
5606+
.addFromClause(
5607+
UnnestExpression.of(JsonIdentifierExpression.of("props", "source-loc"), true))
5608+
.setFilter(
5609+
RelationalExpression.of(
5610+
IdentifierExpression.of("_id"), EQ, ConstantExpression.of(1)))
5611+
.build();
5612+
5613+
Iterator<Document> iterator = collection.aggregate(query);
5614+
assertDocsAndSizeEqualWithoutOrder(
5615+
dataStoreName, iterator, "query/unnest_null_nested_array_response.json", 2);
5616+
}
5617+
5618+
@ParameterizedTest
5619+
@ArgumentsSource(PostgresProvider.class)
5620+
public void testArrayFilterAnyWithJsonNullArray(String dataStoreName) {
5621+
Collection collection = getFlatCollection(dataStoreName);
5622+
5623+
Query query =
5624+
Query.builder()
5625+
.addSelection(IdentifierExpression.of("item"))
5626+
.setFilter(
5627+
ArrayRelationalFilterExpression.builder()
5628+
.operator(ArrayOperator.ANY)
5629+
.filter(
5630+
RelationalExpression.of(
5631+
JsonIdentifierExpression.of("props", "colors"),
5632+
EQ,
5633+
ConstantExpression.of("Blue")))
5634+
.build())
5635+
.build();
5636+
5637+
long count = collection.count(query);
5638+
assertEquals(2, count, "Should find 2 items with 'Blue' color");
5639+
}
5640+
55785641
@ParameterizedTest
55795642
@ArgumentsSource(PostgresProvider.class)
55805643
void testExistsOnArrays(String dataStoreName) throws JsonProcessingException {

document-store/src/integrationTest/resources/query/pg_flat_collection_insert.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n4, 'Shampoo', 5, 20, '2014-04-04T11:21:39.736Z', false,\n'{\"hair-care\", \"budget\", \"bulk\"}',\n'{\"HairCare\"}',\nNULL,\nNULL,\n'{1, 2}',\n'{5.0, 10.0}',\n'{true, true}'\n)",
77
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n5, 'Soap', 20, 5, '2014-04-04T21:23:13.331Z', true,\n'{\"hygiene\", \"antibacterial\", \"family-pack\"}',\n'{\"Hygiene\"}',\n'{\"colors\": [\"Orange\", \"Blue\"], \"brand\": \"Lifebuoy\", \"size\": \"S\", \"product-code\": \"SOAP-LIF-005\", \"source-loc\": [\"warehouse-C\"], \"seller\": {\"name\": \"Hans and Co.\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL,\n'{3, 6, 9}',\n'{7.5}',\n'{false}'\n)",
88
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n6, 'Comb', 7.5, 5, '2015-06-04T05:08:13Z', true,\n'{\"grooming\", \"plastic\", \"essential\"}',\n'{\"Grooming\"}',\nNULL,\nNULL,\n'{20, 30}',\n'{6.0, 8.0}',\n'{true, false}'\n)",
9-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n7, 'Comb', 7.5, 10, '2015-09-10T08:43:00Z', false,\n'{\"grooming\", \"bulk\", \"wholesale\"}',\n'{\"Grooming\"}',\n'{\"colors\": [], \"product-code\": null, \"source-loc\": [], \"seller\": {\"name\": \"Go Go Plastics\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL,\n'{10}',\n'{3.0}',\n'{false, false, false}'\n)",
9+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n7, 'Comb', 7.5, 10, '2015-09-10T08:43:00Z', false,\n'{\"grooming\", \"bulk\", \"wholesale\"}',\n'{\"Grooming\"}',\n'{\"colors\": [], \"product-code\": null, \"source-loc\": null, \"seller\": {\"name\": \"Go Go Plastics\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL,\n'{10}',\n'{3.0}',\n'{false, false, false}'\n)",
1010
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n8, 'Soap', 10, 5, '2016-02-06T20:20:13Z', true,\n'{\"hygiene\", \"budget\", \"basic\"}',\n'{\"Hygiene\"}',\nNULL,\nNULL,\n'{1, 10, 20}',\n'{2.5, 5.0}',\n'{true}'\n)",
1111
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n9, 'Bottle', 15, 3, '2016-03-01T10:00:00Z', false,\nNULL,\nNULL,\nNULL,\nNULL,\nNULL,\nNULL,\nNULL\n)",
1212
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"in_stock\", \"tags\", \"categoryTags\", \"props\", \"sales\", \"numbers\", \"scores\", \"flags\"\n) VALUES (\n10, 'Cup', 8, 2, '2016-04-01T10:00:00Z', true,\n'{}',\n'{}',\nNULL,\nNULL,\nNULL,\nNULL,\nNULL\n)"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"item": "Soap"
4+
},
5+
{
6+
"item": "Soap"
7+
}
8+
]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
{
3+
"item": "Bottle"
4+
}
5+
]

document-store/src/main/java/org/hypertrace/core/documentstore/TypesafeDatastoreConfigAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public DatastoreConfig convert(final Config config) {
9393
connectionConfig.credentials(),
9494
connectionConfig.applicationName(),
9595
connectionConfig.connectionPoolConfig(),
96+
connectionConfig.queryTimeout(),
9697
connectionConfig.schemaCacheExpiry(),
9798
connectionConfig.schemaRefreshCooldown(),
9899
connectionConfig.customParameters()) {

document-store/src/main/java/org/hypertrace/core/documentstore/model/config/ConnectionConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public ConnectionConfig build() {
126126
credentials,
127127
applicationName,
128128
connectionPoolConfig,
129+
queryTimeout,
129130
null,
130131
null,
131132
customParameters);

document-store/src/main/java/org/hypertrace/core/documentstore/model/config/postgres/PostgresConnectionConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class PostgresConnectionConfig extends ConnectionConfig {
4040

4141
@NonNull String applicationName;
4242
@NonNull ConnectionPoolConfig connectionPoolConfig;
43+
@NonNull Duration queryTimeout;
4344
@NonNull Duration schemaCacheExpiry;
4445
@NonNull Duration schemaRefreshCooldown;
4546

@@ -53,6 +54,7 @@ public PostgresConnectionConfig(
5354
@Nullable final ConnectionCredentials credentials,
5455
@NonNull final String applicationName,
5556
@Nullable final ConnectionPoolConfig connectionPoolConfig,
57+
@NonNull final Duration queryTimeout,
5658
@Nullable final Duration schemaCacheExpiry,
5759
@Nullable final Duration schemaRefreshCooldown,
5860
@NonNull final Map<String, String> customParameters) {
@@ -63,6 +65,7 @@ public PostgresConnectionConfig(
6365
customParameters);
6466
this.applicationName = applicationName;
6567
this.connectionPoolConfig = getConnectionPoolConfigOrDefault(connectionPoolConfig);
68+
this.queryTimeout = queryTimeout;
6669
this.schemaCacheExpiry = getSchemaCacheExpiryOrDefault(schemaCacheExpiry);
6770
this.schemaRefreshCooldown = getSchemaRefreshCooldownOrDefault(schemaRefreshCooldown);
6871
}

document-store/src/main/java/org/hypertrace/core/documentstore/postgres/PostgresClient.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public Map<String, String> getCustomParameters() {
6969
return connectionConfig.customParameters();
7070
}
7171

72+
public int getQueryTimeoutSeconds() {
73+
return (int) connectionConfig.queryTimeout().toSeconds();
74+
}
75+
7276
public void close() {
7377
if (connection != null) {
7478
try {

document-store/src/main/java/org/hypertrace/core/documentstore/postgres/PostgresCollection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public PostgresCollection(final PostgresClient client, final String collectionNa
113113
this.tableIdentifier = tableIdentifier;
114114
this.subDocUpdater =
115115
new PostgresSubDocumentUpdater(new PostgresQueryBuilder(this.tableIdentifier));
116-
this.queryExecutor = new PostgresQueryExecutor();
116+
this.queryExecutor = new PostgresQueryExecutor(client.getQueryTimeoutSeconds());
117117
this.updateValidator = new CommonUpdateValidator();
118118
}
119119

document-store/src/main/java/org/hypertrace/core/documentstore/postgres/PostgresQueryExecutor.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@
66
import java.sql.PreparedStatement;
77
import java.sql.ResultSet;
88
import java.sql.SQLException;
9-
import lombok.AllArgsConstructor;
109
import lombok.extern.slf4j.Slf4j;
1110
import org.hypertrace.core.documentstore.postgres.query.v1.PostgresQueryParser;
1211
import org.hypertrace.core.documentstore.postgres.query.v1.transformer.PostgresQueryTransformer;
1312

1413
@Slf4j
15-
@AllArgsConstructor
1614
public class PostgresQueryExecutor {
1715

16+
private final int queryTimeoutSeconds;
17+
18+
public PostgresQueryExecutor(int queryTimeoutSeconds) {
19+
this.queryTimeoutSeconds = queryTimeoutSeconds;
20+
}
21+
1822
static org.hypertrace.core.documentstore.query.Query transformAndLog(
1923
org.hypertrace.core.documentstore.query.Query query) {
2024
log.debug("Original query before transformation: {}", query);
@@ -28,7 +32,8 @@ protected ResultSet execute(final Connection connection, PostgresQueryParser que
2832
final String sqlQuery = queryParser.parse();
2933
final Params params = queryParser.getParamsBuilder().build();
3034
// this is closed when the corresponding ResultSet is closed in the iterators
31-
PreparedStatement preparedStatement = buildPreparedStatement(sqlQuery, params, connection);
35+
PreparedStatement preparedStatement =
36+
buildPreparedStatement(sqlQuery, params, connection, queryTimeoutSeconds);
3237
try {
3338
log.debug("Executing SQL query: {}", sqlQuery);
3439
return preparedStatement.executeQuery();
@@ -45,7 +50,16 @@ protected ResultSet execute(final Connection connection, PostgresQueryParser que
4550

4651
public PreparedStatement buildPreparedStatement(
4752
String sqlQuery, Params params, Connection connection) throws SQLException {
53+
return buildPreparedStatement(sqlQuery, params, connection, this.queryTimeoutSeconds);
54+
}
55+
56+
public PreparedStatement buildPreparedStatement(
57+
String sqlQuery, Params params, Connection connection, int queryTimeoutSeconds)
58+
throws SQLException {
4859
PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);
60+
if (queryTimeoutSeconds > 0) {
61+
preparedStatement.setQueryTimeout(queryTimeoutSeconds);
62+
}
4963
enrichPreparedStatementWithParams(preparedStatement, params);
5064
return preparedStatement;
5165
}

0 commit comments

Comments
 (0)