Skip to content

Commit

Permalink
MODSOURCE-763: Adjust condition operands to work with marc_indexers i…
Browse files Browse the repository at this point in the history
…tself
  • Loading branch information
Maksat-Galymzhan committed Jun 20, 2024
1 parent dd267e7 commit 16d13d6
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 232 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ private static List<Lexeme> getLexemes(String expression) {

private static String processExpression(String expression, List<Lexeme> lexemes) {
if (expression.matches(MARC_FIELD.getSearchValue()) || expression.matches(LEADER_FIELD.getSearchValue())) {
String splitResult[] = expression.split(SPACE, 3);
String[] splitResult = expression.split(SPACE, 3);
String leftOperand = splitResult[0];
String operator = splitResult[1];
String rightSuffix[] = splitResult[2].split("'*'", 3);
String[] rightSuffix = splitResult[2].split("'*'", 3);
String rightOperand = rightSuffix[1];
lexemes.add(BinaryOperandLexeme.of(leftOperand, operator, rightOperand));
return rightSuffix[2];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,22 @@ public static boolean matches(String key) {

@Override
public String toSqlRepresentation() {
String iField = "\"i" + key.substring(0, key.indexOf('.')) + "\"";
StringBuilder builder = new StringBuilder("to_date(substring(").append(iField).append(".\"value\", 1, 8), '").append(DATE_PATTERN).append("')");
String[] keyParts = getKey().split("\\.");
String field = keyParts[0];
String fieldNumberToSearch = "\"field_no\" = '" + field + "'";

StringBuilder builder = new StringBuilder("("+fieldNumberToSearch + " and to_date(substring(").append("value, 1, 8), '").append(DATE_PATTERN).append("')");

if (BINARY_OPERATOR_EQUALS.equals(getOperator()) && !this.rangeSearch) {
return builder.append(" = ?").toString();
return builder.append(" = ?)").toString();
} else if (BINARY_OPERATOR_NOT_EQUALS.equals(getOperator()) && !this.rangeSearch) {
return builder.append(" <> ?").toString();
return builder.append(" <> ?)").toString();
} else if (BINARY_OPERATOR_FROM.equals(getOperator()) && !this.rangeSearch) {
return builder.append(" >= ?").toString();
return builder.append(" >= ?)").toString();
} else if (BINARY_OPERATOR_TO.equals(getOperator()) && !this.rangeSearch) {
return builder.append(" <= ?").toString();
return builder.append(" <= ?)").toString();
} else if (BINARY_OPERATOR_IN.equals(getOperator()) && this.rangeSearch) {
return builder.append(" between ? and ?").toString();
return builder.append(" between ? and ?)").toString();
}
throw new IllegalArgumentException(format("The given expression [%s %s '%s'] is not supported", key, operator.getSearchValue(), value));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ public String toSqlRepresentation() {
String[] keyParts = getKey().split("\\.");
var field = keyParts[0];
var indicator = keyParts[1];
var sqlRepresentation = "\"" + "i" + field + "\"" + "." + "\"" + indicator + "\"";
String fieldNumberToSearch = "\"field_no\" = '" + field+"'";
var sqlRepresentation = "("+fieldNumberToSearch + " and " + "\"" + indicator + "\"";
if (BINARY_OPERATOR_LEFT_ANCHORED_EQUALS.equals(getOperator())) {
return sqlRepresentation + " like ?";
return sqlRepresentation + " like ?)";
} else if (BINARY_OPERATOR_EQUALS.equals(getOperator())) {
return sqlRepresentation + " = ?";
return sqlRepresentation + " = ?)";
} else if (BINARY_OPERATOR_NOT_EQUALS.equals(getOperator())) {
return sqlRepresentation + " <> ?";
return sqlRepresentation + " <> ?)";
} else if (BINARY_OPERATOR_IS.equals(getOperator())) {
return PresenceBinaryOperand.getSqlRepresentationForIndicator(field, indicator, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public static boolean matches(String key) {

@Override
public String toSqlRepresentation() {
String iField = "\"" + "i" + field + "\"";
String prefix = "substring(" + iField + ".\"value\", " + startPosition + ", " + endPosition + ")";
String fieldNumberToSearch = "\"field_no\" = '" + field+"'";
String prefix = "("+fieldNumberToSearch +" and substring(\"value\", " + startPosition + ", " + endPosition + ")";
if (BINARY_OPERATOR_EQUALS.equals(getOperator())) {
return prefix + " = ?";
return prefix + " = ?)";
} else if (BINARY_OPERATOR_NOT_EQUALS.equals(getOperator())) {
return prefix + " <> ?";
return prefix + " <> ?)";
}
throw new IllegalArgumentException(format("Operator [%s] is not supported for the given Position operand", getOperator().getSearchValue()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,27 @@ private PresenceBinaryOperand() {
public static String getSqlRepresentationForMarcField(String field, String value) {
validateValue(value);
if (PRESENT.equals(value)) {
return "(id in (select marc_id from marc_indexers_" + field + "))";
return "(\"field_no\" = '"+field+"' and id in (select marc_id from marc_indexers))";
} else {
return "(id not in (select marc_id from marc_indexers_" + field + "))";
return "(\"field_no\" = '"+field+"' and id not in (select marc_id from marc_indexers))";
}
}

public static String getSqlRepresentationForSubField(String field, String subField, String value) {
validateValue(value);
if (PRESENT.equals(value)) {
return "(id in (select marc_id from marc_indexers_" + field + " where subfield_no = '" + subField + "')) ";
return "(\"field_no\" = '" + field + "' and id in (select marc_id from marc_indexers where subfield_no = '" + subField + "'))";
} else {
return "(id not in (select marc_id from marc_indexers_" + field + " where subfield_no = '" + subField + "')) ";
return "(\"field_no\" = '" + field + "' and id not in (select marc_id from marc_indexers where subfield_no = '" + subField + "'))";
}
}

public static String getSqlRepresentationForIndicator(String field, String indicator, String value) {
validateValue(value);
if (PRESENT.equals(value)) {
return "(id in (select marc_id from marc_indexers_" + field + " where " + indicator + " <> '#')) ";
return "(\"field_no\" = '"+field+"' and id in (select marc_id from marc_indexers where " + indicator + " <> '#'))";
} else {
return "(id in (select marc_id from marc_indexers_" + field + " where " + indicator + " = '#')) ";
return "(\"field_no\" = '"+field+"' and id in (select marc_id from marc_indexers where " + indicator + " = '#'))";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public static boolean matches(String key) {
public String toSqlRepresentation() {
String[] keyParts = getKey().split("\\.");
String field = keyParts[0];
String iField = "\"" + "i" + field + "\"";
String fieldNumberToSearch = "\"field_no\" = '" + field+"'";
String subField = keyParts[1];
StringBuilder stringBuilder = new StringBuilder()
.append("(").append(iField).append(".\"subfield_no\" = '").append(subField).append("'")
.append("(").append(fieldNumberToSearch).append(" and \"subfield_no\" = '").append(subField).append("'")
.append(" and ")
.append(iField).append(".\"value\" ");
.append("\"value\" ");
if (BINARY_OPERATOR_LEFT_ANCHORED_EQUALS.equals(getOperator())) {
return stringBuilder.append("like ?)").toString();
} else if (BINARY_OPERATOR_EQUALS.equals(getOperator())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ public static boolean matches(String key) {
public String toSqlRepresentation() {
StringBuilder stringBuilder = new StringBuilder();
String field = getKey().split("\\.")[0];
String prefix = stringBuilder.append("\"").append("i").append(field).append("\".\"value\"").toString();
String fieldNumberToSearch = "(\"field_no\" = '" + field+"'";
String prefix = stringBuilder.append(fieldNumberToSearch).append(" and ").append("\"value\"").toString();
if (BINARY_OPERATOR_LEFT_ANCHORED_EQUALS.equals(getOperator())) {
return prefix + " like ?";
return prefix + " like ?)";
} else if (BINARY_OPERATOR_EQUALS.equals(getOperator())) {
return prefix + " = ?";
return prefix + " = ?)";
} else if (BINARY_OPERATOR_NOT_EQUALS.equals(getOperator())) {
return stringBuilder.append(" <> ?").toString();
return stringBuilder.append(" <> ?)").toString();
} else if (BINARY_OPERATOR_IS.equals(getOperator())) {
return PresenceBinaryOperand.getSqlRepresentationForMarcField(field, value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
package org.folio.rest.impl;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.io.InputStream;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
import java.util.UUID;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
Expand All @@ -29,10 +12,6 @@
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.apache.http.HttpStatus;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.folio.TestUtil;
import org.folio.dao.PostgresClientFactory;
import org.folio.dao.util.ParsedRecordDaoUtil;
Expand All @@ -47,6 +26,27 @@
import org.folio.rest.jaxrs.model.Record.RecordType;
import org.folio.rest.jaxrs.model.Snapshot;
import org.folio.rest.jaxrs.model.SourceRecord;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
import java.util.UUID;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;

@RunWith(VertxUnitRunner.class)
public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
Expand Down Expand Up @@ -77,31 +77,31 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
}
}

private static ParsedRecord invalidParsedRecord = new ParsedRecord()
private static final ParsedRecord invalidParsedRecord = new ParsedRecord()
.withContent("Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.");
private static ErrorRecord errorRecord = new ErrorRecord()
private static final ErrorRecord errorRecord = new ErrorRecord()
.withDescription("Oops... something happened")
.withContent("Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.");

private static Snapshot snapshot_1 = new Snapshot()
private static final Snapshot snapshot_1 = new Snapshot()
.withJobExecutionId(UUID.randomUUID().toString())
.withStatus(Snapshot.Status.PARSING_IN_PROGRESS);
private static Snapshot snapshot_2 = new Snapshot()
private static final Snapshot snapshot_2 = new Snapshot()
.withJobExecutionId(UUID.randomUUID().toString())
.withStatus(Snapshot.Status.PARSING_IN_PROGRESS);
private static Snapshot snapshot_3 = new Snapshot()
private static final Snapshot snapshot_3 = new Snapshot()
.withJobExecutionId(UUID.randomUUID().toString())
.withStatus(Snapshot.Status.PARSING_IN_PROGRESS);

private static Record marc_bib_record_1 = new Record()
private static final Record marc_bib_record_1 = new Record()
.withId(FIRST_UUID)
.withSnapshotId(snapshot_1.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
.withRawRecord(rawRecord)
.withMatchedId(FIRST_UUID)
.withOrder(0)
.withState(Record.State.ACTUAL);
private static Record marc_bib_record_2 = new Record()
private static final Record marc_bib_record_2 = new Record()
.withId(SECOND_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
Expand All @@ -113,15 +113,15 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
.withExternalIdsHolder(new ExternalIdsHolder()
.withInstanceId(UUID.randomUUID().toString())
.withInstanceHrid("12345"));
private static Record marc_bib_record_3 = new Record()
private static final Record marc_bib_record_3 = new Record()
.withId(THIRD_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
.withRawRecord(rawRecord)
.withErrorRecord(errorRecord)
.withMatchedId(THIRD_UUID)
.withState(Record.State.ACTUAL);
private static Record marc_bib_record_4 = new Record()
private static final Record marc_bib_record_4 = new Record()
.withId(FOURTH_UUID)
.withSnapshotId(snapshot_1.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
Expand All @@ -133,7 +133,7 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
.withExternalIdsHolder(new ExternalIdsHolder()
.withInstanceId(UUID.randomUUID().toString())
.withInstanceHrid("12345"));
private static Record marc_bib_record_5 = new Record()
private static final Record marc_bib_record_5 = new Record()
.withId(FIFTH_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
Expand All @@ -142,7 +142,7 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
.withParsedRecord(invalidParsedRecord)
.withOrder(101)
.withState(Record.State.ACTUAL);
private static Record marc_bib_record_6 = new Record()
private static final Record marc_bib_record_6 = new Record()
.withId(SIXTH_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(Record.RecordType.MARC_BIB)
Expand All @@ -154,7 +154,7 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
.withExternalIdsHolder(new ExternalIdsHolder()
.withInstanceId(UUID.randomUUID().toString())
.withInstanceHrid("12345"));
private static Record marc_auth_record_1 = new Record()
private static final Record marc_auth_record_1 = new Record()
.withId(SEVENTH_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(RecordType.MARC_AUTHORITY)
Expand All @@ -166,7 +166,7 @@ public class SourceStorageStreamApiTest extends AbstractRestVerticleTest {
.withExternalIdsHolder(new ExternalIdsHolder()
.withAuthorityId(UUID.randomUUID().toString())
.withAuthorityHrid("12345"));
private static Record marc_holdings_record_1 = new Record()
private static final Record marc_holdings_record_1 = new Record()
.withId(EIGHTH_UUID)
.withSnapshotId(snapshot_2.getJobExecutionId())
.withRecordType(RecordType.MARC_HOLDING)
Expand Down Expand Up @@ -588,7 +588,7 @@ public void shouldReturnEmptyCollectionOnGetByRecordIdIfThereIsNoSuchRecord(Test
InputStream response = RestAssured.given()
.spec(spec)
.when()
.get(SOURCE_STORAGE_STREAM_SOURCE_RECORDS_PATH + "?recordId=" + UUID.randomUUID().toString() + "&limit=1&offset=0")
.get(SOURCE_STORAGE_STREAM_SOURCE_RECORDS_PATH + "?recordId=" + UUID.randomUUID() + "&limit=1&offset=0")
.then()
.statusCode(HttpStatus.SC_OK)
.extract().response().asInputStream();
Expand Down Expand Up @@ -1425,9 +1425,59 @@ public void shouldReturnIdOnSearchMarcRecordIdsWhenInstanceIdIsMissing(TestConte
async.complete();
}

@Test
public void shouldProcessSearchQueryIfSearchNeededWithinOneField(TestContext testContext) {
// given
final Async async = testContext.async();
postSnapshots(testContext, snapshot_2);
postRecords(testContext, marc_bib_record_2);
MarcRecordSearchRequest searchRequest = new MarcRecordSearchRequest();
searchRequest.setFieldsSearchExpression(
"050.a ^= 'M3' and 050.b ^= '.M896'");
// when
ExtractableResponse<Response> response = RestAssured.given()
.spec(spec)
.body(searchRequest)
.when()
.post("/source-storage/stream/marc-record-identifiers")
.then()
.extract();
JsonObject responseBody = new JsonObject(response.body().asString());
// then
assertEquals(HttpStatus.SC_OK, response.statusCode());
assertEquals(1, responseBody.getJsonArray("records").size());
assertEquals(1, responseBody.getInteger("totalCount").intValue());
async.complete();
}

@Test
public void shouldProcessSearchQueryIfSearchNeededWithinOneFieldWithDifferentOperands(TestContext testContext) {
// given
final Async async = testContext.async();
postSnapshots(testContext, snapshot_2);
postRecords(testContext, marc_bib_record_2);
MarcRecordSearchRequest searchRequest = new MarcRecordSearchRequest();
searchRequest.setFieldsSearchExpression(
"050.a ^= 'M3' and 050.b ^= '.M896'");
// when
ExtractableResponse<Response> response = RestAssured.given()
.spec(spec)
.body(searchRequest)
.when()
.post("/source-storage/stream/marc-record-identifiers")
.then()
.extract();
JsonObject responseBody = new JsonObject(response.body().asString());
// then
assertEquals(HttpStatus.SC_OK, response.statusCode());
assertEquals(1, responseBody.getJsonArray("records").size());
assertEquals(1, responseBody.getInteger("totalCount").intValue());
async.complete();
}

private Flowable<String> flowableInputStreamScanner(InputStream inputStream) {
return Flowable.create(subscriber -> {
try (Scanner scanner = new Scanner(inputStream, "UTF-8")) {
try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8)) {
while (scanner.hasNext()) {
subscriber.onNext(scanner.nextLine());
}
Expand Down
Loading

0 comments on commit 16d13d6

Please sign in to comment.