diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec1c73e..88bf8a04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). (~/.oci/regions-config.json) or environment variable (OCI_REGION_METADATA) ### Added +- Cloud only: added new OCI regions (RKT, SHJ, RUH, EBB, EBL) +- PrepareQueryException. This exception is thrown if a prepared query is + executed after (a) the index used by the query has been dropped and then + re-created with a different schema, or (b) one or more of the referenced + tables has been altered (via the alter table statement). - Cloud only: added new OCI regions (RKT, SHJ, RUH, EBB, EBL, JJT, DLN, DTZ) - Cloud only: refactored how the Region class is managed, allowing dynamic addition of regions not yet known to the system diff --git a/driver/src/main/java/oracle/nosql/driver/PrepareQueryException.java b/driver/src/main/java/oracle/nosql/driver/PrepareQueryException.java new file mode 100644 index 00000000..fc3ef3fd --- /dev/null +++ b/driver/src/main/java/oracle/nosql/driver/PrepareQueryException.java @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl/ + */ + +package oracle.nosql.driver; + +/** + * The query must be recompiled after DDL changes on the tables and/or + * indexes that are accessed by the query. + */ +public class PrepareQueryException extends NoSQLException { + + private static final long serialVersionUID = 1L; + + /** + * @hidden + * @param msg the exception message + */ + public PrepareQueryException(String msg) { + super(msg); + } +} diff --git a/driver/src/main/java/oracle/nosql/driver/http/Client.java b/driver/src/main/java/oracle/nosql/driver/http/Client.java index b42fb0d3..8e0f6f1b 100644 --- a/driver/src/main/java/oracle/nosql/driver/http/Client.java +++ b/driver/src/main/java/oracle/nosql/driver/http/Client.java @@ -633,7 +633,7 @@ public Result execute(Request kvRequest) { */ kvRequest.setTimeoutInternal(thisIterationTimeoutMs); serialVersionUsed = writeContent(buffer, kvRequest, - queryVersionUsed); + queryVersionUsed); kvRequest.setTimeoutInternal(timeoutMs); /* @@ -1628,14 +1628,17 @@ private synchronized boolean decrementSerialVersion(short versionUsed) { * false: already at lowest version number. */ private synchronized boolean decrementQueryVersion(short versionUsed) { + if (queryVersion != versionUsed) { return true; } - if (queryVersion == QueryDriver.QUERY_V4) { - queryVersion = QueryDriver.QUERY_V3; - return true; + + if (queryVersion == QueryDriver.QUERY_V3) { + return false; } - return false; + + --queryVersion; + return true; } /** diff --git a/driver/src/main/java/oracle/nosql/driver/ops/serde/BinaryProtocol.java b/driver/src/main/java/oracle/nosql/driver/ops/serde/BinaryProtocol.java index e27bced4..7c673d7b 100644 --- a/driver/src/main/java/oracle/nosql/driver/ops/serde/BinaryProtocol.java +++ b/driver/src/main/java/oracle/nosql/driver/ops/serde/BinaryProtocol.java @@ -39,6 +39,7 @@ import static oracle.nosql.driver.util.BinaryProtocol.OPERATION_NOT_SUPPORTED; import static oracle.nosql.driver.util.BinaryProtocol.PROVISIONED; import static oracle.nosql.driver.util.BinaryProtocol.READ_LIMIT_EXCEEDED; +import static oracle.nosql.driver.util.BinaryProtocol.RECOMPILE_QUERY; import static oracle.nosql.driver.util.BinaryProtocol.REQUEST_SIZE_LIMIT; import static oracle.nosql.driver.util.BinaryProtocol.REQUEST_SIZE_LIMIT_EXCEEDED; import static oracle.nosql.driver.util.BinaryProtocol.REQUEST_TIMEOUT; @@ -85,6 +86,7 @@ import oracle.nosql.driver.Nson; import oracle.nosql.driver.OperationNotSupportedException; import oracle.nosql.driver.OperationThrottlingException; +import oracle.nosql.driver.PrepareQueryException; import oracle.nosql.driver.ReadThrottlingException; import oracle.nosql.driver.RequestSizeLimitException; import oracle.nosql.driver.RequestTimeoutException; @@ -492,6 +494,8 @@ public static RuntimeException mapException(int code, String msg) { return new TableNotReadyException(msg); case ETAG_MISMATCH: return new IllegalArgumentException(msg); + case RECOMPILE_QUERY: + return new PrepareQueryException(msg); default: return new NoSQLException("Unknown error code " + code + ": " + msg); diff --git a/driver/src/main/java/oracle/nosql/driver/ops/serde/nson/NsonSerializerFactory.java b/driver/src/main/java/oracle/nosql/driver/ops/serde/nson/NsonSerializerFactory.java index d3e444a9..98c833ad 100644 --- a/driver/src/main/java/oracle/nosql/driver/ops/serde/nson/NsonSerializerFactory.java +++ b/driver/src/main/java/oracle/nosql/driver/ops/serde/nson/NsonSerializerFactory.java @@ -889,7 +889,7 @@ public void serialize(Request request, writeMapField(ns, QUERY_NAME, rq.getQueryName()); } if (rq.getVirtualScan() != null) { - writeVirtualScan(ns, rq.getVirtualScan()); + writeVirtualScan(ns, rq.getVirtualScan(), queryVersion); } } @@ -898,13 +898,15 @@ public void serialize(Request request, } private static void writeVirtualScan(NsonSerializer ns, - VirtualScan vs) + VirtualScan vs, + short queryVersion) throws IOException { + startMap(ns, VIRTUAL_SCAN); writeMapField(ns, VIRTUAL_SCAN_SID, vs.sid()); writeMapField(ns, VIRTUAL_SCAN_PID, vs.pid()); - if (vs.isFirstBatch()) { + if (queryVersion <= QueryDriver.QUERY_V4 && vs.isFirstBatch()) { writeMapField(ns, VIRTUAL_SCAN_PRIM_KEY, vs.primKey()); writeMapField(ns, VIRTUAL_SCAN_SEC_KEY, vs.secKey()); writeMapField(ns, VIRTUAL_SCAN_MOVE_AFTER, vs.moveAfterResumeKey()); @@ -915,6 +917,7 @@ private static void writeVirtualScan(NsonSerializer ns, writeMapField(ns, VIRTUAL_SCAN_JOIN_PATH_SEC_KEY, vs.joinPathSecKey()); writeMapField(ns, VIRTUAL_SCAN_JOIN_PATH_MATCHED, vs.joinPathMatched()); } + endMap(ns, VIRTUAL_SCAN); } diff --git a/driver/src/main/java/oracle/nosql/driver/query/QueryDriver.java b/driver/src/main/java/oracle/nosql/driver/query/QueryDriver.java index 809de7f0..3fb838f2 100644 --- a/driver/src/main/java/oracle/nosql/driver/query/QueryDriver.java +++ b/driver/src/main/java/oracle/nosql/driver/query/QueryDriver.java @@ -35,7 +35,10 @@ public class QueryDriver { /* added query name in QueryRequest */ public static short QUERY_V4 = 4; - public static short QUERY_VERSION = QUERY_V4; + /* Changed VirtualScan info exchanged between sdk and proxy */ + public static final short QUERY_V5 = 5; + + public static final short QUERY_VERSION = QUERY_V5; private static final int BATCH_SIZE = 100; diff --git a/driver/src/main/java/oracle/nosql/driver/query/ReceiveIter.java b/driver/src/main/java/oracle/nosql/driver/query/ReceiveIter.java index 7a4c9e4c..43305ab4 100644 --- a/driver/src/main/java/oracle/nosql/driver/query/ReceiveIter.java +++ b/driver/src/main/java/oracle/nosql/driver/query/ReceiveIter.java @@ -429,6 +429,8 @@ private void initPartitionSort( rcb.trace("ReceiveIter.initPartitionSort() : got result.\n" + "reached limit = " + result.reachedLimit() + " in phase 1 = " + result.isInPhase1()); + + origRequest.addQueryTraces(result.getQueryTraces()); } /* diff --git a/driver/src/main/java/oracle/nosql/driver/query/VirtualScan.java b/driver/src/main/java/oracle/nosql/driver/query/VirtualScan.java index 5c4fb9ba..ed1cb905 100644 --- a/driver/src/main/java/oracle/nosql/driver/query/VirtualScan.java +++ b/driver/src/main/java/oracle/nosql/driver/query/VirtualScan.java @@ -11,7 +11,9 @@ public class VirtualScan { final private int theSID; + final private int thePID; + final private byte[] thePrimResumeKey; final private byte[] theSecResumeKey; final private boolean theMoveAfterResumeKey; @@ -62,7 +64,7 @@ public byte[] secKey() { public byte[] primKey() { return thePrimResumeKey; } - + public boolean moveAfterResumeKey() { return theMoveAfterResumeKey; } @@ -99,51 +101,8 @@ public String toString() { sb.append("sid/pid = ").append(theSID).append("/").append(thePID); sb.append("\n"); - if (thePrimResumeKey != null) { - sb.append("thePrimResumeKey = "); - sb.append(PlanIter.printByteArray(thePrimResumeKey)); - sb.append("\n"); - } - - if (theSecResumeKey != null) { - sb.append("theSecResumeKey = "); - sb.append(PlanIter.printByteArray(theSecResumeKey)); - sb.append("\n"); - } - - sb.append("theMoveAfterResumeKey = ").append(theMoveAfterResumeKey); - sb.append("\n"); - - if (theDescResumeKey != null) { - sb.append("theDescResumeKey = "); - sb.append(PlanIter.printByteArray(theDescResumeKey)); - sb.append("\n"); - } - - if (theJoinPathTables != null) { - sb.append("theJoinPathTables = "); - sb.append(PlanIter.printIntArray(theJoinPathTables)); - sb.append("\n"); - } - - if (theJoinPathKey != null) { - sb.append("theJoinPathKey = "); - sb.append(PlanIter.printByteArray(theJoinPathKey)); - sb.append("\n"); - } - - if (theJoinPathSecKey != null) { - sb.append("theJoinPathSecKey = "); - sb.append(PlanIter.printByteArray(theJoinPathSecKey)); - sb.append("\n"); - } - - sb.append("theJoinPathMatched = ").append(theJoinPathMatched); - sb.append("\n"); - sb.append("theFirstBatch = ").append(theFirstBatch); sb.append("\n"); - return sb.toString(); } } diff --git a/driver/src/main/java/oracle/nosql/driver/util/BinaryProtocol.java b/driver/src/main/java/oracle/nosql/driver/util/BinaryProtocol.java index 63785cf0..f94afd1a 100644 --- a/driver/src/main/java/oracle/nosql/driver/util/BinaryProtocol.java +++ b/driver/src/main/java/oracle/nosql/driver/util/BinaryProtocol.java @@ -187,6 +187,8 @@ public static boolean isTenantOperation(OpCode op) { /* added in V4 */ public static final int TABLE_NOT_READY = 26; public static final int UNSUPPORTED_QUERY_VERSION = 27; + /* added in V5 */ + public static final int RECOMPILE_QUERY = 28; /* * Error codes for user throttling, range from 50 to 100(exclusive).