diff --git a/data/semantickernel-data-hsqldb/src/main/java/com/microsoft/semantickernel/data/jdbc/hsqldb/HSQLDBVectorStoreQueryProvider.java b/data/semantickernel-data-hsqldb/src/main/java/com/microsoft/semantickernel/data/jdbc/hsqldb/HSQLDBVectorStoreQueryProvider.java index 48431316..3de4a11c 100644 --- a/data/semantickernel-data-hsqldb/src/main/java/com/microsoft/semantickernel/data/jdbc/hsqldb/HSQLDBVectorStoreQueryProvider.java +++ b/data/semantickernel-data-hsqldb/src/main/java/com/microsoft/semantickernel/data/jdbc/hsqldb/HSQLDBVectorStoreQueryProvider.java @@ -28,7 +28,7 @@ * The HSQLDB vector store query provider. * Provides the necessary methods to interact with a HSQLDB vector store and vector store collections. */ -public class HSQLDBVectorStoreQueryProvider extends JDBCVectorStoreQueryProvider { +public class HSQLDBVectorStoreQueryProvider extends JDBCVectorStoreQueryProvider { private final ObjectMapper objectMapper; diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStore.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStore.java index ddc2f750..bfbf545c 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStore.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStore.java @@ -49,8 +49,19 @@ public JDBCVectorStore(@Nonnull DataSource dataSource, * * @return the builder */ - public static Builder builder() { - return new Builder(); + public static Builder builder() { + Builder builder = new Builder<>(); + return builder; + } + + /** + * Creates a builder for the vector store with the specified Key type. + * + * @param the key type + * @return the builder + */ + public static Builder getGenericBuilder() { + return new Builder(); } /** @@ -64,9 +75,9 @@ public static Builder builder() { public VectorStoreRecordCollection getCollection( @Nonnull String collectionName, @Nonnull VectorStoreRecordCollectionOptions options) { - if (!options.getKeyClass().equals(String.class)) { - throw new SKException("JDBC only supports string keys"); - } +// if (!options.getKeyClass().equals(String.class)) { +// throw new SKException("JDBC only supports string keys"); +// } if (options.getRecordClass() == null) { throw new SKException("Record class is required"); } @@ -81,11 +92,12 @@ public VectorStoreRecordCollection getCollection( options.getRecordDefinition()); } - JDBCVectorStoreRecordCollectionOptions jdbcOptions = (JDBCVectorStoreRecordCollectionOptions) options; - return (VectorStoreRecordCollection) new JDBCVectorStoreRecordCollection<>( + JDBCVectorStoreRecordCollectionOptions jdbcOptions = (JDBCVectorStoreRecordCollectionOptions) options; + return (VectorStoreRecordCollection) new JDBCVectorStoreGenericRecordCollection<>( dataSource, collectionName, - JDBCVectorStoreRecordCollectionOptions.builder() + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(jdbcOptions.getKeyClass()) .withCollectionsTableName(jdbcOptions.getCollectionsTableName()) .withPrefixForCollectionTables(jdbcOptions.getPrefixForCollectionTables()) .withQueryProvider(jdbcOptions.getQueryProvider() == null ? queryProvider @@ -105,13 +117,13 @@ public VectorStoreRecordCollection getCollection( * @param The record type. * @return The collection. */ - public VectorStoreRecordCollection getCollection( + public VectorStoreRecordCollection getCollection( @Nonnull String collectionName, @Nonnull Class recordClass, @Nullable VectorStoreRecordDefinition recordDefinition) { return getCollection( collectionName, - JDBCVectorStoreRecordCollectionOptions.builder() + JDBCVectorStoreRecordCollectionOptions.genericBuilder() .withRecordClass(recordClass) .withRecordDefinition(recordDefinition) .withQueryProvider(this.queryProvider) @@ -125,7 +137,7 @@ public VectorStoreRecordCollection getCollection( */ @Override public Mono> getCollectionNamesAsync() { - return Mono.fromCallable(queryProvider::getCollectionNames) + return Mono.>fromCallable(queryProvider::getCollectionNames) .subscribeOn(Schedulers.boundedElastic()); } @@ -141,10 +153,10 @@ public Mono prepareAsync() { /** * Builder for creating a {@link JDBCVectorStore}. */ - public static class Builder { + public static class Builder { private DataSource dataSource; - private JDBCVectorStoreOptions options; + private JDBCVectorStoreOptions options; /** * Sets the data source. @@ -153,7 +165,7 @@ public static class Builder { * @return the builder */ @SuppressFBWarnings("EI_EXPOSE_REP2") - public Builder withDataSource(DataSource dataSource) { + public Builder withDataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } @@ -164,7 +176,7 @@ public Builder withDataSource(DataSource dataSource) { * @param options the options * @return the builder */ - public Builder withOptions(JDBCVectorStoreOptions options) { + public Builder withOptions(JDBCVectorStoreOptions options) { this.options = options; return this; } diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreGenericRecordCollection.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreGenericRecordCollection.java new file mode 100644 index 00000000..2772aae2 --- /dev/null +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreGenericRecordCollection.java @@ -0,0 +1,364 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.semantickernel.data.jdbc; + +import com.microsoft.semantickernel.builders.SemanticKernelBuilder; +import com.microsoft.semantickernel.data.vectorsearch.VectorSearchResults; +import com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection; +import com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordMapper; +import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordDefinition; +import com.microsoft.semantickernel.data.vectorstorage.options.DeleteRecordOptions; +import com.microsoft.semantickernel.data.vectorstorage.options.GetRecordOptions; +import com.microsoft.semantickernel.data.vectorstorage.options.UpsertRecordOptions; +import com.microsoft.semantickernel.data.vectorstorage.options.VectorSearchOptions; +import com.microsoft.semantickernel.exceptions.SKException; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.lang.reflect.Field; +import java.sql.ResultSet; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.sql.DataSource; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +/** + * The JDBCVectorStoreRecordCollection class represents a collection of records in a JDBC vector + * store. It implements the SQLVectorStoreRecordCollection interface and provides methods for + * managing the collection, such as creating, deleting, and upserting records. + * + * @param the type of the records in the collection + */ +public class JDBCVectorStoreGenericRecordCollection + implements SQLVectorStoreRecordCollection { + + private final String collectionName; + protected final VectorStoreRecordDefinition recordDefinition; + protected final VectorStoreRecordMapper vectorStoreRecordMapper; + private final JDBCVectorStoreRecordCollectionOptions options; + protected final SQLVectorStoreQueryProvider queryProvider; + + /** + * Creates a new instance of the {@link JDBCVectorStoreRecordCollection}. + * + * @param dataSource the data source + * @param collectionName the name of the collection + * @param options the options + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource is not exposed + public JDBCVectorStoreGenericRecordCollection( + @Nonnull DataSource dataSource, + @Nonnull String collectionName, + @Nonnull JDBCVectorStoreRecordCollectionOptions options) { + this.collectionName = collectionName; + this.options = options; + + // If record definition is not provided, create one from the record class + recordDefinition = options.getRecordDefinition() == null + ? VectorStoreRecordDefinition.fromRecordClass(options.getRecordClass()) + : options.getRecordDefinition(); + + // If the query provider is not provided, set a default one + if (options.getQueryProvider() == null) { + this.queryProvider = JDBCVectorStoreQueryProvider.builder() + .withDataSource(dataSource) + .build(); + } else { + this.queryProvider = options.getQueryProvider(); + } + + // If mapper is not provided, set a default one + if (options.getVectorStoreRecordMapper() == null) { + vectorStoreRecordMapper = options.getQueryProvider() + .getVectorStoreRecordMapper(options.getRecordClass(), + recordDefinition); + } else { + vectorStoreRecordMapper = options.getVectorStoreRecordMapper(); + } + + // Check if the types are supported + queryProvider.validateSupportedTypes(recordDefinition); + } + + /** + * Gets the name of the collection. + * + * @return The name of the collection. + */ + @Override + public String getCollectionName() { + return collectionName; + } + + /** + * Checks if the collection exists in the store. + * + * @return A Mono emitting a boolean indicating if the collection exists. + * @throws SKException if the operation fails + */ + @Override + public Mono collectionExistsAsync() { + return Mono.fromCallable( + () -> queryProvider.collectionExists(this.collectionName)) + .subscribeOn(Schedulers.boundedElastic()); + } + + /** + * Creates the collection in the store. + * + * @return A Mono representing the completion of the creation operation. + * @throws SKException if the operation fails + */ + @Override + public Mono> createCollectionAsync() { + return Mono.fromRunnable( + () -> queryProvider.createCollection(this.collectionName, recordDefinition)) + .subscribeOn(Schedulers.boundedElastic()) + .then(Mono.just(this)); + } + + /** + * Creates the collection in the store if it does not exist. + * + * @return A Mono representing the completion of the creation operation. + * @throws SKException if the operation fails + */ + @Override + public Mono> createCollectionIfNotExistsAsync() { + return collectionExistsAsync().map( + exists -> { + if (!exists) { + return createCollectionAsync(); + } + return Mono.empty(); + }) + .flatMap(mono -> mono) + .then(Mono.just(this)); + } + + /** + * Deletes the collection from the store. + * + * @return A Mono representing the completion of the deletion operation. + * @throws SKException if the operation fails + */ + @Override + public Mono deleteCollectionAsync() { + return Mono.fromRunnable( + () -> { + queryProvider.deleteCollection(this.collectionName); + }).subscribeOn(Schedulers.boundedElastic()).then(); + } + + /** + * Gets a record from the store. + * + * @param key The key of the record to get. + * @param options The options for getting the record. + * @return A Mono emitting the record. + * @throws SKException if the operation fails + */ + @Override + public Mono getAsync(Key key, GetRecordOptions options) { + Objects.requireNonNull(key, "key is required"); + + return this.getBatchAsync(Collections.singletonList(key), options) + .mapNotNull(records -> { + if (records.isEmpty()) { + return null; + } + return records.get(0); + }); + } + + /** + * Gets a batch of records from the store. + * + * @param keys The keys of the records to get. + * @param options The options for getting the records. + * @return A Mono emitting a collection of records. + * @throws SKException if the operation fails + */ + @Override + public Mono> getBatchAsync(@Nonnull List keys, GetRecordOptions options) { + Objects.requireNonNull(keys, "keys is required"); + + return Mono.fromCallable( + () -> queryProvider.getRecords(this.collectionName, keys, recordDefinition, + vectorStoreRecordMapper, options)) + .subscribeOn(Schedulers.boundedElastic()); + } + + protected Key getKeyFromRecord(Record data) { + try { + Field keyField = data.getClass() + .getDeclaredField(recordDefinition.getKeyField().getName()); + keyField.setAccessible(true); + return (Key)keyField.get(data); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new SKException("Failed to get key from record", e); + } + } + + /** + * Inserts or updates a record in the store. + * + * @param data The record to upsert. + * @param options The options for upserting the record. + * @return A Mono emitting the key of the upserted record. + * @throws SKException if the operation fails + */ + @Override + public Mono upsertAsync(Record data, UpsertRecordOptions options) { + Objects.requireNonNull(data, "data is required"); + + return this.upsertBatchAsync(Collections.singletonList(data), options) + .mapNotNull(keys -> { + if (keys.isEmpty()) { + return null; + } + return keys.get(0); + }); + } + + /** + * Inserts or updates a batch of records in the store. + * + * @param data The records to upsert. + * @param options The options for upserting the records. + * @return A Mono emitting a collection of keys of the upserted records. + * @throws SKException if the operation fails + */ + @Override + public Mono> upsertBatchAsync(List data, UpsertRecordOptions options) { + Objects.requireNonNull(data, "data is required"); + + return Mono.fromCallable( + () -> { + queryProvider.upsertRecords(this.collectionName, data, recordDefinition, options); + return data.stream().map(this::getKeyFromRecord).collect(Collectors.toList()); + }) + .subscribeOn(Schedulers.boundedElastic()); + } + + /** + * Deletes a record from the store. + * + * @param key The key of the record to delete. + * @param options The options for deleting the record. + * @return A Mono representing the completion of the deletion operation. + * @throws SKException if the operation fails + */ + @Override + public Mono deleteAsync(Key key, DeleteRecordOptions options) { + return this.deleteBatchAsync(Collections.singletonList(key), options); + } + + /** + * Deletes a batch of records from the store. + * + * @param keys The keys of the records to delete. + * @param options The options for deleting the records. + * @return A Mono representing the completion of the deletion operation. + * @throws SKException if the operation fails + */ + @Override + public Mono deleteBatchAsync(List keys, DeleteRecordOptions options) { + return Mono.fromRunnable( + () -> { + queryProvider.deleteRecords(this.collectionName, keys, recordDefinition, options); + }).subscribeOn(Schedulers.boundedElastic()).then(); + } + + /** + * Prepares the collection for use. + * + * @return A Mono representing the completion of the preparation operation. + * @throws SKException if the operation fails + */ + @Override + public Mono prepareAsync() { + return Mono.fromRunnable(queryProvider::prepareVectorStore) + .subscribeOn(Schedulers.boundedElastic()).then(); + } + + /** + * Vectorized search. This method searches for records that are similar to the given vector. + * + * @param vector The vector to search with. + * @param vectorSearchOptions The options to use for the search. + * @return A list of search results. + */ + @Override + public Mono> searchAsync(List vector, + VectorSearchOptions vectorSearchOptions) { + return Mono.fromCallable( + () -> queryProvider.search(this.collectionName, vector, vectorSearchOptions, + recordDefinition, + vectorStoreRecordMapper)) + .subscribeOn(Schedulers.boundedElastic()); + } + + /** + * Builder for a JDBCVectorStoreRecordCollection. + * + * @param the type of the records in the collection + */ + public static class Builder + implements SemanticKernelBuilder> { + + private DataSource dataSource; + private String collectionName; + private JDBCVectorStoreRecordCollectionOptions options; + + /** + * Sets the data source. + * + * @param dataSource the data source + * @return the builder + */ + @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource is not exposed + public Builder withDataSource(DataSource dataSource) { + this.dataSource = dataSource; + return this; + } + + /** + * Sets the collection name. + * + * @param collectionName the collection name + * @return the builder + */ + public Builder withCollectionName(String collectionName) { + this.collectionName = collectionName; + return this; + } + + /** + * Sets the options. + * + * @param options the options + * @return the builder + */ + public Builder withOptions(JDBCVectorStoreRecordCollectionOptions options) { + this.options = options; + return this; + } + + @Override + public JDBCVectorStoreGenericRecordCollection build() { + if (dataSource == null) { + throw new SKException("dataSource is required"); + } + if (collectionName == null) { + throw new SKException("collectionName is required"); + } + if (options == null) { + throw new SKException("options is required"); + } + + return new JDBCVectorStoreGenericRecordCollection<>(dataSource, collectionName, options); + } + } +} diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreOptions.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreOptions.java index 729ebbbd..199065e8 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreOptions.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreOptions.java @@ -8,11 +8,11 @@ /** * Options for the JDBC vector store. */ -public class JDBCVectorStoreOptions { +public class JDBCVectorStoreOptions { @Nullable private final JDBCVectorStoreRecordCollectionFactory vectorStoreRecordCollectionFactory; @Nullable - private final SQLVectorStoreQueryProvider queryProvider; + private final SQLVectorStoreQueryProvider queryProvider; /** * Creates a new instance of the JDBC vector store options. @@ -23,7 +23,7 @@ public class JDBCVectorStoreOptions { */ @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource in queryProvider is not exposed public JDBCVectorStoreOptions( - @Nullable SQLVectorStoreQueryProvider queryProvider, + @Nullable SQLVectorStoreQueryProvider queryProvider, @Nullable JDBCVectorStoreRecordCollectionFactory vectorStoreRecordCollectionFactory) { this.queryProvider = queryProvider; this.vectorStoreRecordCollectionFactory = vectorStoreRecordCollectionFactory; @@ -43,7 +43,7 @@ public JDBCVectorStoreOptions() { */ @Nullable @SuppressFBWarnings("EI_EXPOSE_REP") // DataSource in queryProvider is not exposed - public SQLVectorStoreQueryProvider getQueryProvider() { + public SQLVectorStoreQueryProvider getQueryProvider() { return queryProvider; } @@ -69,9 +69,9 @@ public JDBCVectorStoreRecordCollectionFactory getVectorStoreRecordCollectionFact /** * Builder for JDBC vector store options. */ - public static class Builder { + public static class Builder { @Nullable - private SQLVectorStoreQueryProvider queryProvider; + private SQLVectorStoreQueryProvider queryProvider; @Nullable private JDBCVectorStoreRecordCollectionFactory vectorStoreRecordCollectionFactory; @@ -82,7 +82,7 @@ public static class Builder { * @return The updated builder instance. */ @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource in queryProvider is not exposed - public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvider) { + public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvider) { this.queryProvider = queryProvider; return this; } @@ -93,7 +93,7 @@ public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvider) { * @param vectorStoreRecordCollectionFactory The vector store record collection factory. * @return The updated builder instance. */ - public Builder withVectorStoreRecordCollectionFactory( + public Builder withVectorStoreRecordCollectionFactory( JDBCVectorStoreRecordCollectionFactory vectorStoreRecordCollectionFactory) { this.vectorStoreRecordCollectionFactory = vectorStoreRecordCollectionFactory; return this; @@ -104,8 +104,8 @@ public Builder withVectorStoreRecordCollectionFactory( * * @return The JDBC vector store options. */ - public JDBCVectorStoreOptions build() { - return new JDBCVectorStoreOptions(queryProvider, vectorStoreRecordCollectionFactory); + public JDBCVectorStoreOptions build() { + return new JDBCVectorStoreOptions(queryProvider, vectorStoreRecordCollectionFactory); } } } diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreQueryProvider.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreQueryProvider.java index 2fcc2d5b..ad751e4e 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreQueryProvider.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreQueryProvider.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -42,8 +43,8 @@ /** * A JDBC vector store query provider. */ -public class JDBCVectorStoreQueryProvider - implements SQLVectorStoreQueryProvider, +public class JDBCVectorStoreQueryProvider + implements SQLVectorStoreQueryProvider, SQLVectorStoreFilterQueryProvider { private static final Logger LOGGER = LoggerFactory @@ -122,8 +123,8 @@ public JDBCVectorStoreQueryProvider( * * @return the builder */ - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new Builder(); } /** @@ -407,7 +408,7 @@ public List getCollectionNames() { * @throws SKException if an error occurs while getting the records */ @Override - public List getRecords(String collectionName, List keys, + public List getRecords(String collectionName, List keys, VectorStoreRecordDefinition recordDefinition, VectorStoreRecordMapper mapper, GetRecordOptions options) { @@ -438,7 +439,11 @@ public List getRecords(String collectionName, List keys try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(query)) { for (int i = 0; i < keys.size(); ++i) { - statement.setObject(i + 1, keys.get(i)); + if (recordDefinition.getKeyField().getFieldType().equals(UUID.class)) { + statement.setObject(i + 1, keys.get(i).toString()); + } else { + statement.setObject(i + 1, keys.get(i)); + } } List records = new ArrayList<>(); @@ -471,7 +476,7 @@ public void upsertRecords(String collectionName, List records, * @throws SKException if an error occurs while deleting the records */ @Override - public void deleteRecords(String collectionName, List keys, + public void deleteRecords(String collectionName, List keys, VectorStoreRecordDefinition recordDefinition, DeleteRecordOptions options) { String query = formatQuery("DELETE FROM %s WHERE %s IN (%s)", getCollectionTableName(collectionName), @@ -481,7 +486,11 @@ public void deleteRecords(String collectionName, List keys, try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(query)) { for (int i = 0; i < keys.size(); ++i) { - statement.setObject(i + 1, keys.get(i)); + if (recordDefinition.getKeyField().getFieldType().equals(UUID.class)) { + statement.setObject(i + 1, keys.get(i).toString()); + } else { + statement.setObject(i + 1, keys.get(i)); + } } statement.execute(); @@ -714,8 +723,8 @@ public VectorStoreRecordMapper getVectorStoreRecordM /** * The builder for {@link JDBCVectorStoreQueryProvider}. */ - public static class Builder - implements SQLVectorStoreQueryProvider.Builder { + public static class Builder + implements SQLVectorStoreQueryProvider.Builder { private DataSource dataSource; private String collectionsTable = DEFAULT_COLLECTIONS_TABLE; @@ -728,7 +737,7 @@ public static class Builder * @return the builder */ @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource is not exposed - public Builder withDataSource(DataSource dataSource) { + public Builder withDataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } @@ -739,7 +748,7 @@ public Builder withDataSource(DataSource dataSource) { * @param collectionsTable the collections table name * @return the builder */ - public Builder withCollectionsTable(String collectionsTable) { + public Builder withCollectionsTable(String collectionsTable) { this.collectionsTable = validateSQLidentifier(collectionsTable); return this; } @@ -750,18 +759,18 @@ public Builder withCollectionsTable(String collectionsTable) { * @param prefixForCollectionTables the prefix for collection tables * @return the builder */ - public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { + public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { this.prefixForCollectionTables = validateSQLidentifier(prefixForCollectionTables); return this; } @Override - public JDBCVectorStoreQueryProvider build() { + public JDBCVectorStoreQueryProvider build() { if (dataSource == null) { throw new SKException("DataSource is required"); } - return new JDBCVectorStoreQueryProvider(dataSource, collectionsTable, + return new JDBCVectorStoreQueryProvider(dataSource, collectionsTable, prefixForCollectionTables); } } diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollection.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollection.java index 1d6b3e09..5cf12a9c 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollection.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollection.java @@ -2,26 +2,10 @@ package com.microsoft.semantickernel.data.jdbc; import com.microsoft.semantickernel.builders.SemanticKernelBuilder; -import com.microsoft.semantickernel.data.vectorsearch.VectorSearchResults; -import com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection; -import com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordMapper; -import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordDefinition; -import com.microsoft.semantickernel.data.vectorstorage.options.DeleteRecordOptions; -import com.microsoft.semantickernel.data.vectorstorage.options.GetRecordOptions; -import com.microsoft.semantickernel.data.vectorstorage.options.UpsertRecordOptions; -import com.microsoft.semantickernel.data.vectorstorage.options.VectorSearchOptions; import com.microsoft.semantickernel.exceptions.SKException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; -import java.sql.ResultSet; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.sql.DataSource; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; /** * The JDBCVectorStoreRecordCollection class represents a collection of records in a JDBC vector @@ -31,13 +15,7 @@ * @param the type of the records in the collection */ public class JDBCVectorStoreRecordCollection - implements SQLVectorStoreRecordCollection { - - private final String collectionName; - protected final VectorStoreRecordDefinition recordDefinition; - protected final VectorStoreRecordMapper vectorStoreRecordMapper; - private final JDBCVectorStoreRecordCollectionOptions options; - protected final SQLVectorStoreQueryProvider queryProvider; + extends JDBCVectorStoreGenericRecordCollection { /** * Creates a new instance of the {@link JDBCVectorStoreRecordCollection}. @@ -50,254 +28,8 @@ public class JDBCVectorStoreRecordCollection public JDBCVectorStoreRecordCollection( @Nonnull DataSource dataSource, @Nonnull String collectionName, - @Nonnull JDBCVectorStoreRecordCollectionOptions options) { - this.collectionName = collectionName; - this.options = options; - - // If record definition is not provided, create one from the record class - recordDefinition = options.getRecordDefinition() == null - ? VectorStoreRecordDefinition.fromRecordClass(options.getRecordClass()) - : options.getRecordDefinition(); - - // If the query provider is not provided, set a default one - if (options.getQueryProvider() == null) { - this.queryProvider = JDBCVectorStoreQueryProvider.builder() - .withDataSource(dataSource) - .build(); - } else { - this.queryProvider = options.getQueryProvider(); - } - - // If mapper is not provided, set a default one - if (options.getVectorStoreRecordMapper() == null) { - vectorStoreRecordMapper = options.getQueryProvider() - .getVectorStoreRecordMapper(options.getRecordClass(), - recordDefinition); - } else { - vectorStoreRecordMapper = options.getVectorStoreRecordMapper(); - } - - // Check if the types are supported - queryProvider.validateSupportedTypes(recordDefinition); - } - - /** - * Gets the name of the collection. - * - * @return The name of the collection. - */ - @Override - public String getCollectionName() { - return collectionName; - } - - /** - * Checks if the collection exists in the store. - * - * @return A Mono emitting a boolean indicating if the collection exists. - * @throws SKException if the operation fails - */ - @Override - public Mono collectionExistsAsync() { - return Mono.fromCallable( - () -> queryProvider.collectionExists(this.collectionName)) - .subscribeOn(Schedulers.boundedElastic()); - } - - /** - * Creates the collection in the store. - * - * @return A Mono representing the completion of the creation operation. - * @throws SKException if the operation fails - */ - @Override - public Mono> createCollectionAsync() { - return Mono.fromRunnable( - () -> queryProvider.createCollection(this.collectionName, recordDefinition)) - .subscribeOn(Schedulers.boundedElastic()) - .then(Mono.just(this)); - } - - /** - * Creates the collection in the store if it does not exist. - * - * @return A Mono representing the completion of the creation operation. - * @throws SKException if the operation fails - */ - @Override - public Mono> createCollectionIfNotExistsAsync() { - return collectionExistsAsync().map( - exists -> { - if (!exists) { - return createCollectionAsync(); - } - return Mono.empty(); - }) - .flatMap(mono -> mono) - .then(Mono.just(this)); - } - - /** - * Deletes the collection from the store. - * - * @return A Mono representing the completion of the deletion operation. - * @throws SKException if the operation fails - */ - @Override - public Mono deleteCollectionAsync() { - return Mono.fromRunnable( - () -> { - queryProvider.deleteCollection(this.collectionName); - }).subscribeOn(Schedulers.boundedElastic()).then(); - } - - /** - * Gets a record from the store. - * - * @param key The key of the record to get. - * @param options The options for getting the record. - * @return A Mono emitting the record. - * @throws SKException if the operation fails - */ - @Override - public Mono getAsync(String key, GetRecordOptions options) { - Objects.requireNonNull(key, "key is required"); - - return this.getBatchAsync(Collections.singletonList(key), options) - .mapNotNull(records -> { - if (records.isEmpty()) { - return null; - } - return records.get(0); - }); - } - - /** - * Gets a batch of records from the store. - * - * @param keys The keys of the records to get. - * @param options The options for getting the records. - * @return A Mono emitting a collection of records. - * @throws SKException if the operation fails - */ - @Override - public Mono> getBatchAsync(@Nonnull List keys, GetRecordOptions options) { - Objects.requireNonNull(keys, "keys is required"); - - return Mono.fromCallable( - () -> queryProvider.getRecords(this.collectionName, keys, recordDefinition, - vectorStoreRecordMapper, options)) - .subscribeOn(Schedulers.boundedElastic()); - } - - protected String getKeyFromRecord(Record data) { - try { - Field keyField = data.getClass() - .getDeclaredField(recordDefinition.getKeyField().getName()); - keyField.setAccessible(true); - return keyField.get(data).toString(); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new SKException("Failed to get key from record", e); - } - } - - /** - * Inserts or updates a record in the store. - * - * @param data The record to upsert. - * @param options The options for upserting the record. - * @return A Mono emitting the key of the upserted record. - * @throws SKException if the operation fails - */ - @Override - public Mono upsertAsync(Record data, UpsertRecordOptions options) { - Objects.requireNonNull(data, "data is required"); - - return this.upsertBatchAsync(Collections.singletonList(data), options) - .mapNotNull(keys -> { - if (keys.isEmpty()) { - return null; - } - return keys.get(0); - }); - } - - /** - * Inserts or updates a batch of records in the store. - * - * @param data The records to upsert. - * @param options The options for upserting the records. - * @return A Mono emitting a collection of keys of the upserted records. - * @throws SKException if the operation fails - */ - @Override - public Mono> upsertBatchAsync(List data, UpsertRecordOptions options) { - Objects.requireNonNull(data, "data is required"); - - return Mono.fromCallable( - () -> { - queryProvider.upsertRecords(this.collectionName, data, recordDefinition, options); - return data.stream().map(this::getKeyFromRecord).collect(Collectors.toList()); - }) - .subscribeOn(Schedulers.boundedElastic()); - } - - /** - * Deletes a record from the store. - * - * @param key The key of the record to delete. - * @param options The options for deleting the record. - * @return A Mono representing the completion of the deletion operation. - * @throws SKException if the operation fails - */ - @Override - public Mono deleteAsync(String key, DeleteRecordOptions options) { - return this.deleteBatchAsync(Collections.singletonList(key), options); - } - - /** - * Deletes a batch of records from the store. - * - * @param keys The keys of the records to delete. - * @param options The options for deleting the records. - * @return A Mono representing the completion of the deletion operation. - * @throws SKException if the operation fails - */ - @Override - public Mono deleteBatchAsync(List keys, DeleteRecordOptions options) { - return Mono.fromRunnable( - () -> { - queryProvider.deleteRecords(this.collectionName, keys, recordDefinition, options); - }).subscribeOn(Schedulers.boundedElastic()).then(); - } - - /** - * Prepares the collection for use. - * - * @return A Mono representing the completion of the preparation operation. - * @throws SKException if the operation fails - */ - @Override - public Mono prepareAsync() { - return Mono.fromRunnable(queryProvider::prepareVectorStore) - .subscribeOn(Schedulers.boundedElastic()).then(); - } - - /** - * Vectorized search. This method searches for records that are similar to the given vector. - * - * @param vector The vector to search with. - * @param vectorSearchOptions The options to use for the search. - * @return A list of search results. - */ - @Override - public Mono> searchAsync(List vector, - VectorSearchOptions vectorSearchOptions) { - return Mono.fromCallable( - () -> queryProvider.search(this.collectionName, vector, vectorSearchOptions, - recordDefinition, - vectorStoreRecordMapper)) - .subscribeOn(Schedulers.boundedElastic()); + @Nonnull JDBCVectorStoreRecordCollectionOptions options) { + super(dataSource, collectionName, options); } /** @@ -310,7 +42,7 @@ public static class Builder private DataSource dataSource; private String collectionName; - private JDBCVectorStoreRecordCollectionOptions options; + private JDBCVectorStoreRecordCollectionOptions options; /** * Sets the data source. @@ -341,7 +73,7 @@ public Builder withCollectionName(String collectionName) { * @param options the options * @return the builder */ - public Builder withOptions(JDBCVectorStoreRecordCollectionOptions options) { + public Builder withOptions(JDBCVectorStoreRecordCollectionOptions options) { this.options = options; return this; } diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionFactory.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionFactory.java index 796f0720..0369c143 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionFactory.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionFactory.java @@ -20,7 +20,7 @@ public interface JDBCVectorStoreRecordCollectionFactory { * @param The type of record in the collection. * @return The new JDBC vector store record collection. */ - JDBCVectorStoreRecordCollection createVectorStoreRecordCollection( + JDBCVectorStoreGenericRecordCollection createVectorStoreRecordCollection( DataSource dataSource, String collectionName, Class recordClass, diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionOptions.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionOptions.java index 596d0f29..8a21e5d3 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionOptions.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/JDBCVectorStoreRecordCollectionOptions.java @@ -16,22 +16,25 @@ * Options for a JDBC vector store record collection. * @param the record type */ -public class JDBCVectorStoreRecordCollectionOptions - implements VectorStoreRecordCollectionOptions { - private final Class recordClass; - private final VectorStoreRecordMapper vectorStoreRecordMapper; - private final VectorStoreRecordDefinition recordDefinition; - private final SQLVectorStoreQueryProvider queryProvider; - private final String collectionsTableName; - private final String prefixForCollectionTables; - - private JDBCVectorStoreRecordCollectionOptions( +public class JDBCVectorStoreRecordCollectionOptions + implements VectorStoreRecordCollectionOptions { + protected final Class keyClass; + protected final Class recordClass; + protected final VectorStoreRecordMapper vectorStoreRecordMapper; + protected final VectorStoreRecordDefinition recordDefinition; + protected final SQLVectorStoreQueryProvider queryProvider; + protected final String collectionsTableName; + protected final String prefixForCollectionTables; + + protected JDBCVectorStoreRecordCollectionOptions( + Class keyClass, Class recordClass, VectorStoreRecordDefinition recordDefinition, VectorStoreRecordMapper vectorStoreRecordMapper, - SQLVectorStoreQueryProvider queryProvider, + SQLVectorStoreQueryProvider queryProvider, String collectionsTableName, String prefixForCollectionTables) { + this.keyClass = keyClass; this.recordClass = recordClass; this.recordDefinition = recordDefinition; this.vectorStoreRecordMapper = vectorStoreRecordMapper; @@ -40,23 +43,14 @@ private JDBCVectorStoreRecordCollectionOptions( this.prefixForCollectionTables = prefixForCollectionTables; } - /** - * Creates a new builder. - * @param the record type - * @return the builder - */ - public static Builder builder() { - return new Builder<>(); - } - /** * Gets the key class. * * @return the key class */ @Override - public Class getKeyClass() { - return String.class; + public Class getKeyClass() { + return keyClass; } /** @@ -104,38 +98,60 @@ public String getPrefixForCollectionTables() { * @return the query provider */ @SuppressFBWarnings("EI_EXPOSE_REP") // DataSource in queryProvider is not exposed - public SQLVectorStoreQueryProvider getQueryProvider() { + public SQLVectorStoreQueryProvider getQueryProvider() { return queryProvider; } + public static Builder builder() { + Builder builder = new Builder<>(); + builder.keyClass = String.class; + return builder; + } + + public static Builder genericBuilder() { + return new Builder<>(); + } + /** * Builder for JDBC vector store record collection options. + * @param the key type * @param the record type */ - public static class Builder { - private Class recordClass; - private VectorStoreRecordDefinition recordDefinition; - private VectorStoreRecordMapper vectorStoreRecordMapper; - private SQLVectorStoreQueryProvider queryProvider; - private String collectionsTableName = DEFAULT_COLLECTIONS_TABLE; - private String prefixForCollectionTables = DEFAULT_PREFIX_FOR_COLLECTION_TABLES; + public static class Builder { + protected Class recordClass; + protected Class keyClass; + protected VectorStoreRecordDefinition recordDefinition; + protected VectorStoreRecordMapper vectorStoreRecordMapper; + protected SQLVectorStoreQueryProvider queryProvider; + protected String collectionsTableName = DEFAULT_COLLECTIONS_TABLE; + protected String prefixForCollectionTables = DEFAULT_PREFIX_FOR_COLLECTION_TABLES; /** * Sets the record class. * @param recordClass the record class * @return the builder */ - public Builder withRecordClass(Class recordClass) { + public Builder withRecordClass(Class recordClass) { this.recordClass = recordClass; return this; } + /** + * Sets the key class. + * @param keyClass the key class + * @return the builder + */ + public Builder withKeyClass(Class keyClass) { + this.keyClass = keyClass; + return this; + } + /** * Sets the record definition. * @param recordDefinition the record definition * @return the builder */ - public Builder withRecordDefinition(VectorStoreRecordDefinition recordDefinition) { + public Builder withRecordDefinition(VectorStoreRecordDefinition recordDefinition) { this.recordDefinition = recordDefinition; return this; } @@ -145,7 +161,7 @@ public Builder withRecordDefinition(VectorStoreRecordDefinition recordDe * @param vectorStoreRecordMapper the vector store record mapper * @return the builder */ - public Builder withVectorStoreRecordMapper( + public Builder withVectorStoreRecordMapper( VectorStoreRecordMapper vectorStoreRecordMapper) { this.vectorStoreRecordMapper = vectorStoreRecordMapper; return this; @@ -157,7 +173,7 @@ public Builder withVectorStoreRecordMapper( * @return the builder */ @SuppressFBWarnings("EI_EXPOSE_REP2") // DataSource in queryProvider is not exposed - public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvider) { + public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvider) { this.queryProvider = queryProvider; return this; } @@ -167,7 +183,7 @@ public Builder withQueryProvider(SQLVectorStoreQueryProvider queryProvid * @param collectionsTableName the collections table name * @return the builder */ - public Builder withCollectionsTableName(String collectionsTableName) { + public Builder withCollectionsTableName(String collectionsTableName) { this.collectionsTableName = JDBCVectorStoreQueryProvider .validateSQLidentifier(collectionsTableName); return this; @@ -178,7 +194,7 @@ public Builder withCollectionsTableName(String collectionsTableName) { * @param prefixForCollectionTables the prefix for collection tables * @return the builder */ - public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { + public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { this.prefixForCollectionTables = JDBCVectorStoreQueryProvider .validateSQLidentifier(prefixForCollectionTables); return this; @@ -188,12 +204,17 @@ public Builder withPrefixForCollectionTables(String prefixForCollectionT * Builds the options. * @return the options */ - public JDBCVectorStoreRecordCollectionOptions build() { + public JDBCVectorStoreRecordCollectionOptions build() { if (recordClass == null) { throw new SKException("recordClass is required"); } + if (keyClass == null) { + throw new SKException("keyClass is required"); + } + return new JDBCVectorStoreRecordCollectionOptions<>( + keyClass, recordClass, recordDefinition, vectorStoreRecordMapper, diff --git a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/SQLVectorStoreQueryProvider.java b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/SQLVectorStoreQueryProvider.java index 30a535fb..d042f1de 100644 --- a/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/SQLVectorStoreQueryProvider.java +++ b/data/semantickernel-data-jdbc/src/main/java/com/microsoft/semantickernel/data/jdbc/SQLVectorStoreQueryProvider.java @@ -18,7 +18,7 @@ * The JDBC vector store query provider. * Provides the necessary methods to interact with a JDBC vector store and vector store collections. */ -public interface SQLVectorStoreQueryProvider { +public interface SQLVectorStoreQueryProvider { /** * The default name for the collections table. */ @@ -104,7 +104,7 @@ public interface SQLVectorStoreQueryProvider { * @param the record type * @return the records */ - List getRecords(String collectionName, List keys, + List getRecords(String collectionName, List keys, VectorStoreRecordDefinition recordDefinition, VectorStoreRecordMapper mapper, GetRecordOptions options); @@ -128,7 +128,7 @@ void upsertRecords(String collectionName, List records, * @param recordDefinition the record definition * @param options the options */ - void deleteRecords(String collectionName, List keys, + void deleteRecords(String collectionName, List keys, VectorStoreRecordDefinition recordDefinition, DeleteRecordOptions options); /** @@ -166,7 +166,7 @@ VectorStoreRecordMapper getVectorStoreRecordMapper( /** * The builder for the JDBC vector store query provider. */ - interface Builder extends SemanticKernelBuilder { + interface Builder extends SemanticKernelBuilder> { } } diff --git a/data/semantickernel-data-mysql/src/main/java/com/microsoft/semantickernel/data/jdbc/mysql/MySQLVectorStoreQueryProvider.java b/data/semantickernel-data-mysql/src/main/java/com/microsoft/semantickernel/data/jdbc/mysql/MySQLVectorStoreQueryProvider.java index feb6dc4f..98ab997d 100644 --- a/data/semantickernel-data-mysql/src/main/java/com/microsoft/semantickernel/data/jdbc/mysql/MySQLVectorStoreQueryProvider.java +++ b/data/semantickernel-data-mysql/src/main/java/com/microsoft/semantickernel/data/jdbc/mysql/MySQLVectorStoreQueryProvider.java @@ -28,7 +28,7 @@ * vector store and vector store collections. */ public class MySQLVectorStoreQueryProvider extends - JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { + JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { private final ObjectMapper objectMapper; diff --git a/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreFieldHelper.java b/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreFieldHelper.java index bf4dd295..0b1a161e 100644 --- a/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreFieldHelper.java +++ b/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreFieldHelper.java @@ -62,6 +62,13 @@ class OracleVectorStoreFieldHelper { private static final HashMap, String> supportedKeyTypes = new HashMap(); static { supportedKeyTypes.put(String.class, String.format(OracleDataTypesMapping.STRING_VARCHAR, 255)); + supportedKeyTypes.put(short.class, OracleDataTypesMapping.SHORT); + supportedKeyTypes.put(Short.class, OracleDataTypesMapping.SHORT); + supportedKeyTypes.put(int.class, OracleDataTypesMapping.INTEGER); + supportedKeyTypes.put(Integer.class, OracleDataTypesMapping.INTEGER); + supportedKeyTypes.put(long.class, OracleDataTypesMapping.LONG); + supportedKeyTypes.put(Long.class, OracleDataTypesMapping.LONG); + supportedKeyTypes.put(UUID.class, OracleDataTypesMapping.UUID); } /** diff --git a/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreQueryProvider.java b/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreQueryProvider.java index e3fa157b..32d71edb 100644 --- a/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreQueryProvider.java +++ b/data/semantickernel-data-oracle/src/main/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreQueryProvider.java @@ -43,6 +43,7 @@ import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordDataField; import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordDefinition; import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordField; +import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordKeyField; import com.microsoft.semantickernel.data.vectorstorage.definition.VectorStoreRecordVectorField; import com.microsoft.semantickernel.data.vectorstorage.options.GetRecordOptions; import com.microsoft.semantickernel.data.vectorstorage.options.UpsertRecordOptions; @@ -77,7 +78,7 @@ /** * JDBC Vector Store for the Oracle Database */ -public class OracleVectorStoreQueryProvider extends JDBCVectorStoreQueryProvider { +public class OracleVectorStoreQueryProvider extends JDBCVectorStoreQueryProvider { // This could be removed if super.collectionTable made protected private final String collectionsTable; @@ -363,7 +364,7 @@ private void setUpsertStatementValues(PreparedStatement upsertStatement, Object } continue; } - } else if (field instanceof VectorStoreRecordDataField) { + } else if (field instanceof VectorStoreRecordDataField || field instanceof VectorStoreRecordKeyField) { // Lists are stored as JSON objects, write the list using the JDBC OSON // extensions. if (field.getFieldType().equals(List.class)) { @@ -751,15 +752,15 @@ public VectorStoreRecordMapper getVectorStoreRecordM * Gets a builder that allows to build an OracleVectorStoreQueryProvider * @return the builder */ - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new Builder(); } /** * OracleVectorStoreQueryProvider builder. */ - public static class Builder - extends JDBCVectorStoreQueryProvider.Builder { + public static class Builder + extends JDBCVectorStoreQueryProvider.Builder { /** * The data source @@ -793,7 +794,7 @@ public static class Builder @SuppressFBWarnings("EI_EXPOSE_REP2") - public Builder withDataSource(DataSource dataSource) { + public Builder withDataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } @@ -803,7 +804,7 @@ public Builder withDataSource(DataSource dataSource) { * @param collectionsTable the collections table name * @return the builder */ - public Builder withCollectionsTable(String collectionsTable) { + public Builder withCollectionsTable(String collectionsTable) { this.collectionsTable = validateSQLidentifier(collectionsTable); return this; } @@ -813,7 +814,7 @@ public Builder withCollectionsTable(String collectionsTable) { * @param prefixForCollectionTables the prefix for collection tables * @return the builder */ - public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { + public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { this.prefixForCollectionTables = validateSQLidentifier(prefixForCollectionTables); return this; } @@ -824,7 +825,7 @@ public Builder withPrefixForCollectionTables(String prefixForCollectionTables) { * @return the builder */ @SuppressFBWarnings("EI_EXPOSE_REP2") - public Builder withObjectMapper( + public Builder withObjectMapper( ObjectMapper objectMapper) { this.objectMapper = objectMapper; return this; @@ -836,7 +837,7 @@ public Builder withObjectMapper( * {@link StringTypeMapping#USE_VARCHAR} * @return the builder */ - public Builder withStringTypeMapping (StringTypeMapping stringTypeMapping) { + public Builder withStringTypeMapping (StringTypeMapping stringTypeMapping) { this.stringTypeMapping = stringTypeMapping; return this; } @@ -847,7 +848,7 @@ public Builder withStringTypeMapping (StringTypeMapping stringTypeMapping) { * is 2000. * @return then builder */ - public Builder withDefaultVarcharSize (int defaultVarcharSize) { + public Builder withDefaultVarcharSize (int defaultVarcharSize) { this.defaultVarcharSize = defaultVarcharSize; return this; } @@ -857,10 +858,9 @@ public Builder withDefaultVarcharSize (int defaultVarcharSize) { * @return the query provider */ @Override - public OracleVectorStoreQueryProvider build() { - return new OracleVectorStoreQueryProvider(dataSource, collectionsTable, + public OracleVectorStoreQueryProvider build() { + return new OracleVectorStoreQueryProvider(dataSource, collectionsTable, prefixForCollectionTables, defaultVarcharSize, stringTypeMapping, objectMapper); } } } - diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreAnnotatedTypeTest.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreAnnotatedTypeTest.java index e0332950..f5e2ac45 100644 --- a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreAnnotatedTypeTest.java +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreAnnotatedTypeTest.java @@ -100,7 +100,7 @@ void testDataTypes(String dataFieldName, Class dataFieldType, Object dataFiel Arrays.asList(keyField, dataTypeField, dataField, dummyVector) ); - OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() .withDataSource(DATA_SOURCE) .build(); diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreKeyTypesTest.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreKeyTypesTest.java new file mode 100644 index 00000000..57d18b86 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/OracleVectorStoreKeyTypesTest.java @@ -0,0 +1,373 @@ +/* + ** Oracle Database Vector Store Connector for Semantic Kernel (Java) + ** + ** Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + ** + ** The MIT License (MIT) + ** + ** Permission is hereby granted, free of charge, to any person obtaining a copy + ** of this software and associated documentation files (the "Software"), to + ** deal in the Software without restriction, including without limitation the + ** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + ** sell copies of the Software, and to permit persons to whom the Software is + ** furnished to do so, subject to the following conditions: + ** + ** The above copyright notice and this permission notice shall be included in + ** all copies or substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + ** IN THE SOFTWARE. + */ +package com.microsoft.semantickernel.data.jdbc.oracle; + +import com.microsoft.semantickernel.data.jdbc.JDBCVectorStore; +import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreRecordCollectionOptions; +import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreOptions; +import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreRecordCollectionOptions; +import com.microsoft.semantickernel.data.jdbc.oracle.data.IntTypeKeyBoxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.IntTypeKeyUnboxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.LongTypeKeyBoxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.LongTypeKeyUnboxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.ShortTypeKeyBoxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.ShortTypeKeyUnboxed; +import com.microsoft.semantickernel.data.jdbc.oracle.data.UUIDTypeKey; +import com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; +import com.microsoft.semantickernel.data.vectorstorage.options.GetRecordOptions; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import java.util.UUID; + +public class OracleVectorStoreKeyTypesTest extends OracleCommonVectorStoreRecordCollectionTest { + + + @Test + public void shortTypeKeyUnboxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider + .builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("ShortTypeKeyUnboxed", + JDBCVectorStoreRecordCollectionOptions + .genericBuilder() + .withKeyClass(Short.class) + .withRecordClass(ShortTypeKeyUnboxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + ShortTypeKeyUnboxed record = new ShortTypeKeyUnboxed(); + record.key = 1; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + ShortTypeKeyUnboxed results = collection.getAsync((short)1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync((short) 1, null).block(); + + ShortTypeKeyUnboxed resultsAfterDelete = collection.getAsync( + (short) 1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + @Test + public void shortTypeKeyBoxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider + .builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("ShortTypeKeyBoxed", + JDBCVectorStoreRecordCollectionOptions + .genericBuilder() + .withKeyClass(Short.class) + .withRecordClass( + ShortTypeKeyBoxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + ShortTypeKeyBoxed record = new ShortTypeKeyBoxed(); + record.key = 1; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + ShortTypeKeyBoxed results = collection.getAsync((short)1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync((short)1, null).block(); + + ShortTypeKeyBoxed resultsAfterDelete = collection.getAsync((short)1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + + @Test + public void intTypeKeyUnboxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("IntTypeKeyUnboxed", + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(Integer.class) + .withRecordClass(IntTypeKeyUnboxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + IntTypeKeyUnboxed record = new IntTypeKeyUnboxed(); + record.key = 1; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + IntTypeKeyUnboxed results = collection.getAsync(1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync(1, null).block(); + + IntTypeKeyUnboxed resultsAfterDelete = collection.getAsync(1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + @Test + public void intTypeKeyBoxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("IntTypeKeyBoxed", + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(Integer.class) + .withRecordClass( + IntTypeKeyBoxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + IntTypeKeyBoxed record = new IntTypeKeyBoxed(); + record.key = 1; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + IntTypeKeyBoxed results = collection.getAsync(1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync(1, null).block(); + + IntTypeKeyBoxed resultsAfterDelete = collection.getAsync(1, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + @Test + public void longTypeKeyUnboxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("LongTypeKeyUnboxed", + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(Long.class) + .withRecordClass( + LongTypeKeyUnboxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + LongTypeKeyUnboxed record = new LongTypeKeyUnboxed(); + record.key = 1; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + LongTypeKeyUnboxed results = collection.getAsync(1L, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync(1L, null).block(); + + LongTypeKeyUnboxed resultsAfterDelete = collection.getAsync(1L, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + @Test + public void longTypeKeyBoxedTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("LongTypeKeyBoxed", + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(Long.class) + .withRecordClass( + LongTypeKeyBoxed.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + LongTypeKeyBoxed record = new LongTypeKeyBoxed(); + record.key = 1L; + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + LongTypeKeyBoxed results = collection.getAsync(1L, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync(1L, null).block(); + + LongTypeKeyBoxed resultsAfterDelete = collection.getAsync(1L, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + + @Test + public void uuidTypeKeyTest() { + OracleVectorStoreQueryProvider queryProvider = OracleVectorStoreQueryProvider.builder() + .withDataSource(DATA_SOURCE) + .build(); + + JDBCVectorStore vectorStore = JDBCVectorStore.builder() + .withDataSource(DATA_SOURCE) + .withOptions(JDBCVectorStoreOptions.builder() + .withQueryProvider(queryProvider) + .build()) + .build(); + + VectorStoreRecordCollection collection = vectorStore + .getCollection("UUIDTypeKey", + JDBCVectorStoreRecordCollectionOptions.genericBuilder() + .withKeyClass(UUID.class) + .withRecordClass( + UUIDTypeKey.class) + .build()) + .createCollectionAsync().block(); + + collection.createCollectionAsync().block(); + + UUIDTypeKey record = new UUIDTypeKey(); + record.key = UUID.randomUUID(); + record.data = "one"; + record.vector = new float[] { 0.5f, 3.2f, 7.1f, -4.0f, 2.8f, 10.0f, -1.3f, 5.5f }; + + collection.upsertAsync(record, null).block(); + + UUIDTypeKey results = collection.getAsync(record.key, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertEquals(record.key, results.key); + Assert.assertEquals(record.data, results.data); + + collection.deleteAsync(record.key, null).block(); + + UUIDTypeKey resultsAfterDelete = collection.getAsync(record.key, + GetRecordOptions.builder().includeVectors(false).build()).block(); + + Assert.assertNull(resultsAfterDelete); + } + +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyBoxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyBoxed.java new file mode 100644 index 00000000..30455188 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyBoxed.java @@ -0,0 +1,24 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class IntTypeKeyBoxed { + @VectorStoreRecordKey + public Integer key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public IntTypeKeyBoxed () {} + + public IntTypeKeyBoxed (Integer key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyUnboxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyUnboxed.java new file mode 100644 index 00000000..49523e40 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/IntTypeKeyUnboxed.java @@ -0,0 +1,24 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class IntTypeKeyUnboxed { + @VectorStoreRecordKey + public int key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public IntTypeKeyUnboxed () {} + + public IntTypeKeyUnboxed (int key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyBoxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyBoxed.java new file mode 100644 index 00000000..8911c44b --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyBoxed.java @@ -0,0 +1,24 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class LongTypeKeyBoxed { + @VectorStoreRecordKey + public Long key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public LongTypeKeyBoxed () {} + + public LongTypeKeyBoxed (Long key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyUnboxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyUnboxed.java new file mode 100644 index 00000000..1aed9487 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/LongTypeKeyUnboxed.java @@ -0,0 +1,24 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class LongTypeKeyUnboxed { + @VectorStoreRecordKey + public long key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public LongTypeKeyUnboxed () {} + + public LongTypeKeyUnboxed (long key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyBoxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyBoxed.java new file mode 100644 index 00000000..e78d36f3 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyBoxed.java @@ -0,0 +1,25 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class ShortTypeKeyBoxed { + @VectorStoreRecordKey + public Short key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public ShortTypeKeyBoxed () {} + + public ShortTypeKeyBoxed (Short key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} + diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyUnboxed.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyUnboxed.java new file mode 100644 index 00000000..37e02c2e --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/ShortTypeKeyUnboxed.java @@ -0,0 +1,24 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; + +public class ShortTypeKeyUnboxed { + @VectorStoreRecordKey + public short key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public ShortTypeKeyUnboxed () {} + + public ShortTypeKeyUnboxed (short key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/UUIDTypeKey.java b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/UUIDTypeKey.java new file mode 100644 index 00000000..47ee8a66 --- /dev/null +++ b/data/semantickernel-data-oracle/src/test/java/com/microsoft/semantickernel/data/jdbc/oracle/data/UUIDTypeKey.java @@ -0,0 +1,25 @@ +package com.microsoft.semantickernel.data.jdbc.oracle.data; + +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey; +import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector; +import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction; +import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind; +import java.util.UUID; + +public class UUIDTypeKey { + @VectorStoreRecordKey + public UUID key; + @VectorStoreRecordData(isFilterable = true) + public String data; + @VectorStoreRecordVector(dimensions = 8, distanceFunction = DistanceFunction.COSINE_DISTANCE, indexKind = IndexKind.IVFFLAT) + public float[] vector; + + public UUIDTypeKey () {} + + public UUIDTypeKey (UUID key, String data, float[] vector) { + this.key = key; + this.data = data; + this.vector = vector; + } +} diff --git a/data/semantickernel-data-postgres/src/main/java/com/microsoft/semantickernel/data/jdbc/postgres/PostgreSQLVectorStoreQueryProvider.java b/data/semantickernel-data-postgres/src/main/java/com/microsoft/semantickernel/data/jdbc/postgres/PostgreSQLVectorStoreQueryProvider.java index 1f3273eb..0ab7bd9f 100644 --- a/data/semantickernel-data-postgres/src/main/java/com/microsoft/semantickernel/data/jdbc/postgres/PostgreSQLVectorStoreQueryProvider.java +++ b/data/semantickernel-data-postgres/src/main/java/com/microsoft/semantickernel/data/jdbc/postgres/PostgreSQLVectorStoreQueryProvider.java @@ -45,7 +45,7 @@ * vector store and vector store collections. */ public class PostgreSQLVectorStoreQueryProvider extends - JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { + JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { private final String collectionsTable; private final String prefixForCollectionTables; private final ObjectMapper objectMapper; diff --git a/data/semantickernel-data-sqlite/src/main/java/com/microsoft/semantickernel/data/jdbc/sqlite/SQLiteVectorStoreQueryProvider.java b/data/semantickernel-data-sqlite/src/main/java/com/microsoft/semantickernel/data/jdbc/sqlite/SQLiteVectorStoreQueryProvider.java index 57de1225..af9ead96 100644 --- a/data/semantickernel-data-sqlite/src/main/java/com/microsoft/semantickernel/data/jdbc/sqlite/SQLiteVectorStoreQueryProvider.java +++ b/data/semantickernel-data-sqlite/src/main/java/com/microsoft/semantickernel/data/jdbc/sqlite/SQLiteVectorStoreQueryProvider.java @@ -25,7 +25,7 @@ * A query provider for a vector store in SQLite. */ public class SQLiteVectorStoreQueryProvider extends - JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { + JDBCVectorStoreQueryProvider implements SQLVectorStoreQueryProvider { private final DataSource dataSource; private final ObjectMapper objectMapper;