33import com .fasterxml .jackson .core .JsonProcessingException ;
44import com .fasterxml .jackson .databind .JsonNode ;
55import com .fasterxml .jackson .databind .ObjectMapper ;
6+ import com .fasterxml .jackson .databind .SerializationFeature ;
67import com .fasterxml .jackson .databind .node .ArrayNode ;
8+ import com .fasterxml .jackson .databind .util .ISO8601DateFormat ;
9+ import com .fasterxml .jackson .databind .util .StdDateFormat ;
10+ import com .fasterxml .jackson .datatype .jsr310 .JavaTimeModule ;
711import com .microsoft .semantickernel .data .filter .AnyTagEqualToFilterClause ;
812import com .microsoft .semantickernel .data .filter .EqualToFilterClause ;
913import com .microsoft .semantickernel .data .jdbc .*;
2125import com .microsoft .semantickernel .data .vectorstorage .options .VectorSearchOptions ;
2226import com .microsoft .semantickernel .exceptions .SKException ;
2327import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
28+ import oracle .jdbc .OraclePreparedStatement ;
2429import oracle .jdbc .OracleStatement ;
2530import oracle .jdbc .OracleTypes ;
31+ import oracle .sql .TIMESTAMPLTZ ;
32+ import oracle .sql .TIMESTAMPTZ ;
2633
2734import javax .annotation .Nonnull ;
2835import javax .annotation .concurrent .GuardedBy ;
2936import javax .sql .DataSource ;
37+ import java .nio .ByteBuffer ;
3038import java .sql .Connection ;
3139import java .sql .PreparedStatement ;
3240import java .sql .ResultSet ;
41+ import java .sql .SQLType ;
3342import java .sql .Statement ;
3443import java .sql .SQLException ;
44+ import java .sql .Timestamp ;
45+ import java .text .SimpleDateFormat ;
46+ import java .time .LocalDateTime ;
47+ import java .time .OffsetDateTime ;
48+ import java .time .format .DateTimeFormatter ;
49+ import java .time .format .DateTimeFormatterBuilder ;
3550import java .util .ArrayList ;
3651import java .util .Collections ;
3752import java .util .List ;
53+ import java .util .UUID ;
3854import java .util .logging .Logger ;
3955import java .util .stream .Collectors ;
4056import java .util .stream .StreamSupport ;
@@ -90,6 +106,7 @@ private OracleVectorStoreQueryProvider(
90106 OracleVectorStoreFieldHelper .getSupportedVectorTypes ());
91107 this .collectionsTable = collectionsTable ;
92108 this .objectMapper = objectMapper ;
109+ this .objectMapper .registerModule (new JavaTimeModule ());
93110 }
94111
95112 @ Override
@@ -120,15 +137,15 @@ public void createCollection(String collectionName,
120137 try (Statement statement = connection .createStatement ()) {
121138 // Create table
122139 System .out .println (createStorageTable );
123- statement .execute (createStorageTable );
140+ statement .addBatch (createStorageTable );
124141
125142 // Index filterable columns
126143 for (VectorStoreRecordDataField dataField : recordDefinition .getDataFields ()) {
127144 if (dataField .isFilterable ()) {
128145 String dataFieldIndex = OracleVectorStoreFieldHelper .createIndexForDataField (
129146 getCollectionTableName (collectionName ), dataField , supportedDataTypes );
130147 System .out .println (dataFieldIndex );
131- statement .execute (dataFieldIndex );
148+ statement .addBatch (dataFieldIndex );
132149 }
133150 }
134151
@@ -138,10 +155,10 @@ public void createCollection(String collectionName,
138155 vectorField , getCollectionTableName (collectionName ));
139156 if (createVectorIndex != null ) {
140157 System .out .println (createVectorIndex );
141- statement .execute (createVectorIndex );
158+ statement .addBatch (createVectorIndex );
142159 }
143160 }
144- // statement.executeBatch();
161+ statement .executeBatch ();
145162
146163 try (PreparedStatement insert = connection .prepareStatement (
147164 insertCollectionQuery )) {
@@ -220,6 +237,10 @@ public void upsertRecords(String collectionName, List<?> records, VectorStoreRec
220237
221238 private void setUpsertStatementValues (PreparedStatement statement , Object record ,
222239 List <VectorStoreRecordField > fields ) {
240+ objectMapper .disable (SerializationFeature .WRITE_DATES_AS_TIMESTAMPS );
241+ String datePattern = "yyyy-MM-dd HH:mm:ss.SSSZ" ;
242+ SimpleDateFormat df = new SimpleDateFormat (datePattern );
243+ objectMapper .setDateFormat (df );
223244 JsonNode jsonNode = objectMapper .valueToTree (record );
224245
225246 for (int i = 0 ; i < fields .size (); ++i ) {
@@ -230,27 +251,55 @@ private void setUpsertStatementValues(PreparedStatement statement, Object record
230251 if (field instanceof VectorStoreRecordVectorField ) {
231252 // Convert the vector field to a string
232253 if (!field .getFieldType ().equals (String .class )) {
233- double [] values = valueNode .isNull ()
254+ double [] values = ( valueNode == null || valueNode .isNull () )
234255 ? null
235256 : StreamSupport .stream ((
236257 (ArrayNode )valueNode ).spliterator (), false )
237258 .mapToDouble (d -> d .asDouble ()).toArray ();
238259 statement .setObject (i + 1 , values ,
239- OracleVectorStoreFieldHelper .getOracleTypeForField ((VectorStoreRecordVectorField )field ));
260+ OracleVectorStoreFieldHelper .getOracleTypeForVectorField ((VectorStoreRecordVectorField )field ));
240261 System .out .println ("Set values: " + values );
241262 continue ;
242263 }
243264 } else if (field instanceof VectorStoreRecordDataField ) {
244265 // Convert List field to a string
245266 if (field .getFieldType ().equals (List .class )) {
246267 statement .setObject (i + 1 , objectMapper .writeValueAsString (valueNode ));
247- System .out .println ("Set values: " + objectMapper .writeValueAsString (valueNode ));
268+ System .out .println (
269+ "Set values: " + objectMapper .writeValueAsString (valueNode ));
270+ continue ;
271+ }
272+ if (OracleVectorStoreFieldHelper .isUUID (field )) {
273+ if (valueNode == null || valueNode .isNull ()) {
274+ statement .setNull (i + 1 , OracleTypes .RAW );
275+ } else {
276+ UUID uuid = UUID .fromString (valueNode .textValue ());
277+ ByteBuffer bb = ByteBuffer .allocate (16 );
278+ bb .putLong (uuid .getMostSignificantBits ());
279+ bb .putLong (uuid .getLeastSignificantBits ());
280+ statement .setBytes (i + 1 , bb .array ());
281+ System .out .println ("Set values: " + objectMapper .convertValue (valueNode ,
282+ field .getFieldType ()));
283+ }
284+ continue ;
285+ }
286+ if (field .getFieldType ().equals (OffsetDateTime .class )) {
287+ if (valueNode == null || valueNode .isNull ()) {
288+ statement .setNull (i + 1 , OracleTypes .TIMESTAMPTZ );
289+ } else {
290+ OffsetDateTime offsetDateTime = OffsetDateTime .parse (
291+ valueNode .asText ());
292+ ((OraclePreparedStatement ) statement ).setTIMESTAMPTZ (i + 1 ,
293+ TIMESTAMPTZ .of (offsetDateTime ));
294+ System .out .println ("Set values: " + objectMapper .convertValue (valueNode ,
295+ field .getFieldType ()));
296+ }
248297 continue ;
249298 }
250299 }
251300
252301 statement .setObject (i + 1 ,
253- objectMapper .convertValue (valueNode , field .getFieldType ()));
302+ objectMapper .convertValue (valueNode ,field .getFieldType ()));
254303 System .out .println ("Set values: " + objectMapper .convertValue (valueNode , field .getFieldType ()));
255304 } catch (SQLException | JsonProcessingException e ) {
256305 throw new RuntimeException (e );
@@ -317,7 +366,7 @@ public <Record> VectorSearchResults<Record> search(String collectionName, List<F
317366 defineDataColumnType (columnIndex ++, oracleStatement , field .getFieldType ());
318367 else
319368 oracleStatement .defineColumnType (columnIndex ++,
320- OracleVectorStoreFieldHelper .getOracleTypeForField ((VectorStoreRecordVectorField ) field ),
369+ OracleVectorStoreFieldHelper .getOracleTypeForVectorField ((VectorStoreRecordVectorField ) field ),
321370 Integer .MAX_VALUE );
322371 }
323372 oracleStatement .setLobPrefetchSize (Integer .MAX_VALUE ); // Workaround for Oracle JDBC bug 37030121
@@ -380,6 +429,8 @@ private void defineDataColumnType(int columnIndex, OracleStatement statement, Cl
380429 statement .defineColumnType (columnIndex , OracleTypes .JSON , Integer .MAX_VALUE );
381430 break ;
382431 case OracleDataTypesMapping .UUID :
432+ statement .defineColumnType (columnIndex , OracleTypes .RAW );
433+ break ;
383434 case OracleDataTypesMapping .BYTE_ARRAY :
384435 statement .defineColumnType (columnIndex , OracleTypes .RAW );
385436 default :
0 commit comments