From 96393cfed3eaaacf80a1f40e7235dd884230624e Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 2 Sep 2021 19:28:52 +0000 Subject: [PATCH 01/81] Merged PR 649012: Generalize ClientProvider, ConfigurationProvider, and DB Connection Configuration Introducing changes to abstract out DatabaseCredentials, ClientProvider with changes to accomodate this in the ConfigurationProvider and Startup classes. Configuration files updated to accommodate interpreting database type during startup and configuration initialization. # Why this change is needed The first step in extending the POC to be compatible with SQL Database is through generalizing the database credentials classes, the clientproviders, and configuration provider. # How Describe how the change works. ##Startup class - Infers DatabaseType from _appsettings.json_ . The DatabaseType determines the implementation of _IClientProvider_. ##IDatabaseCredentials interface - created to capture overlap between SQL and Cosmos connections which is the ConnectionString. I chose _ConnectionString_ over _EndpointURL_ as the interface member because connectionstring is a superset of endpointurl for both database types. Can leave database specific details such as username, password, access keys to the specific class implementations. Future work to accommodate Postgres TBD because Postgres requires connectionstring to be built. ##IClientProvider interface - Created to capture overlap between clients. ClientProvider class must implement getClient(). Client initialization adhering to initial Cosmos POC model of Singletons. - Generic interface types expected: - SQL: SqlConnection - Cosmos: CosmosClient - Current PR utilizes Cosmos implementation of Singleton for connection. I want to get E2E working here first before optimizing further for collection of connections, which is implemented in SQLREST project. ##ConfigurationProvider - On initialization, the instance (Singleton enforced) reads from _appsettings.json_ to determine which DbCredential to create. ##Appsettings.json - Added proposed new db configuration structure to be read in by the configuration provider and startup class. The config specifies the database type to instruct which credentials class to implement (SQL/Cosmos). - Specific credentials classes created to accommodate future need to build the connection string. ``` json "DatabaseConnection": { "DatabaseType": "COSMOS", "Credentials": { "ServerEndpointUrl": "", "AuthorizationKey": "", "Container": "", "Database": "", "ConnectionString": "" } } ``` # Test Integration testing by calling REST endpoint to add and query schema. Addition test class written for ClientProvider to validate opening SQL connection succeeds. # Checklist - [X] Build and run test locally. - [ ] Check code coverage report and make sure that there are test coverage for your change. - [X] Link work item to this change. - [ ] Update the design/functional docs. added README to the section on testing Related work items: #1333552 --- .../Cosmos.GraphQL.Service.Tests.csproj | 4 +- .../SqlClientProviderTests.cs | 37 ++++++++++++++++++ .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 2 +- .../Cosmos.GraphQL.Service.csproj | 3 ++ .../Resolvers/CosmosClientProvider.cs | 20 ++++------ .../Resolvers/IClientProvider.cs | 16 ++++++++ .../Resolvers/MutationEngine.cs | 11 ------ .../Resolvers/SQLClientProvider.cs | 36 ++++++++++++++++++ .../Cosmos.GraphQL.Service/Startup.cs | 38 ++++++++++++++++--- .../Cosmos.GraphQL.Service/appsettings.json | 19 +++++++++- .../Cosmos.GraphQL.Service/config.json | 11 ------ .../configurations/ConfigurationProvider.cs | 38 ++++++++++--------- .../configurations/CosmosCredentials.cs | 15 ++++++++ .../configurations/IConfigurationProvider.cs | 15 ++++++++ .../configurations/IDatabaseCredentials.cs | 20 ++++++++++ .../configurations/SQLCredentials.cs | 12 ++++++ 16 files changed, 236 insertions(+), 61 deletions(-) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj index 858e39d0a5..a67bd14764 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs new file mode 100644 index 0000000000..af037fa819 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs @@ -0,0 +1,37 @@ +using Cosmos.GraphQL.Service.Resolvers; +using Microsoft.Data.SqlClient; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Data; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Tests +{ + [TestClass] + public class SqlClientProviderTests + { + private IClientProvider _clientProvider; + public SqlClientProviderTests() + { + _clientProvider = new SQLClientProvider(); + } + /// + /// Ensure a connection is successfully opened within the [Database]ClientProvider, + /// given a valid connection string. + /// + /// + [TestMethod] + public void TestOpenConnection() + { + SqlConnection connection = _clientProvider.getClient(); + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + Assert.IsTrue(connection.State.Equals(ConnectionState.Open)); + connection.Dispose(); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index e025ff544f..6b09650684 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -36,7 +36,7 @@ private void Init() clientProvider = new CosmosClientProvider(); string uid = Guid.NewGuid().ToString(); dynamic sourceItem = TestHelper.GetItem(uid); - clientProvider.getCosmosContainer().CreateItemAsync(sourceItem, new PartitionKey(uid)); // TODO: Make it sync + //clientProvider.getCosmosContainer().CreateItemAsync(sourceItem, new PartitionKey(uid)); // TODO: Make it sync metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index 910a6afd80..6c33240177 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -10,8 +10,11 @@ + + + diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs index 3496a9222f..93447d871d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs @@ -5,19 +5,22 @@ namespace Cosmos.GraphQL.Service.Resolvers { - public class CosmosClientProvider + public class CosmosClientProvider : IClientProvider { private static CosmosClient _cosmosClient; private static readonly object syncLock = new object(); private static void init() { - var cred = ConfigurationProvider.getInstance().cred; + var cred = ConfigurationProvider.getInstance().Creds; + _cosmosClient = new CosmosClientBuilder(cred.ConnectionString).WithContentResponseOnWrite(true).Build(); + } - _cosmosClient = new CosmosClientBuilder(cred.EndpointUrl, cred.AuthorizationKey).WithContentResponseOnWrite(true).Build(); - // _cosmosClient = new CosmosClient(cred.EndpointUrl, cred.AuthorizationKey). + public CosmosClient getClient() + { + return getCosmosClient(); } - + public CosmosClient getCosmosClient() { if (_cosmosClient == null) @@ -33,13 +36,6 @@ public CosmosClient getCosmosClient() return _cosmosClient; } - - public Container getCosmosContainer() - { - return getCosmosClient().GetDatabase(ConfigurationProvider.getInstance().databaseName) - .GetContainer(ConfigurationProvider.getInstance().containerName); - - } } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs new file mode 100644 index 0000000000..0052d448c7 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Interface representing database clients with retrieval method. + /// + /// Type of database client (i.e. SqlConnection or CosmosClient) + public interface IClientProvider + { + public T getClient(); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index bc51c77aba..e717dfd802 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -129,16 +129,5 @@ private async void executeInit() "Newtonsoft.Json", "Newtonsoft.Json.Linq"); } - - private async Task> runAndInitializedScript() - { - executeInit(); - - Globals.Initialize(_clientProvider.getCosmosContainer()); - Globals global = new Globals(); - - return await CSharpScript.RunAsync("Container container = Cosmos.Container;", this.scriptOptions, - globals: global); - } } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs new file mode 100644 index 0000000000..c55ae5f7e1 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; +using Cosmos.GraphQL.Service.configurations; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + public class SQLClientProvider: IClientProvider + { + private static SqlConnection _sqlConnection; + private static readonly object syncLock = new object(); + + private void init() + { + _sqlConnection = new SqlConnection(ConfigurationProvider.getInstance().Creds.ConnectionString); + } + + public SqlConnection getClient() + { + if (_sqlConnection == null) + { + lock (syncLock) + { + if (_sqlConnection == null) + { + init(); + } + } + } + + return _sqlConnection; + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 98192bbdeb..b4a958ef7c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -2,13 +2,22 @@ using Cosmos.GraphQL.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Azure.Cosmos; +using Microsoft.Data.SqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; - +using System; namespace Cosmos.GraphQL.Service { + enum DatabaseType + { + SQL, + COSMOS, + POSTGRES, + } + public class Startup { public Startup(IConfiguration configuration) @@ -21,15 +30,34 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + if(Configuration.GetValue("DatabaseConnection:DatabaseType") is null) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not *contain* the DatabaseType key.")); + } + + if (!Enum.TryParse(Configuration.GetValue("DatabaseConnection:DatabaseType"), out DatabaseType dbType)) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); + } + + switch (dbType) + { + case DatabaseType.COSMOS: + services.AddSingleton, CosmosClientProvider>(); + services.AddSingleton(); + services.AddSingleton(); + break; + case DatabaseType.SQL: + services.AddSingleton, SQLClientProvider>(); + break; + default: + throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); + } - // pass a singleton QueryEngine - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddControllers(); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index d9d9a9bff6..478f1acc96 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -6,5 +6,22 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "DatabaseConnection": { + "DatabaseType": "COSMOS", + "Credentials": { + "ServerEndpointUrl": "", + "AuthorizationKey": "", + "Container": "", + "Database": "", + "ConnectionString": "" + } + }, + "DatabaseConnection2": { + "DatabaseType": "SQL", + "Credentials": { + "ConnectionString": "" + + } + } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json deleted file mode 100644 index 97212bab6d..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "CosmosCredentials" : { - "EndPointUrl": "", - "AuthorizationKey": "" - }, - - "CosmosContainer" : "", - "CosmosDatabase" : "" -} - - diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index 78fd19eb17..47d970e750 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -6,14 +6,10 @@ namespace Cosmos.GraphQL.Service.configurations { public class ConfigurationProvider { - private static ConfigurationProvider instance; + private static ConfigurationProvider instance; private static readonly object lockObject = new object(); + public IDatabaseCredentials Creds { get; private set; } - public CosmosCredentials cred { get; private set; } - public string databaseName { get; private set; } - public string containerName { get; private set; } - - public static ConfigurationProvider getInstance() { if (instance == null) @@ -34,21 +30,27 @@ public static ConfigurationProvider getInstance() private void init() { - var config = new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) - .AddJsonFile("config.json").Build(); + .AddJsonFile("AppSettings.json").Build(); - var section = config.GetSection(nameof(CosmosCredentials)); - cred = section.Get(); - containerName = config.GetValue("CosmosContainer"); - databaseName = config.GetValue("CosmosDatabase"); + var section = config.GetSection("DatabaseConnection"); + if (!Enum.TryParse(section["DatabaseType"], out DatabaseType dbType)) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); + } + section = section.GetSection("Credentials"); + switch (dbType) + { + case DatabaseType.COSMOS: + Creds = section.Get(); + break; + case DatabaseType.SQL: + Creds = section.Get(); + break; + default: + break; + } } } - - public class CosmosCredentials - { - public string EndpointUrl { get; set; } - public string AuthorizationKey { get; set; } - } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs new file mode 100644 index 0000000000..f349bbbe18 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + public class CosmosCredentials : IDatabaseCredentials + { + public string ConnectionString { get; set; } + public string EndpointUrl { get; set; } + public string AuthorizationKey { get; set; } + public string Container { get; set; } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs new file mode 100644 index 0000000000..7f042a0d6d --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + /// + /// Provider for the singleton instance of a connection provider to a specific database + /// + public interface IConfigurationProvider + { + public IConfigurationProvider getInstance(); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs new file mode 100644 index 0000000000..2fd1e89e2f --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + /// + /// This interface defines the common connection field utilized between Cosmos/SQL. + /// Classes that implement this interface can also add their own db specific fields. + /// + public interface IDatabaseCredentials + { + /// + /// ConnectionString represents the minimal info needed to connect to a given database. + /// It is the common factor between Cosmos DB and SQL DB. Pending Postgres. + /// + public string ConnectionString { get; set; } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs new file mode 100644 index 0000000000..1240c4c8c1 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + public class SQLCredentials : IDatabaseCredentials + { + public string ConnectionString { get; set; } + } +} From 165a96b2f4d4962e714de861c218e6293b619b54 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Fri, 3 Sep 2021 18:27:25 +0000 Subject: [PATCH 02/81] Merged PR 654028: Create FileMetadataStoreProvider to read GraphQL config from file #Summary Initial work to create FileMetadataStoreProvider, enables reading JSON config from file. Renamed interface to IMetadataStoreProvider. Sample Config.json for runtime config. Gitignore updated to ignore /vs folder. Added two simple integration tests for new fileprovider. # Why this change is needed The first step in extending the POC to be compatible with SQL Database is through generalizing the database credentials classes, the clientproviders, and configuration provider. # How Describe how the change works. ##IMetadataStoreProvider - Files which had previously referenced the interface as MetadataStoreProvider now reference the renamed interface __IMetadataStoreProvider__ ##FileMetadataStoreProvider - Implemented to act us underlying storage of configuration data assuming that configuration is only read once at startup. In this case, the class constructor is responsible for reading the file, storing the GraphQL schema string and saving the Resolvers as key/value pairs into a collection. The Get() calls are similar to the cachedmetadatastoreprovider where a dictionary is used to keep track of resolvername:resolvervalue. ##config.json - Added simplified skeleton of GraphQL configuration file as agreed on during architecture meetings: 1 file with schema and resolvers embedded ``` json { "GraphQLSchema": "", "Resolvers": [ { "engine": "SQL", "name": "bookById", "database": "", "container": "", "parametrizedQuery": "SELECT * from r WHERE r.id = @arg.id", "operationType": "READ_ITEM" }, { "name": "authorById" } ] } ``` ##.gitignore Updated to not track __vs/__ folders within the project, for sanity. # Test Integration testing done by creating MetadataProviderTests class: - Getting schema from config - Getting resolver from config # Checklist - [X] Build and run test locally. - [X] Check code coverage report and make sure that there are test coverage for your change. - [X] Link work item to this change. - [ ] Update the design/functional docs. added README to the section on testing Related work items: #1333554 --- .gitignore | 4 +- .../MetadataProviderTests.cs | 33 ++++++++ .../SchemaTests.cs | 2 +- .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 2 +- .../Resolvers/MutationEngine.cs | 7 +- .../Resolvers/QueryEngine.cs | 4 +- .../Services/CachedMetadataStoreProvider.cs | 5 +- .../Services/DocumentMetadataStoreProvider.cs | 2 +- .../Services/FileMetadataStoreProvider.cs | 84 +++++++++++++++++++ .../Services/GraphQLService.cs | 4 +- ...eProvider.cs => IMetadataStoreProvider.cs} | 2 +- .../Cosmos.GraphQL.Service/Startup.cs | 2 +- .../Cosmos.GraphQL.Service/config.json | 18 ++++ 13 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/{MetadataStoreProvider.cs => IMetadataStoreProvider.cs} (95%) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json diff --git a/.gitignore b/.gitignore index bab11274cb..077b9433cb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,7 @@ Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/bin/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/obj/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/.idea/* - */.idea/* + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs new file mode 100644 index 0000000000..b6b1d31c94 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Cosmos.GraphQL.Services; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Cosmos.GraphQL.Service.Tests +{ + [TestClass] + public class MetadataProviderTests + { + IMetadataStoreProvider _fileProvider; + + public MetadataProviderTests() + { + _fileProvider = new FileMetadataStoreProvider(); + } + + [TestMethod] + public void TestGetSchema() + { + Assert.IsNotNull(_fileProvider.GetGraphQLSchema()); + } + + [TestMethod] + public void TestGetResolver() + { + Assert.IsNotNull(_fileProvider.GetQueryResolver("authorById")); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index b6936d04dc..91b21ed28c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -19,7 +19,7 @@ public class SchemaTests public async Task TestAddSchemaAsync() { CosmosClientProvider clientProvider = new CosmosClientProvider(); - MetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); + IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); QueryEngine queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, clientProvider, metadataStoreProvider); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index 6b09650684..c842c5f525 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -20,7 +20,7 @@ public class TestBase { internal GraphQLService graphQLService; internal CosmosClientProvider clientProvider; - internal MetadataStoreProvider metadataStoreProvider; + internal IMetadataStoreProvider metadataStoreProvider; internal QueryEngine queryEngine; internal MutationEngine mutationEngine; internal GraphQLController controller; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index e717dfd802..13c0097c20 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -21,17 +21,14 @@ public class MutationEngine { private readonly CosmosClientProvider _clientProvider; - private readonly MetadataStoreProvider _metadataStoreProvider; + private readonly IMetadataStoreProvider _metadataStoreProvider; private ScriptOptions scriptOptions; - public MutationEngine(CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public MutationEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; - - // - // new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider.getCosmosClient())); } public void registerResolver(MutationResolver resolver) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs index d92dd93673..357a5ce435 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs @@ -21,9 +21,9 @@ public class QueryEngine private readonly CosmosClientProvider _clientProvider; private ScriptOptions scriptOptions; - private MetadataStoreProvider _metadataStoreProvider; + private IMetadataStoreProvider _metadataStoreProvider; - public QueryEngine(CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public QueryEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs index 16a58eaae0..be533a23e0 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs @@ -18,14 +18,13 @@ public MetadataStoreException(string message, Exception inner) } } - public class CachedMetadataStoreProvider : MetadataStoreProvider + public class CachedMetadataStoreProvider : IMetadataStoreProvider { - private readonly MetadataStoreProvider _storeProvider; + private readonly IMetadataStoreProvider _storeProvider; private string _schema; private ConcurrentDictionary _mutationResolvers = new ConcurrentDictionary(); private ConcurrentDictionary _queryResolvers = new ConcurrentDictionary(); - public CachedMetadataStoreProvider(DocumentMetadataStoreProvider storeProvider) { this._storeProvider = storeProvider; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs index 5b6fdf2f72..b8315f37b0 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs @@ -7,7 +7,7 @@ namespace Cosmos.GraphQL.Services { - public class DocumentMetadataStoreProvider : MetadataStoreProvider + public class DocumentMetadataStoreProvider : IMetadataStoreProvider { private readonly CosmosClient client; private readonly string systemDatabaseName = "_systemGraphQL"; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs new file mode 100644 index 0000000000..ed7e820192 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs @@ -0,0 +1,84 @@ +using Cosmos.GraphQL.Service.Models; +using Cosmos.GraphQL.Services; +using System; +using System.IO; +using System.Text.Json; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service +{ + public class FileMetadataStoreProvider : IMetadataStoreProvider + { + private string _graphQLSchema; + private IDictionary _resolvers; + + public FileMetadataStoreProvider() + { + init(); + } + + private void init() + { + string jsonString = File.ReadAllText(@"config.json"); + + using (JsonDocument document = JsonDocument.Parse(jsonString)) + { + JsonElement root = document.RootElement; + JsonElement schema = root.GetProperty("GraphQLSchema"); + _graphQLSchema = schema.GetString(); + JsonElement resolversListJson = root.GetProperty("Resolvers"); + _resolvers = new Dictionary(); + foreach(JsonElement resolver in resolversListJson.EnumerateArray()) + { + _resolvers.Add(resolver.GetProperty("name").ToString(), resolver.ToString()); + } + } + + } + /// + /// Reads generated JSON configuration file with GraphQL Schema + /// + /// GraphQL schema as string + public string GetGraphQLSchema() + { + return _graphQLSchema; + } + + public MutationResolver GetMutationResolver(string name) + { + if (!_resolvers.TryGetValue(name, out string resolver)) + { + throw new KeyNotFoundException("Mutation Resolver does not exist."); + } + + return JsonSerializer.Deserialize(resolver); + } + + public GraphQLQueryResolver GetQueryResolver(string name) + { + if (!_resolvers.TryGetValue(name, out string resolver)) + { + throw new KeyNotFoundException("Query Resolver does not exist."); + } + + return JsonSerializer.Deserialize(resolver); + } + + public void StoreGraphQLSchema(string schema) + { + throw new NotImplementedException(); + } + + public void StoreMutationResolver(MutationResolver mutationResolver) + { + throw new NotImplementedException(); + } + + public void StoreQueryResolver(GraphQLQueryResolver mutationResolver) + { + throw new NotImplementedException(); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 9ac49771af..c2f04dab82 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -46,9 +46,9 @@ public MyDocumentWriter(IDocumentWriter internalWriter) private readonly QueryEngine _queryEngine; private readonly MutationEngine _mutationEngine; - private MetadataStoreProvider _metadataStoreProvider; + private IMetadataStoreProvider _metadataStoreProvider; - public GraphQLService(QueryEngine queryEngine, MutationEngine mutationEngine, CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public GraphQLService(QueryEngine queryEngine, MutationEngine mutationEngine, CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._queryEngine = queryEngine; this._mutationEngine = mutationEngine; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs similarity index 95% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs index 2db1babaad..adc451bd95 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs @@ -19,7 +19,7 @@ namespace Cosmos.GraphQL.Services { - public interface MetadataStoreProvider + public interface IMetadataStoreProvider { void StoreGraphQLSchema(string schema); string GetGraphQLSchema(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index b4a958ef7c..60b60dba8e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -54,7 +54,7 @@ public void ConfigureServices(IServiceCollection services) throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); } - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json new file mode 100644 index 0000000000..33967ccc03 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -0,0 +1,18 @@ +{ + "GraphQLSchema": "{ \r\n type Query { \r\n bookById (id: @id): Book \r\n } \r\n\r\n type Book { \r\n id : ID!, \r\n title : String!, \r\n numberOfPages: Int, \r\n author: Author\r\n } \r\n\r\n type Author { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String, \r\n address: String, \r\n } \r\n\r\n type Mutation { \r\n addBook( \r\n id : ID!, \r\n title: String!, \r\n numberOfPages: Int, \r\n author : { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String \r\n address: String \r\n } \r\n ): Book \r\n } \r\n} ", + "Resolvers": [ + { + "engine": "SQL", + "name": "bookById", + "database": "", + "container": "", + "parametrizedQuery": "SELECT * from r WHERE r.id = @arg.id", + "operationType": "READ_ITEM" + }, + { + "name": "authorById" + } + ] +} + + From 8c4a8b9b28516c038e99b3113344fd9f8b55f74d Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 3 Sep 2021 20:35:28 +0000 Subject: [PATCH 03/81] Merged PR 654882: Create IQueryEngine to represent execution against a backend data source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Summary** Added an interface IQueryEngine representing the execution against the backend data source for different queries. Renamed existing QueryEngine to CosmosQueryEngine and added skeleton code for SQLQueryEngine. The SQLQueryEngine::Execute method contains only comments on how this will be executed in future as a TODO. **Why this change is needed** We need to have abstract interfaces for all the existing classes that target CosmosDb. This change is 1 step closer to that. Merging this sooner before completely implementing the Execute method since we are moving to github. **How** Currently, IQueryEngine exposes 4 functions that should be implemented by each query engine. `RegisterResolver`, `Execute`, `ExecuteList`, `IsListQuery` Each query engine has private members for - connecting to the respective backend `_clientProvider ` - retrieving the metadata (aka graphql schema) `_metadataProvider` **Test** No new tests are added since this is just a skeleton code. Existing Build and tests still pass. **Checklist** • [X] Build and run test locally. • [ ] Check code coverage report and make sure that there are test coverage for your change. • [X] Link work item to this change. • [ ] Update the design/functional docs. Related work items: #1333353 --- .../SchemaTests.cs | 4 +- .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 6 +- .../Controllers/GraphQLController.cs | 8 +- .../{QueryEngine.cs => CosmosQueryEngine.cs} | 33 ++++--- .../Resolvers/IQueryEngine.cs | 33 +++++++ .../Resolvers/SQLQueryEngine.cs | 88 +++++++++++++++++++ .../Services/GraphQLService.cs | 10 +-- .../Cosmos.GraphQL.Service/Startup.cs | 3 +- 8 files changed, 160 insertions(+), 25 deletions(-) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/{QueryEngine.cs => CosmosQueryEngine.cs} (78%) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index 91b21ed28c..2d6cff1f7e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -20,9 +20,9 @@ public async Task TestAddSchemaAsync() { CosmosClientProvider clientProvider = new CosmosClientProvider(); IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); - QueryEngine queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); + CosmosQueryEngine queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); - GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, clientProvider, metadataStoreProvider); + GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); var graphql_schema = TestHelper.GraphQLTestSchema; var request = new HttpRequestMessage(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index c842c5f525..b071a47edf 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -21,7 +21,7 @@ public class TestBase internal GraphQLService graphQLService; internal CosmosClientProvider clientProvider; internal IMetadataStoreProvider metadataStoreProvider; - internal QueryEngine queryEngine; + internal CosmosQueryEngine queryEngine; internal MutationEngine mutationEngine; internal GraphQLController controller; @@ -39,9 +39,9 @@ private void Init() //clientProvider.getCosmosContainer().CreateItemAsync(sourceItem, new PartitionKey(uid)); // TODO: Make it sync metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); - queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); + queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); - graphQLService = new GraphQLService(queryEngine, mutationEngine, clientProvider, metadataStoreProvider); + graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); graphQLService.parseAsync(TestHelper.GraphQLTestSchema); controller = new GraphQLController(null, queryEngine, mutationEngine, graphQLService); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs index 4b87f61ea1..58918ce404 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs @@ -19,15 +19,15 @@ namespace Cosmos.GraphQL.Service.Controllers public class GraphQLController : ControllerBase { - string JsonData = @"{'serviceName':'cosmos', 'endpointType':'graphQL'}"; + string JsonData = @"{'serviceName':'datagateway', 'endpointType':'graphQL'}"; - private readonly QueryEngine _queryEngine; + private readonly IQueryEngine _queryEngine; private readonly MutationEngine _mutationEngine; private readonly ILogger _logger; private readonly GraphQLService _schemaManager; - public GraphQLController(ILogger logger, QueryEngine queryEngine, MutationEngine mutationEngine, GraphQLService schemaManager) + public GraphQLController(ILogger logger, IQueryEngine queryEngine, MutationEngine mutationEngine, GraphQLService schemaManager) { _logger = logger; @@ -47,7 +47,7 @@ public IEnumerable Get() [HttpPost] public void addResolver(GraphQLQueryResolver resolver) { - _queryEngine.registerResolver(resolver); + _queryEngine.RegisterResolver(resolver); _schemaManager.attachQueryResolverToSchema(resolver.id); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs similarity index 78% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs index 357a5ce435..cf54726c0f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs @@ -16,25 +16,35 @@ namespace Cosmos.GraphQL.Services { - public class QueryEngine + // + // CosmosQueryEngine to Execute against CosmosDb. + // + public class CosmosQueryEngine : IQueryEngine { private readonly CosmosClientProvider _clientProvider; - - private ScriptOptions scriptOptions; private IMetadataStoreProvider _metadataStoreProvider; - public QueryEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + // + // Constructor. + // + public CosmosQueryEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { - this._clientProvider = clientProvider; + this._clientProvider = (CosmosClientProvider)clientProvider; this._metadataStoreProvider = metadataStoreProvider; } - public void registerResolver(GraphQLQueryResolver resolver) + // + // Register the given resolver with this query engine. + // + public void RegisterResolver(GraphQLQueryResolver resolver) { - this._metadataStoreProvider.StoreQueryResolver(resolver); + this._metadataStoreProvider.StoreQueryResolver(resolver); } - public JsonDocument execute(string graphQLQueryName, IDictionary parameters) + // + // Execute the given named graphql query on the backend. + // + public JsonDocument Execute(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container @@ -67,7 +77,7 @@ public JsonDocument execute(string graphQLQueryName, IDictionary executeList(string graphQLQueryName, IDictionary parameters) + public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container @@ -101,7 +111,10 @@ public IEnumerable executeList(string graphQLQueryName, IDictionar return resultsAsList; } - internal bool isListQuery(string queryName) + // + // Returns if the given query is a list query. + // + public bool IsListQuery(string queryName) { return _metadataStoreProvider.GetQueryResolver(queryName).isList; } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs new file mode 100644 index 0000000000..27b035fc8f --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Text.Json; +using Cosmos.GraphQL.Service.Models; +using GraphQL.Execution; + +namespace Cosmos.GraphQL.Services +{ + // + // Interface for execution against the backend data source for different queries. + // + public interface IQueryEngine + { + // + // Registers the given resolver with this query engine. + // + public void RegisterResolver(GraphQLQueryResolver resolver); + + // + // Executes the given named graphql query on the backend and expecting a single Json back. + // + public JsonDocument Execute(string graphQLQueryName, IDictionary parameters); + + // + // Executes the given named graphql query on the backend and expecting a list of Jsons back. + // + public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters); + + // + // Returns if the given query is a list query. + // + public bool IsListQuery(string queryName); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs new file mode 100644 index 0000000000..27ce92d813 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Reflection; +using System.Text.Json; +using System.Threading.Tasks; +using Cosmos.GraphQL.Service.configurations; +using Cosmos.GraphQL.Service.Models; +using Cosmos.GraphQL.Service.Resolvers; +using GraphQL.Execution; +using Microsoft.Azure.Cosmos; +using Microsoft.Data.SqlClient; +using Newtonsoft.Json.Linq; + +namespace Cosmos.GraphQL.Services +{ + // + // SQLQueryEngine to Execute against SQL Db. + // + public class SQLQueryEngine : IQueryEngine + { + private readonly SQLClientProvider _clientProvider; + private IMetadataStoreProvider _metadataStoreProvider; + + // + // Constructor. + // + public SQLQueryEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + { + _clientProvider = (SQLClientProvider)clientProvider; + _metadataStoreProvider = metadataStoreProvider; + } + + // + // Register the given resolver with this query engine. + // + public void RegisterResolver(GraphQLQueryResolver resolver) + { + _metadataStoreProvider.StoreQueryResolver(resolver); + } + + // + // Execute the given named graphql query on the backend. + // + public JsonDocument Execute(string graphQLQueryName, IDictionary parameters) + { + // TODO: add support for nesting + // TODO: add support for join query against another container + // TODO: add support for TOP and Order-by push-down + + GraphQLQueryResolver resolver = _metadataStoreProvider.GetQueryResolver(graphQLQueryName); + SqlConnection conn = this._clientProvider.getClient(); + + // TODO: + // Open connection + // Edit query = FOR JSON PATH + // Execute Query + // Parse Results into Json and return. + // Will this work with multiple simultaneous calls ? + + JsonDocument jsonDocument = JsonDocument.Parse("{}"); + + return jsonDocument; + } + + // + // Executes the given named graphql query on the backend and expecting a list of Jsons back. + // + public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters) + { + // TODO: add support for nesting + // TODO: add support for join query against another container + // TODO: add support for TOP and Order-by push-down + + var resolver = _metadataStoreProvider.GetQueryResolver(graphQLQueryName); + List resultsAsList = new List(); + return resultsAsList; + } + + // + // Returns if the given query is a list query. + // + public bool IsListQuery(string queryName) + { + return _metadataStoreProvider.GetQueryResolver(queryName).isList; + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index c2f04dab82..0a28669b02 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -44,11 +44,11 @@ public MyDocumentWriter(IDocumentWriter internalWriter) private readonly IDocumentWriter _writer; - private readonly QueryEngine _queryEngine; + private readonly IQueryEngine _queryEngine; private readonly MutationEngine _mutationEngine; private IMetadataStoreProvider _metadataStoreProvider; - public GraphQLService(QueryEngine queryEngine, MutationEngine mutationEngine, CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + public GraphQLService(IQueryEngine queryEngine, MutationEngine mutationEngine, IMetadataStoreProvider metadataStoreProvider) { this._queryEngine = queryEngine; this._mutationEngine = mutationEngine; @@ -187,12 +187,12 @@ public Task Resolve( public void attachQueryResolverToSchema(string queryName) { - if (_queryEngine.isListQuery(queryName)) + if (_queryEngine.IsListQuery(queryName)) { this._schema.Query.GetField(queryName).Resolver = new FuncFieldResolver>(context => { - return _queryEngine.executeList(queryName, context.Arguments); + return _queryEngine.ExecuteList(queryName, context.Arguments); }); } else @@ -200,7 +200,7 @@ public void attachQueryResolverToSchema(string queryName) this._schema.Query.GetField(queryName).Resolver = new FuncFieldResolver(context => { - return _queryEngine.execute(queryName, context.Arguments); + return _queryEngine.Execute(queryName, context.Arguments); }); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 60b60dba8e..29949329bd 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -46,16 +46,17 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton, CosmosClientProvider>(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); break; case DatabaseType.SQL: services.AddSingleton, SQLClientProvider>(); + services.AddSingleton(); break; default: throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); } services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddControllers(); From e89ca564b676e41556111b5abb6124cd458cfbbf Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:17:17 -0700 Subject: [PATCH 04/81] Change Execute to async --- .../Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs | 6 +++--- .../Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs index cf54726c0f..a8c7d6266b 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs @@ -17,7 +17,7 @@ namespace Cosmos.GraphQL.Services { // - // CosmosQueryEngine to Execute against CosmosDb. + // CosmosQueryEngine to ExecuteAsync against CosmosDb. // public class CosmosQueryEngine : IQueryEngine { @@ -42,9 +42,9 @@ public void RegisterResolver(GraphQLQueryResolver resolver) } // - // Execute the given named graphql query on the backend. + // ExecuteAsync the given named graphql query on the backend. // - public JsonDocument Execute(string graphQLQueryName, IDictionary parameters) + public async Task ExecuteAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs index 27b035fc8f..65bf88552f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Text.Json; +using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; using GraphQL.Execution; @@ -18,7 +19,7 @@ public interface IQueryEngine // // Executes the given named graphql query on the backend and expecting a single Json back. // - public JsonDocument Execute(string graphQLQueryName, IDictionary parameters); + public Task ExecuteAsync(string graphQLQueryName, IDictionary parameters); // // Executes the given named graphql query on the backend and expecting a list of Jsons back. From b517924991d6f9c22ac37ebf18c100f79c72f833 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:18:15 -0700 Subject: [PATCH 05/81] Use DbConnectionService directly --- .../Cosmos.GraphQL.Service/configurations/SQLCredentials.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs index 1240c4c8c1..f7a777fe5c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs @@ -8,5 +8,6 @@ namespace Cosmos.GraphQL.Service.configurations public class SQLCredentials : IDatabaseCredentials { public string ConnectionString { get; set; } + public string Server { get; set; } } } From 5dcf40236c0d75c5745e503b39c4af6098347f39 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:18:52 -0700 Subject: [PATCH 06/81] Use QueryExecutor to execute the query --- .../Resolvers/SQLQueryEngine.cs | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index 27ce92d813..71a125f7f5 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data.Common; using System.Configuration; using System.Reflection; using System.Text.Json; @@ -10,25 +11,28 @@ using GraphQL.Execution; using Microsoft.Azure.Cosmos; using Microsoft.Data.SqlClient; +using Microsoft.Sql.Rest.QueryHandler; using Newtonsoft.Json.Linq; namespace Cosmos.GraphQL.Services { // - // SQLQueryEngine to Execute against SQL Db. + // SQLQueryEngine to ExecuteAsync against SQL Db. // public class SQLQueryEngine : IQueryEngine { - private readonly SQLClientProvider _clientProvider; private IMetadataStoreProvider _metadataStoreProvider; + private readonly IQueryExecutor _queryExecutor; + + private const string x_ForJsonSuffix = " FOR JSON PATH, ROOT('data');"; // // Constructor. // - public SQLQueryEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + public SQLQueryEngine(IMetadataStoreProvider metadataStoreProvider, IQueryExecutor queryExecutor) { - _clientProvider = (SQLClientProvider)clientProvider; _metadataStoreProvider = metadataStoreProvider; + _queryExecutor = queryExecutor; } // @@ -36,29 +40,47 @@ public SQLQueryEngine(IClientProvider clientProvider, IMetadataSt // public void RegisterResolver(GraphQLQueryResolver resolver) { - _metadataStoreProvider.StoreQueryResolver(resolver); + // Registration of Resolvers is already done at startup. + // _metadataStoreProvider.StoreQueryResolver(resolver); } // - // Execute the given named graphql query on the backend. + // ExecuteAsync the given named graphql query on the backend. // - public JsonDocument Execute(string graphQLQueryName, IDictionary parameters) + public async Task ExecuteAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting - // TODO: add support for join query against another container + // TODO: add support for join query against another table // TODO: add support for TOP and Order-by push-down GraphQLQueryResolver resolver = _metadataStoreProvider.GetQueryResolver(graphQLQueryName); - SqlConnection conn = this._clientProvider.getClient(); + JsonDocument jsonDocument = JsonDocument.Parse("{ }"); + try + { + // Edit query to add FOR JSON PATH + // + string queryText = resolver.parametrizedQuery + x_ForJsonSuffix; - // TODO: - // Open connection - // Edit query = FOR JSON PATH - // Execute Query - // Parse Results into Json and return. - // Will this work with multiple simultaneous calls ? + // Open connection and execute query using _queryExecutor + // + DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName); - JsonDocument jsonDocument = JsonDocument.Parse("{}"); + // Parse Results into Json and return + // TODO: Is this sufficient for multiple rows in data ? + // + if (dbDataReader.FieldCount > 0) + { + jsonDocument = JsonDocument.Parse(dbDataReader.GetString(0)); + } + else + { + Console.WriteLine("Did not return enough columns in the JSON result."); + } + } + catch (SystemException ex) + { + Console.WriteLine("Caught an exception: " + ex.Message); + } return jsonDocument; } From 1915dd74a8bdebaee86cbe8926dd75ab5c080b10 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:21:31 -0700 Subject: [PATCH 07/81] Use DbConnectionService needing Server --- .../Resolvers/SQLClientProvider.cs | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs index c55ae5f7e1..b1d71fece5 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs @@ -1,36 +1,20 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Data.SqlClient; -using Cosmos.GraphQL.Service.configurations; +using Microsoft.Sql.Rest.Utils; namespace Cosmos.GraphQL.Service.Resolvers { - public class SQLClientProvider: IClientProvider + public class SQLClientProvider: IClientProvider { - private static SqlConnection _sqlConnection; - private static readonly object syncLock = new object(); + private static DbConnectionService _sqlConnectionService; - private void init() + public SQLClientProvider(IDbConnectionService dbConnectionService) { - _sqlConnection = new SqlConnection(ConfigurationProvider.getInstance().Creds.ConnectionString); + _sqlConnectionService = (DbConnectionService)dbConnectionService; } - public SqlConnection getClient() + public DbConnectionService getClient() { - if (_sqlConnection == null) - { - lock (syncLock) - { - if (_sqlConnection == null) - { - init(); - } - } - } - - return _sqlConnection; + return _sqlConnectionService; } } } From 7179a90d8438eb12f57547fc534a87bfb349ada5 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:24:12 -0700 Subject: [PATCH 08/81] Add required services for SQL Database type --- .../Cosmos.GraphQL.Service/Startup.cs | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 29949329bd..b51cf6715b 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -1,12 +1,15 @@ +using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Resolvers; using Cosmos.GraphQL.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Azure.Cosmos; -using Microsoft.Data.SqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Sql.Rest.QueryHandler; +using Microsoft.Sql.Rest.Utils; using System; namespace Cosmos.GraphQL.Service @@ -30,33 +33,39 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - if(Configuration.GetValue("DatabaseConnection:DatabaseType") is null) + if(Configuration.GetValue("DatabaseConnection2:DatabaseType") is null) { throw new NotSupportedException(String.Format("The configuration file is invalid and does not *contain* the DatabaseType key.")); } - if (!Enum.TryParse(Configuration.GetValue("DatabaseConnection:DatabaseType"), out DatabaseType dbType)) + if (!Enum.TryParse(Configuration.GetValue("DatabaseConnection2:DatabaseType"), out DatabaseType dbType)) { throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); } - + switch (dbType) { case DatabaseType.COSMOS: services.AddSingleton, CosmosClientProvider>(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); break; case DatabaseType.SQL: - services.AddSingleton, SQLClientProvider>(); + SQLCredentials creds = (SQLCredentials)configurations.ConfigurationProvider.getInstance().Creds; + services.AddSingleton(provider => + new DbConnectionService(provider.GetService(), + creds.Server)); + services.AddSingleton, SQLClientProvider>(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); break; default: throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); } - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddControllers(); From 21b6074aa081e6da3aa6f542157ad8a9f4fce6f9 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:25:57 -0700 Subject: [PATCH 09/81] For SQL, no need to add schema --- .../Services/GraphQLService.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 0a28669b02..26165f705e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -78,7 +78,22 @@ internal async Task ExecuteAsync(String requestBody) { if (this.Schema == null) { - return "{\"error\": \"Schema must be defined first\" }"; + // Attempt to initialize schema from the metadata store provider + // This happens in case of SQL as backend. + // + parseAsync(_metadataStoreProvider.GetGraphQLSchema()); + // If its still null, return error + // + if (this.Schema == null) + { + return "{\"error\": \"Schema must be defined first\" }"; + } + else + { + // Loop through all the queries and attach the resolvers for each query before hand. + // + attachQueryResolverToSchema("characterList"); + } } var request = requestBody.ToInputs(); @@ -200,7 +215,7 @@ public void attachQueryResolverToSchema(string queryName) this._schema.Query.GetField(queryName).Resolver = new FuncFieldResolver(context => { - return _queryEngine.Execute(queryName, context.Arguments); + return _queryEngine.ExecuteAsync(queryName, context.Arguments).Result; }); } } From da7e7d10888d113062ad1173b9faf997bd115017 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:26:15 -0700 Subject: [PATCH 10/81] Use of server property --- .../Cosmos.GraphQL.Service/appsettings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index 478f1acc96..f04219cfdc 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -20,8 +20,8 @@ "DatabaseConnection2": { "DatabaseType": "SQL", "Credentials": { - "ConnectionString": "" - + "ConnectionString": "", + "Server" : "localhost" } } } From 05076c6fd83d0433767adb7d27edbe049d6337fc Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:27:19 -0700 Subject: [PATCH 11/81] Need to fix Mutation Engine but this is for now to make it work for SQL --- .../Resolvers/MutationEngine.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index 13c0097c20..cdfc708e7e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -14,18 +14,19 @@ using Microsoft.CodeAnalysis.Scripting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Microsoft.Sql.Rest.Utils; namespace Cosmos.GraphQL.Service.Resolvers { public class MutationEngine { - private readonly CosmosClientProvider _clientProvider; + private readonly IClientProvider _clientProvider; private readonly IMetadataStoreProvider _metadataStoreProvider; private ScriptOptions scriptOptions; - public MutationEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + public MutationEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; @@ -54,12 +55,12 @@ private JObject execute(IDictionary parameters, MutationR jObject.Add("id", Guid.NewGuid().ToString()); } - var container = _clientProvider.getCosmosClient().GetDatabase(resolver.databaseName) - .GetContainer(resolver.containerName); + //var container = _clientProvider.getClient().GetDatabase(resolver.databaseName) + // .GetContainer(resolver.containerName); // TODO: check insertion type - JObject res = container.UpsertItemAsync(jObject).Result.Resource; - return res; + // JObject res = container.UpsertItemAsync(jObject).Result.Resource; + return jObject; } public async Task execute(string graphQLMutationName, From 794638cfa140e29eedc466f790dc749d37879778 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:27:43 -0700 Subject: [PATCH 12/81] Config change to work with SQL --- .../configurations/ConfigurationProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index 47d970e750..4c22b162a6 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -34,7 +34,7 @@ private void init() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile("AppSettings.json").Build(); - var section = config.GetSection("DatabaseConnection"); + var section = config.GetSection("DatabaseConnection2"); if (!Enum.TryParse(section["DatabaseType"], out DatabaseType dbType)) { throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); From 339439d201d6aa87432d59c25d3fb47b4e2730e7 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:29:35 -0700 Subject: [PATCH 13/81] Try config json and filemetadata --- .../Services/FileMetadataStoreProvider.cs | 4 ++-- .../Cosmos.GraphQL.Service/config.json | 20 ++++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs index ed7e820192..947bab5df8 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs @@ -32,7 +32,7 @@ private void init() _resolvers = new Dictionary(); foreach(JsonElement resolver in resolversListJson.EnumerateArray()) { - _resolvers.Add(resolver.GetProperty("name").ToString(), resolver.ToString()); + _resolvers.Add(resolver.GetProperty("id").ToString(), resolver.ToString()); } } @@ -68,7 +68,7 @@ public GraphQLQueryResolver GetQueryResolver(string name) public void StoreGraphQLSchema(string schema) { - throw new NotImplementedException(); + // no op } public void StoreMutationResolver(MutationResolver mutationResolver) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 33967ccc03..99883ff041 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -1,18 +1,14 @@ { - "GraphQLSchema": "{ \r\n type Query { \r\n bookById (id: @id): Book \r\n } \r\n\r\n type Book { \r\n id : ID!, \r\n title : String!, \r\n numberOfPages: Int, \r\n author: Author\r\n } \r\n\r\n type Author { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String, \r\n address: String, \r\n } \r\n\r\n type Mutation { \r\n addBook( \r\n id : ID!, \r\n title: String!, \r\n numberOfPages: Int, \r\n author : { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String \r\n address: String \r\n } \r\n ): Book \r\n } \r\n} ", + "GraphQLSchema": "{ schema {\r\n query: Query \r\n }\r\n type Query { \r\n characterList: characters \r\n } \r\n\r\n type characters { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: int, \r\n primaryFunction: String \r\n} \r\n}", "Resolvers": [ { - "engine": "SQL", - "name": "bookById", - "database": "", - "container": "", - "parametrizedQuery": "SELECT * from r WHERE r.id = @arg.id", - "operationType": "READ_ITEM" - }, - { - "name": "authorById" + "engine": "SQL", + "id": "characterList", + "databaseName": "StarWars", + "isList" : false, + "container": "", + "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters", + "operationType": "READ_ITEM" } ] } - - From 7b85dc579e27312017dff057e6f91393ef66ed33 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 9 Sep 2021 14:29:49 -0700 Subject: [PATCH 14/81] use SqlRest --- .../Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index 6c33240177..d31a42aad2 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -18,4 +18,8 @@ + + + + From d45929582067b9bb32b24e64bd3aaf559674be25 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 2 Sep 2021 19:28:52 +0000 Subject: [PATCH 15/81] Merged PR 649012: Generalize ClientProvider, ConfigurationProvider, and DB Connection Configuration Introducing changes to abstract out DatabaseCredentials, ClientProvider with changes to accomodate this in the ConfigurationProvider and Startup classes. Configuration files updated to accommodate interpreting database type during startup and configuration initialization. # Why this change is needed The first step in extending the POC to be compatible with SQL Database is through generalizing the database credentials classes, the clientproviders, and configuration provider. # How Describe how the change works. ##Startup class - Infers DatabaseType from _appsettings.json_ . The DatabaseType determines the implementation of _IClientProvider_. ##IDatabaseCredentials interface - created to capture overlap between SQL and Cosmos connections which is the ConnectionString. I chose _ConnectionString_ over _EndpointURL_ as the interface member because connectionstring is a superset of endpointurl for both database types. Can leave database specific details such as username, password, access keys to the specific class implementations. Future work to accommodate Postgres TBD because Postgres requires connectionstring to be built. ##IClientProvider interface - Created to capture overlap between clients. ClientProvider class must implement getClient(). Client initialization adhering to initial Cosmos POC model of Singletons. - Generic interface types expected: - SQL: SqlConnection - Cosmos: CosmosClient - Current PR utilizes Cosmos implementation of Singleton for connection. I want to get E2E working here first before optimizing further for collection of connections, which is implemented in SQLREST project. ##ConfigurationProvider - On initialization, the instance (Singleton enforced) reads from _appsettings.json_ to determine which DbCredential to create. ##Appsettings.json - Added proposed new db configuration structure to be read in by the configuration provider and startup class. The config specifies the database type to instruct which credentials class to implement (SQL/Cosmos). - Specific credentials classes created to accommodate future need to build the connection string. ``` json "DatabaseConnection": { "DatabaseType": "COSMOS", "Credentials": { "ServerEndpointUrl": "", "AuthorizationKey": "", "Container": "", "Database": "", "ConnectionString": "" } } ``` # Test Integration testing by calling REST endpoint to add and query schema. Addition test class written for ClientProvider to validate opening SQL connection succeeds. # Checklist - [X] Build and run test locally. - [ ] Check code coverage report and make sure that there are test coverage for your change. - [X] Link work item to this change. - [ ] Update the design/functional docs. added README to the section on testing Related work items: #1333552 --- .../Cosmos.GraphQL.Service.Tests.csproj | 4 +- .../SqlClientProviderTests.cs | 37 ++++++++++++++++++ .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 2 +- .../Cosmos.GraphQL.Service.csproj | 3 ++ .../Resolvers/CosmosClientProvider.cs | 20 ++++------ .../Resolvers/IClientProvider.cs | 16 ++++++++ .../Resolvers/MutationEngine.cs | 11 ------ .../Resolvers/SQLClientProvider.cs | 36 ++++++++++++++++++ .../Cosmos.GraphQL.Service/Startup.cs | 38 ++++++++++++++++--- .../Cosmos.GraphQL.Service/appsettings.json | 19 +++++++++- .../Cosmos.GraphQL.Service/config.json | 11 ------ .../configurations/ConfigurationProvider.cs | 38 ++++++++++--------- .../configurations/CosmosCredentials.cs | 15 ++++++++ .../configurations/IConfigurationProvider.cs | 15 ++++++++ .../configurations/IDatabaseCredentials.cs | 20 ++++++++++ .../configurations/SQLCredentials.cs | 12 ++++++ 16 files changed, 236 insertions(+), 61 deletions(-) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj index 858e39d0a5..a67bd14764 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/Cosmos.GraphQL.Service.Tests.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs new file mode 100644 index 0000000000..af037fa819 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs @@ -0,0 +1,37 @@ +using Cosmos.GraphQL.Service.Resolvers; +using Microsoft.Data.SqlClient; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Data; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Tests +{ + [TestClass] + public class SqlClientProviderTests + { + private IClientProvider _clientProvider; + public SqlClientProviderTests() + { + _clientProvider = new SQLClientProvider(); + } + /// + /// Ensure a connection is successfully opened within the [Database]ClientProvider, + /// given a valid connection string. + /// + /// + [TestMethod] + public void TestOpenConnection() + { + SqlConnection connection = _clientProvider.getClient(); + connection.Open(); + Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); + Console.WriteLine("State: {0}", connection.State); + Assert.IsTrue(connection.State.Equals(ConnectionState.Open)); + connection.Dispose(); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index e025ff544f..6b09650684 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -36,7 +36,7 @@ private void Init() clientProvider = new CosmosClientProvider(); string uid = Guid.NewGuid().ToString(); dynamic sourceItem = TestHelper.GetItem(uid); - clientProvider.getCosmosContainer().CreateItemAsync(sourceItem, new PartitionKey(uid)); // TODO: Make it sync + //clientProvider.getCosmosContainer().CreateItemAsync(sourceItem, new PartitionKey(uid)); // TODO: Make it sync metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index 910a6afd80..6c33240177 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -10,8 +10,11 @@ + + + diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs index 3496a9222f..93447d871d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs @@ -5,19 +5,22 @@ namespace Cosmos.GraphQL.Service.Resolvers { - public class CosmosClientProvider + public class CosmosClientProvider : IClientProvider { private static CosmosClient _cosmosClient; private static readonly object syncLock = new object(); private static void init() { - var cred = ConfigurationProvider.getInstance().cred; + var cred = ConfigurationProvider.getInstance().Creds; + _cosmosClient = new CosmosClientBuilder(cred.ConnectionString).WithContentResponseOnWrite(true).Build(); + } - _cosmosClient = new CosmosClientBuilder(cred.EndpointUrl, cred.AuthorizationKey).WithContentResponseOnWrite(true).Build(); - // _cosmosClient = new CosmosClient(cred.EndpointUrl, cred.AuthorizationKey). + public CosmosClient getClient() + { + return getCosmosClient(); } - + public CosmosClient getCosmosClient() { if (_cosmosClient == null) @@ -33,13 +36,6 @@ public CosmosClient getCosmosClient() return _cosmosClient; } - - public Container getCosmosContainer() - { - return getCosmosClient().GetDatabase(ConfigurationProvider.getInstance().databaseName) - .GetContainer(ConfigurationProvider.getInstance().containerName); - - } } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs new file mode 100644 index 0000000000..0052d448c7 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Interface representing database clients with retrieval method. + /// + /// Type of database client (i.e. SqlConnection or CosmosClient) + public interface IClientProvider + { + public T getClient(); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index bc51c77aba..e717dfd802 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -129,16 +129,5 @@ private async void executeInit() "Newtonsoft.Json", "Newtonsoft.Json.Linq"); } - - private async Task> runAndInitializedScript() - { - executeInit(); - - Globals.Initialize(_clientProvider.getCosmosContainer()); - Globals global = new Globals(); - - return await CSharpScript.RunAsync("Container container = Cosmos.Container;", this.scriptOptions, - globals: global); - } } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs new file mode 100644 index 0000000000..c55ae5f7e1 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; +using Cosmos.GraphQL.Service.configurations; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + public class SQLClientProvider: IClientProvider + { + private static SqlConnection _sqlConnection; + private static readonly object syncLock = new object(); + + private void init() + { + _sqlConnection = new SqlConnection(ConfigurationProvider.getInstance().Creds.ConnectionString); + } + + public SqlConnection getClient() + { + if (_sqlConnection == null) + { + lock (syncLock) + { + if (_sqlConnection == null) + { + init(); + } + } + } + + return _sqlConnection; + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 98192bbdeb..b4a958ef7c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -2,13 +2,22 @@ using Cosmos.GraphQL.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Azure.Cosmos; +using Microsoft.Data.SqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; - +using System; namespace Cosmos.GraphQL.Service { + enum DatabaseType + { + SQL, + COSMOS, + POSTGRES, + } + public class Startup { public Startup(IConfiguration configuration) @@ -21,15 +30,34 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + if(Configuration.GetValue("DatabaseConnection:DatabaseType") is null) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not *contain* the DatabaseType key.")); + } + + if (!Enum.TryParse(Configuration.GetValue("DatabaseConnection:DatabaseType"), out DatabaseType dbType)) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); + } + + switch (dbType) + { + case DatabaseType.COSMOS: + services.AddSingleton, CosmosClientProvider>(); + services.AddSingleton(); + services.AddSingleton(); + break; + case DatabaseType.SQL: + services.AddSingleton, SQLClientProvider>(); + break; + default: + throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); + } - // pass a singleton QueryEngine - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddControllers(); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index d9d9a9bff6..478f1acc96 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -6,5 +6,22 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "DatabaseConnection": { + "DatabaseType": "COSMOS", + "Credentials": { + "ServerEndpointUrl": "", + "AuthorizationKey": "", + "Container": "", + "Database": "", + "ConnectionString": "" + } + }, + "DatabaseConnection2": { + "DatabaseType": "SQL", + "Credentials": { + "ConnectionString": "" + + } + } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json deleted file mode 100644 index 97212bab6d..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "CosmosCredentials" : { - "EndPointUrl": "", - "AuthorizationKey": "" - }, - - "CosmosContainer" : "", - "CosmosDatabase" : "" -} - - diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index 78fd19eb17..47d970e750 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -6,14 +6,10 @@ namespace Cosmos.GraphQL.Service.configurations { public class ConfigurationProvider { - private static ConfigurationProvider instance; + private static ConfigurationProvider instance; private static readonly object lockObject = new object(); + public IDatabaseCredentials Creds { get; private set; } - public CosmosCredentials cred { get; private set; } - public string databaseName { get; private set; } - public string containerName { get; private set; } - - public static ConfigurationProvider getInstance() { if (instance == null) @@ -34,21 +30,27 @@ public static ConfigurationProvider getInstance() private void init() { - var config = new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) - .AddJsonFile("config.json").Build(); + .AddJsonFile("AppSettings.json").Build(); - var section = config.GetSection(nameof(CosmosCredentials)); - cred = section.Get(); - containerName = config.GetValue("CosmosContainer"); - databaseName = config.GetValue("CosmosDatabase"); + var section = config.GetSection("DatabaseConnection"); + if (!Enum.TryParse(section["DatabaseType"], out DatabaseType dbType)) + { + throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); + } + section = section.GetSection("Credentials"); + switch (dbType) + { + case DatabaseType.COSMOS: + Creds = section.Get(); + break; + case DatabaseType.SQL: + Creds = section.Get(); + break; + default: + break; + } } } - - public class CosmosCredentials - { - public string EndpointUrl { get; set; } - public string AuthorizationKey { get; set; } - } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs new file mode 100644 index 0000000000..f349bbbe18 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/CosmosCredentials.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + public class CosmosCredentials : IDatabaseCredentials + { + public string ConnectionString { get; set; } + public string EndpointUrl { get; set; } + public string AuthorizationKey { get; set; } + public string Container { get; set; } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs new file mode 100644 index 0000000000..7f042a0d6d --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + /// + /// Provider for the singleton instance of a connection provider to a specific database + /// + public interface IConfigurationProvider + { + public IConfigurationProvider getInstance(); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs new file mode 100644 index 0000000000..2fd1e89e2f --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IDatabaseCredentials.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + /// + /// This interface defines the common connection field utilized between Cosmos/SQL. + /// Classes that implement this interface can also add their own db specific fields. + /// + public interface IDatabaseCredentials + { + /// + /// ConnectionString represents the minimal info needed to connect to a given database. + /// It is the common factor between Cosmos DB and SQL DB. Pending Postgres. + /// + public string ConnectionString { get; set; } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs new file mode 100644 index 0000000000..1240c4c8c1 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + public class SQLCredentials : IDatabaseCredentials + { + public string ConnectionString { get; set; } + } +} From 83b47a6fcaa298da6bf070c43050aee2cf31274a Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Fri, 3 Sep 2021 18:27:25 +0000 Subject: [PATCH 16/81] Merged PR 654028: Create FileMetadataStoreProvider to read GraphQL config from file #Summary Initial work to create FileMetadataStoreProvider, enables reading JSON config from file. Renamed interface to IMetadataStoreProvider. Sample Config.json for runtime config. Gitignore updated to ignore /vs folder. Added two simple integration tests for new fileprovider. # Why this change is needed The first step in extending the POC to be compatible with SQL Database is through generalizing the database credentials classes, the clientproviders, and configuration provider. # How Describe how the change works. ##IMetadataStoreProvider - Files which had previously referenced the interface as MetadataStoreProvider now reference the renamed interface __IMetadataStoreProvider__ ##FileMetadataStoreProvider - Implemented to act us underlying storage of configuration data assuming that configuration is only read once at startup. In this case, the class constructor is responsible for reading the file, storing the GraphQL schema string and saving the Resolvers as key/value pairs into a collection. The Get() calls are similar to the cachedmetadatastoreprovider where a dictionary is used to keep track of resolvername:resolvervalue. ##config.json - Added simplified skeleton of GraphQL configuration file as agreed on during architecture meetings: 1 file with schema and resolvers embedded ``` json { "GraphQLSchema": "", "Resolvers": [ { "engine": "SQL", "name": "bookById", "database": "", "container": "", "parametrizedQuery": "SELECT * from r WHERE r.id = @arg.id", "operationType": "READ_ITEM" }, { "name": "authorById" } ] } ``` ##.gitignore Updated to not track __vs/__ folders within the project, for sanity. # Test Integration testing done by creating MetadataProviderTests class: - Getting schema from config - Getting resolver from config # Checklist - [X] Build and run test locally. - [X] Check code coverage report and make sure that there are test coverage for your change. - [X] Link work item to this change. - [ ] Update the design/functional docs. added README to the section on testing Related work items: #1333554 --- .gitignore | 4 +- .../MetadataProviderTests.cs | 33 ++++++++ .../SchemaTests.cs | 2 +- .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 2 +- .../Resolvers/MutationEngine.cs | 7 +- .../Resolvers/QueryEngine.cs | 4 +- .../Services/CachedMetadataStoreProvider.cs | 5 +- .../Services/DocumentMetadataStoreProvider.cs | 2 +- .../Services/FileMetadataStoreProvider.cs | 84 +++++++++++++++++++ .../Services/GraphQLService.cs | 4 +- ...eProvider.cs => IMetadataStoreProvider.cs} | 2 +- .../Cosmos.GraphQL.Service/Startup.cs | 2 +- .../Cosmos.GraphQL.Service/config.json | 18 ++++ 13 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/{MetadataStoreProvider.cs => IMetadataStoreProvider.cs} (95%) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json diff --git a/.gitignore b/.gitignore index bab11274cb..077b9433cb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,7 @@ Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/bin/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/obj/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/.idea/* - */.idea/* + +# Visual Studio 2015 cache/options directory +.vs/ \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs new file mode 100644 index 0000000000..b6b1d31c94 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MetadataProviderTests.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Cosmos.GraphQL.Services; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Cosmos.GraphQL.Service.Tests +{ + [TestClass] + public class MetadataProviderTests + { + IMetadataStoreProvider _fileProvider; + + public MetadataProviderTests() + { + _fileProvider = new FileMetadataStoreProvider(); + } + + [TestMethod] + public void TestGetSchema() + { + Assert.IsNotNull(_fileProvider.GetGraphQLSchema()); + } + + [TestMethod] + public void TestGetResolver() + { + Assert.IsNotNull(_fileProvider.GetQueryResolver("authorById")); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index b6936d04dc..91b21ed28c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -19,7 +19,7 @@ public class SchemaTests public async Task TestAddSchemaAsync() { CosmosClientProvider clientProvider = new CosmosClientProvider(); - MetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); + IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); QueryEngine queryEngine = new QueryEngine(clientProvider, metadataStoreProvider); MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, clientProvider, metadataStoreProvider); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index 6b09650684..c842c5f525 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -20,7 +20,7 @@ public class TestBase { internal GraphQLService graphQLService; internal CosmosClientProvider clientProvider; - internal MetadataStoreProvider metadataStoreProvider; + internal IMetadataStoreProvider metadataStoreProvider; internal QueryEngine queryEngine; internal MutationEngine mutationEngine; internal GraphQLController controller; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index e717dfd802..13c0097c20 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -21,17 +21,14 @@ public class MutationEngine { private readonly CosmosClientProvider _clientProvider; - private readonly MetadataStoreProvider _metadataStoreProvider; + private readonly IMetadataStoreProvider _metadataStoreProvider; private ScriptOptions scriptOptions; - public MutationEngine(CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public MutationEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; - - // - // new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider.getCosmosClient())); } public void registerResolver(MutationResolver resolver) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs index d92dd93673..357a5ce435 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryEngine.cs @@ -21,9 +21,9 @@ public class QueryEngine private readonly CosmosClientProvider _clientProvider; private ScriptOptions scriptOptions; - private MetadataStoreProvider _metadataStoreProvider; + private IMetadataStoreProvider _metadataStoreProvider; - public QueryEngine(CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public QueryEngine(CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs index 16a58eaae0..be533a23e0 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/CachedMetadataStoreProvider.cs @@ -18,14 +18,13 @@ public MetadataStoreException(string message, Exception inner) } } - public class CachedMetadataStoreProvider : MetadataStoreProvider + public class CachedMetadataStoreProvider : IMetadataStoreProvider { - private readonly MetadataStoreProvider _storeProvider; + private readonly IMetadataStoreProvider _storeProvider; private string _schema; private ConcurrentDictionary _mutationResolvers = new ConcurrentDictionary(); private ConcurrentDictionary _queryResolvers = new ConcurrentDictionary(); - public CachedMetadataStoreProvider(DocumentMetadataStoreProvider storeProvider) { this._storeProvider = storeProvider; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs index 5b6fdf2f72..b8315f37b0 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/DocumentMetadataStoreProvider.cs @@ -7,7 +7,7 @@ namespace Cosmos.GraphQL.Services { - public class DocumentMetadataStoreProvider : MetadataStoreProvider + public class DocumentMetadataStoreProvider : IMetadataStoreProvider { private readonly CosmosClient client; private readonly string systemDatabaseName = "_systemGraphQL"; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs new file mode 100644 index 0000000000..ed7e820192 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs @@ -0,0 +1,84 @@ +using Cosmos.GraphQL.Service.Models; +using Cosmos.GraphQL.Services; +using System; +using System.IO; +using System.Text.Json; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service +{ + public class FileMetadataStoreProvider : IMetadataStoreProvider + { + private string _graphQLSchema; + private IDictionary _resolvers; + + public FileMetadataStoreProvider() + { + init(); + } + + private void init() + { + string jsonString = File.ReadAllText(@"config.json"); + + using (JsonDocument document = JsonDocument.Parse(jsonString)) + { + JsonElement root = document.RootElement; + JsonElement schema = root.GetProperty("GraphQLSchema"); + _graphQLSchema = schema.GetString(); + JsonElement resolversListJson = root.GetProperty("Resolvers"); + _resolvers = new Dictionary(); + foreach(JsonElement resolver in resolversListJson.EnumerateArray()) + { + _resolvers.Add(resolver.GetProperty("name").ToString(), resolver.ToString()); + } + } + + } + /// + /// Reads generated JSON configuration file with GraphQL Schema + /// + /// GraphQL schema as string + public string GetGraphQLSchema() + { + return _graphQLSchema; + } + + public MutationResolver GetMutationResolver(string name) + { + if (!_resolvers.TryGetValue(name, out string resolver)) + { + throw new KeyNotFoundException("Mutation Resolver does not exist."); + } + + return JsonSerializer.Deserialize(resolver); + } + + public GraphQLQueryResolver GetQueryResolver(string name) + { + if (!_resolvers.TryGetValue(name, out string resolver)) + { + throw new KeyNotFoundException("Query Resolver does not exist."); + } + + return JsonSerializer.Deserialize(resolver); + } + + public void StoreGraphQLSchema(string schema) + { + throw new NotImplementedException(); + } + + public void StoreMutationResolver(MutationResolver mutationResolver) + { + throw new NotImplementedException(); + } + + public void StoreQueryResolver(GraphQLQueryResolver mutationResolver) + { + throw new NotImplementedException(); + } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 9ac49771af..c2f04dab82 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -46,9 +46,9 @@ public MyDocumentWriter(IDocumentWriter internalWriter) private readonly QueryEngine _queryEngine; private readonly MutationEngine _mutationEngine; - private MetadataStoreProvider _metadataStoreProvider; + private IMetadataStoreProvider _metadataStoreProvider; - public GraphQLService(QueryEngine queryEngine, MutationEngine mutationEngine, CosmosClientProvider clientProvider, MetadataStoreProvider metadataStoreProvider) + public GraphQLService(QueryEngine queryEngine, MutationEngine mutationEngine, CosmosClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { this._queryEngine = queryEngine; this._mutationEngine = mutationEngine; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs similarity index 95% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs index 2db1babaad..adc451bd95 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/MetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/IMetadataStoreProvider.cs @@ -19,7 +19,7 @@ namespace Cosmos.GraphQL.Services { - public interface MetadataStoreProvider + public interface IMetadataStoreProvider { void StoreGraphQLSchema(string schema); string GetGraphQLSchema(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index b4a958ef7c..60b60dba8e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -54,7 +54,7 @@ public void ConfigureServices(IServiceCollection services) throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); } - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json new file mode 100644 index 0000000000..33967ccc03 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -0,0 +1,18 @@ +{ + "GraphQLSchema": "{ \r\n type Query { \r\n bookById (id: @id): Book \r\n } \r\n\r\n type Book { \r\n id : ID!, \r\n title : String!, \r\n numberOfPages: Int, \r\n author: Author\r\n } \r\n\r\n type Author { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String, \r\n address: String, \r\n } \r\n\r\n type Mutation { \r\n addBook( \r\n id : ID!, \r\n title: String!, \r\n numberOfPages: Int, \r\n author : { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String \r\n address: String \r\n } \r\n ): Book \r\n } \r\n} ", + "Resolvers": [ + { + "engine": "SQL", + "name": "bookById", + "database": "", + "container": "", + "parametrizedQuery": "SELECT * from r WHERE r.id = @arg.id", + "operationType": "READ_ITEM" + }, + { + "name": "authorById" + } + ] +} + + From f9229e608c9316cc2b1e6adc4733ca5f57403a69 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Fri, 10 Sep 2021 09:14:51 -0700 Subject: [PATCH 17/81] Cherrypick FileMetadataProvider and SQL Client Provider + add classdiagram files for visualizing code. --- .../Class Diagrams/CosmosClientProvider.cd | 102 ++++++++++++++++++ .../Class Diagrams/SQLClientProvider.cd | 89 +++++++++++++++ .../Cosmos.GraphQL.Service.csproj | 3 + 3 files changed, 194 insertions(+) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd new file mode 100644 index 0000000000..54d55b6b66 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd @@ -0,0 +1,102 @@ + + + + + + AEAAAQAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAAAAAAAA= + Resolvers\CosmosClientProvider.cs + + + + + + + + + + AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= + configurations\ConfigurationProvider.cs + + + + + + + + + DAAABAAAEAAACAAAAAAAAkAAAAAgAAAAABAABACAAAA= + Services\DocumentMetadataStoreProvider.cs + + + + + + + + + + + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= + Services\GraphQLService.cs + + + + + + + + + + AAAAAAAAAAgAAAAAAAAMAAAQEAAABgAAAAAAAAAAAAA= + Resolvers\QueryEngine.cs + + + + + + + + + AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Resolvers\IClientProvider.cs + + + + + + CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= + Services\IMetadataStoreProvider.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= + configurations\IDatabaseCredentials.cs + + + + \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd new file mode 100644 index 0000000000..4cb0df1fc0 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd @@ -0,0 +1,89 @@ + + + + + + AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= + configurations\ConfigurationProvider.cs + + + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= + configurations\SQLCredentials.cs + + + + + + + gEAAAAAAAAAAAAAAAAAAAAgAAAAAAAIAAAAAAAAAAAA= + Resolvers\SQLClientProvider.cs + + + + + + + CAAAJAAAEAAAAAAAAAAAAkACAAAAAAIAABAAAAAAAAA= + Services\FileMetadataStoreProvider.cs + + + + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= + Services\GraphQLService.cs + + + + + + + + + AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Resolvers\IClientProvider.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= + configurations\IDatabaseCredentials.cs + + + + + + CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= + Services\IMetadataStoreProvider.cs + + + + \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index 6c33240177..b8c80d417d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -17,5 +17,8 @@ + + + From 2453c0f82fbf3d49b8ad88d99628c269f016e95a Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Fri, 10 Sep 2021 09:23:06 -0700 Subject: [PATCH 18/81] Removed unused IConfigurationProvider file --- .../configurations/IConfigurationProvider.cs | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs deleted file mode 100644 index 7f042a0d6d..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.configurations -{ - /// - /// Provider for the singleton instance of a connection provider to a specific database - /// - public interface IConfigurationProvider - { - public IConfigurationProvider getInstance(); - } -} From 6b41512ce9a7bba2bf44c2caf5a5506429035873 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 10 Sep 2021 19:25:56 -0700 Subject: [PATCH 19/81] Make ExecuteAsList async as well --- .../Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs | 6 +++--- .../Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs index a8c7d6266b..ff4273f75c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs @@ -62,7 +62,7 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar } } - var firstPage = container.GetItemQueryIterator(querySpec).ReadNextAsync().Result; + var firstPage = await container.GetItemQueryIterator(querySpec).ReadNextAsync(); JObject firstItem = null; @@ -77,7 +77,7 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar return jsonDocument; } - public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters) + public async Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container @@ -95,7 +95,7 @@ public IEnumerable ExecuteList(string graphQLQueryName, IDictionar } } - var firstPage = container.GetItemQueryIterator(querySpec).ReadNextAsync().Result; + var firstPage = await container.GetItemQueryIterator(querySpec).ReadNextAsync(); JObject firstItem = null; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs index 65bf88552f..de7cf8bd5e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs @@ -24,7 +24,7 @@ public interface IQueryEngine // // Executes the given named graphql query on the backend and expecting a list of Jsons back. // - public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters); + public Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters); // // Returns if the given query is a list query. From 1296a711f8d7234cb8d8dc2075501968a4e6c6a4 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 10 Sep 2021 19:26:38 -0700 Subject: [PATCH 20/81] Support multiple query fields --- .../Services/GraphQLService.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 26165f705e..71a4186035 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -92,7 +92,10 @@ internal async Task ExecuteAsync(String requestBody) { // Loop through all the queries and attach the resolvers for each query before hand. // - attachQueryResolverToSchema("characterList"); + foreach (FieldType queryField in Schema.Query.Fields) + { + attachQueryResolverToSchema(queryField.Name); + } } } @@ -148,7 +151,7 @@ object getResolvedValue(JsonElement rootElement, String typeName, IEnumerable>(context => { - return _queryEngine.ExecuteList(queryName, context.Arguments); + return _queryEngine.ExecuteListAsync(queryName, context.Arguments).Result; }); } else From 4c378115cd478368025e6982c86b3a3614c5e4b5 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 10 Sep 2021 19:27:54 -0700 Subject: [PATCH 21/81] Add ExecuteAsList separately --- .../Resolvers/SQLQueryEngine.cs | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index 71a125f7f5..6517e60228 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -24,7 +24,8 @@ public class SQLQueryEngine : IQueryEngine private IMetadataStoreProvider _metadataStoreProvider; private readonly IQueryExecutor _queryExecutor; - private const string x_ForJsonSuffix = " FOR JSON PATH, ROOT('data');"; + private const string x_ForJsonSuffix = " FOR JSON PATH, INCLUDE_NULL_VALUES"; + private const string x_WithoutArrayWrapperSuffix = "WITHOUT_ARRAY_WRAPPER"; // // Constructor. @@ -59,22 +60,21 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar { // Edit query to add FOR JSON PATH // - string queryText = resolver.parametrizedQuery + x_ForJsonSuffix; + string queryText = resolver.parametrizedQuery + x_ForJsonSuffix + "," + x_WithoutArrayWrapperSuffix + ";"; // Open connection and execute query using _queryExecutor // DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName); // Parse Results into Json and return - // TODO: Is this sufficient for multiple rows in data ? // - if (dbDataReader.FieldCount > 0) + if (await dbDataReader.ReadAsync()) { jsonDocument = JsonDocument.Parse(dbDataReader.GetString(0)); } else { - Console.WriteLine("Did not return enough columns in the JSON result."); + Console.WriteLine("Did not return enough rows in the JSON result."); } } catch (SystemException ex) @@ -88,14 +88,40 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar // // Executes the given named graphql query on the backend and expecting a list of Jsons back. // - public IEnumerable ExecuteList(string graphQLQueryName, IDictionary parameters) + public async Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container // TODO: add support for TOP and Order-by push-down - var resolver = _metadataStoreProvider.GetQueryResolver(graphQLQueryName); + GraphQLQueryResolver resolver = _metadataStoreProvider.GetQueryResolver(graphQLQueryName); List resultsAsList = new List(); + try + { + // Edit query to add FOR JSON PATH + // + string queryText = resolver.parametrizedQuery + x_ForJsonSuffix + ";"; + + // Open connection and execute query using _queryExecutor + // + DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName); + + // Deserialize results into list of JsonDocuments and return + // + if (await dbDataReader.ReadAsync()) + { + resultsAsList = JsonSerializer.Deserialize>(dbDataReader.GetString(0)); + } + else + { + Console.WriteLine("Did not return enough rows in the JSON result."); + } + } + catch (SystemException ex) + { + Console.WriteLine("Caught an exception: " + ex.Message); + } + return resultsAsList; } From 237588b270ea4d56084a2a5de38644d083f0144a Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 10 Sep 2021 19:28:43 -0700 Subject: [PATCH 22/81] Fix schema (no enclosing brackets) and add another query --- .../Cosmos.GraphQL.Service/config.json | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 99883ff041..3c6069b94b 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -1,14 +1,19 @@ { - "GraphQLSchema": "{ schema {\r\n query: Query \r\n }\r\n type Query { \r\n characterList: characters \r\n } \r\n\r\n type characters { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: int, \r\n primaryFunction: String \r\n} \r\n}", + "GraphQLSchema": "type Query { \r\n topOneCharacter: characters \r\n characterList : [characters] \r\n } \r\n\r\n type characters { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: Int, \r\n primaryFunction: String \r\n}", "Resolvers": [ + { + "engine": "SQL", + "id": "topOneCharacter", + "databaseName": "StarWars", + "isList": false, + "parametrizedQuery": "SELECT TOP 1 [id], [name], [type], [homePlanet], [primaryFunction] FROM characters" + }, { "engine": "SQL", "id": "characterList", "databaseName": "StarWars", - "isList" : false, - "container": "", - "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters", - "operationType": "READ_ITEM" + "isList": true, + "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters" } ] } From e82e169112d969245422095f5b6426ccad10ff82 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Mon, 13 Sep 2021 12:57:08 -0700 Subject: [PATCH 23/81] InitializeSchemaAndAttachResolvers --- .../Services/GraphQLService.cs | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 71a4186035..ef52412835 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -54,6 +54,8 @@ public GraphQLService(IQueryEngine queryEngine, MutationEngine mutationEngine, I this._mutationEngine = mutationEngine; this._metadataStoreProvider = metadataStoreProvider; this._writer = new MyDocumentWriter(this._writerPure); + + InitializeSchemaAndResolvers(); } public void parseAsync(String data) @@ -78,25 +80,7 @@ internal async Task ExecuteAsync(String requestBody) { if (this.Schema == null) { - // Attempt to initialize schema from the metadata store provider - // This happens in case of SQL as backend. - // - parseAsync(_metadataStoreProvider.GetGraphQLSchema()); - // If its still null, return error - // - if (this.Schema == null) - { - return "{\"error\": \"Schema must be defined first\" }"; - } - else - { - // Loop through all the queries and attach the resolvers for each query before hand. - // - foreach (FieldType queryField in Schema.Query.Fields) - { - attachQueryResolverToSchema(queryField.Name); - } - } + return "{\"error\": \"Schema must be defined first\" }"; } var request = requestBody.ToInputs(); @@ -245,5 +229,31 @@ private static bool IsIntrospectionPath(IEnumerable path) return false; } + /// + /// If the metastore provider is able to get the graphql schema, + /// this function parses it and attaches resolvers to the various query fields. + /// + private void InitializeSchemaAndResolvers() + { + // Attempt to get schema from the metadata store. + // + string graphqlSchema = _metadataStoreProvider.GetGraphQLSchema(); + + // If the schema is available, parse it and attach resolvers. + // + if (!string.IsNullOrEmpty(graphqlSchema)) + { + parseAsync(graphqlSchema); + + // Loop through all the query fields and attach the resolvers for + // each query before hand. + // + foreach (FieldType queryField in Schema.Query.Fields) + { + attachQueryResolverToSchema(queryField.Name); + } + } + } + } } From 79ecbda4e3b2470aa70665751088cad68fe0c46f Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Mon, 13 Sep 2021 13:19:27 -0700 Subject: [PATCH 24/81] Specify queryParameters --- .../Resolvers/SQLQueryEngine.cs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index 6517e60228..5590d0a2d3 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -13,6 +13,7 @@ using Microsoft.Data.SqlClient; using Microsoft.Sql.Rest.QueryHandler; using Newtonsoft.Json.Linq; +using System.Data; namespace Cosmos.GraphQL.Services { @@ -61,10 +62,19 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar // Edit query to add FOR JSON PATH // string queryText = resolver.parametrizedQuery + x_ForJsonSuffix + "," + x_WithoutArrayWrapperSuffix + ";"; + List queryParameters = new List(); + + if (parameters != null) + { + foreach (var parameterEntry in parameters) + { + queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value.Value)); + } + } // Open connection and execute query using _queryExecutor // - DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName); + DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName, queryParameters); // Parse Results into Json and return // @@ -101,10 +111,19 @@ public async Task> ExecuteListAsync(string graphQLQuer // Edit query to add FOR JSON PATH // string queryText = resolver.parametrizedQuery + x_ForJsonSuffix + ";"; + List queryParameters = new List(); + + if (parameters != null) + { + foreach (var parameterEntry in parameters) + { + queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value.Value)); + } + } // Open connection and execute query using _queryExecutor // - DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName); + DbDataReader dbDataReader = await _queryExecutor.ExecuteQueryAsync(queryText, resolver.databaseName, queryParameters); // Deserialize results into list of JsonDocuments and return // From 1ee62a3b0b0b4cd47fa78e83c2603e3aa9dcc746 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Mon, 13 Sep 2021 13:27:02 -0700 Subject: [PATCH 25/81] Use parameter in query --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 3c6069b94b..09c6c7f083 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -1,12 +1,12 @@ { - "GraphQLSchema": "type Query { \r\n topOneCharacter: characters \r\n characterList : [characters] \r\n } \r\n\r\n type characters { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: Int, \r\n primaryFunction: String \r\n}", + "GraphQLSchema": "type Query { \r\n characterById(id : ID!): character \r\n characterList : [character!]! \r\n } \r\n\r\n type character { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: Int, \r\n primaryFunction: String \r\n}", "Resolvers": [ { "engine": "SQL", - "id": "topOneCharacter", + "id": "characterById", "databaseName": "StarWars", "isList": false, - "parametrizedQuery": "SELECT TOP 1 [id], [name], [type], [homePlanet], [primaryFunction] FROM characters" + "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters WHERE [id] = @id" }, { "engine": "SQL", From d1c0b811467ad54b798557d2caddfefc6b62476d Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Mon, 13 Sep 2021 16:24:24 -0700 Subject: [PATCH 26/81] Addressing PR comments. Renaming Sql references to MSSQL. Adding schema.gql file for development purposes with corresponding logic. Updated class summaries. --- ...erTests.cs => MSSQLClientProviderTests.cs} | 6 +++--- .../Cosmos.GraphQL.Service.csproj | 10 +++++++++ ...ientProvider.cs => MSSQLClientProvider.cs} | 8 ++++++- .../Services/FileMetadataStoreProvider.cs | 21 ++++++++++++++++++- .../Cosmos.GraphQL.Service/Startup.cs | 8 +++---- .../Cosmos.GraphQL.Service/appsettings.json | 9 +------- .../Cosmos.GraphQL.Service/config.json | 2 +- .../configurations/ConfigurationProvider.cs | 8 +++++-- .../configurations/MSSQLCredentials.cs | 18 ++++++++++++++++ .../configurations/SQLCredentials.cs | 12 ----------- .../Cosmos.GraphQL.Service/schema.gql | 11 ++++++++++ 11 files changed, 81 insertions(+), 32 deletions(-) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/{SqlClientProviderTests.cs => MSSQLClientProviderTests.cs} (88%) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/{SQLClientProvider.cs => MSSQLClientProvider.cs} (72%) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs similarity index 88% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs index af037fa819..88d8786224 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs @@ -11,12 +11,12 @@ namespace Cosmos.GraphQL.Service.Tests { [TestClass] - public class SqlClientProviderTests + public class MSSQLClientProviderTests { private IClientProvider _clientProvider; - public SqlClientProviderTests() + public MSSQLClientProviderTests() { - _clientProvider = new SQLClientProvider(); + _clientProvider = new MSSQLClientProvider(); } /// /// Ensure a connection is successfully opened within the [Database]ClientProvider, diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index b8c80d417d..256f26a49f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -4,6 +4,16 @@ net5.0 + + + + + + + PreserveNewest + + + diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs similarity index 72% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs index c55ae5f7e1..e74da9ac40 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs @@ -7,8 +7,14 @@ namespace Cosmos.GraphQL.Service.Resolvers { - public class SQLClientProvider: IClientProvider + /// + /// Creates, returns, and maintains SqlConnection for all resources the make SQL database calls. + /// + public class MSSQLClientProvider: IClientProvider { + /// + /// Connection object shared across engines that require database access. + /// private static SqlConnection _sqlConnection; private static readonly object syncLock = new object(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs index ed7e820192..9f7134506d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs @@ -9,9 +9,19 @@ namespace Cosmos.GraphQL.Service { + /// + /// Reads GraphQL Schema and resolver config from text files to make available to GraphQL service. + /// public class FileMetadataStoreProvider : IMetadataStoreProvider { + /// + /// String Representation of graphQL schema, non escaped. + /// private string _graphQLSchema; + + /// + /// Stores resolvers contained in configuration file. + /// private IDictionary _resolvers; public FileMetadataStoreProvider() @@ -27,7 +37,16 @@ private void init() { JsonElement root = document.RootElement; JsonElement schema = root.GetProperty("GraphQLSchema"); - _graphQLSchema = schema.GetString(); + + if (String.IsNullOrEmpty(schema.GetString())) + { + _graphQLSchema = File.ReadAllText("schema.gql"); + } + else + { + _graphQLSchema = schema.GetString(); + } + JsonElement resolversListJson = root.GetProperty("Resolvers"); _resolvers = new Dictionary(); foreach(JsonElement resolver in resolversListJson.EnumerateArray()) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 60b60dba8e..fdf7e63ee9 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -13,7 +13,7 @@ namespace Cosmos.GraphQL.Service { enum DatabaseType { - SQL, + MSSQL, COSMOS, POSTGRES, } @@ -47,11 +47,11 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); break; - case DatabaseType.SQL: - services.AddSingleton, SQLClientProvider>(); + case DatabaseType.MSSQL: + services.AddSingleton, MSSQLClientProvider>(); break; default: - throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. This is likely a bug in this function", dbType)); + throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. Please check the configuration file.", dbType)); } services.AddSingleton(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index 478f1acc96..c905f7f8a3 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -16,12 +16,5 @@ "Database": "", "ConnectionString": "" } - }, - "DatabaseConnection2": { - "DatabaseType": "SQL", - "Credentials": { - "ConnectionString": "" - - } - } + } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 33967ccc03..e13999543a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -1,5 +1,5 @@ { - "GraphQLSchema": "{ \r\n type Query { \r\n bookById (id: @id): Book \r\n } \r\n\r\n type Book { \r\n id : ID!, \r\n title : String!, \r\n numberOfPages: Int, \r\n author: Author\r\n } \r\n\r\n type Author { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String, \r\n address: String, \r\n } \r\n\r\n type Mutation { \r\n addBook( \r\n id : ID!, \r\n title: String!, \r\n numberOfPages: Int, \r\n author : { \r\n id: ID!, \r\n firstName: String, \r\n lastName: String \r\n address: String \r\n } \r\n ): Book \r\n } \r\n} ", + "GraphQLSchema": "", "Resolvers": [ { "engine": "SQL", diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index 47d970e750..cc989328ab 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -4,6 +4,10 @@ namespace Cosmos.GraphQL.Service.configurations { + /// + /// Processes appsettings.json file containing dbtype + /// and database connection credentials/connections strings. + /// public class ConfigurationProvider { private static ConfigurationProvider instance; @@ -45,8 +49,8 @@ private void init() case DatabaseType.COSMOS: Creds = section.Get(); break; - case DatabaseType.SQL: - Creds = section.Get(); + case DatabaseType.MSSQL: + Creds = section.Get(); break; default: break; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs new file mode 100644 index 0000000000..2ee7db715c --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.configurations +{ + /// + /// Represenation of MSSQL specific credential properties + /// + public class MSSQLCredentials : IDatabaseCredentials + { + /// + /// Fully constructed connection string with user credentials. + /// + public string ConnectionString { get; set; } + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs deleted file mode 100644 index 1240c4c8c1..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.configurations -{ - public class SQLCredentials : IDatabaseCredentials - { - public string ConnectionString { get; set; } - } -} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql new file mode 100644 index 0000000000..f97e4f7955 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql @@ -0,0 +1,11 @@ +type Query { + characterList: characters + } + +type characters { + id : ID, + name : String, + type: String, + homePlanet: Int, + primaryFunction: String +} \ No newline at end of file From 003b06eb2c64779ccc7c1077647c68d07e0f9599 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:38:29 -0700 Subject: [PATCH 27/81] Fixes after merging changes from MetadataProvider review --- .../Services/FileMetadataStoreProvider.cs | 2 +- .../Cosmos.GraphQL.Service/Startup.cs | 2 +- .../configurations/MSSQLCredentials.cs | 5 +++++ .../configurations/SQLCredentials.cs | 13 ------------- 4 files changed, 7 insertions(+), 15 deletions(-) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs index 0f3797137c..57a7071fcc 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/FileMetadataStoreProvider.cs @@ -38,7 +38,7 @@ private void init() JsonElement root = document.RootElement; JsonElement schema = root.GetProperty("GraphQLSchema"); - if (String.IsNullOrEmpty(schema.GetString())) + if (string.IsNullOrEmpty(schema.GetString())) { _graphQLSchema = File.ReadAllText("schema.gql"); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index b333976759..82913a9b17 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -53,7 +53,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); break; case DatabaseType.MSSQL: - SQLCredentials creds = (SQLCredentials)configurations.ConfigurationProvider.getInstance().Creds; + MSSQLCredentials creds = (MSSQLCredentials)configurations.ConfigurationProvider.getInstance().Creds; services.AddSingleton(provider => new DbConnectionService(provider.GetService(), creds.Server)); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs index 2ee7db715c..2acd9f9370 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs @@ -14,5 +14,10 @@ public class MSSQLCredentials : IDatabaseCredentials /// Fully constructed connection string with user credentials. /// public string ConnectionString { get; set; } + + /// + /// Server name to connect to. + /// + public string Server { get; set; } } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs deleted file mode 100644 index f7a777fe5c..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/SQLCredentials.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.configurations -{ - public class SQLCredentials : IDatabaseCredentials - { - public string ConnectionString { get; set; } - public string Server { get; set; } - } -} From 2c2f3e2d2989e96a9eac9d5f96af6d9fe7f06746 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:39:43 -0700 Subject: [PATCH 28/81] Planet table --- .../Cosmos.GraphQL.Service/config.json | 20 +++++++++++-- .../Cosmos.GraphQL.Service/schema.gql | 28 ++++++++++++------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 09c6c7f083..8db8e10de3 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -1,19 +1,33 @@ { - "GraphQLSchema": "type Query { \r\n characterById(id : ID!): character \r\n characterList : [character!]! \r\n } \r\n\r\n type character { \r\n id : ID, \r\n name : String, \r\n type: String, \r\n homePlanet: Int, \r\n primaryFunction: String \r\n}", + "GraphQLSchema": "", "Resolvers": [ { "engine": "SQL", "id": "characterById", "databaseName": "StarWars", "isList": false, - "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters WHERE [id] = @id" + "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM character WHERE [id] = @id" }, { "engine": "SQL", "id": "characterList", "databaseName": "StarWars", "isList": true, - "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM characters" + "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM character" + }, + { + "engine": "SQL", + "id": "planetById", + "databaseName": "StarWars", + "isList": false, + "parametrizedQuery": "SELECT [id], [name] FROM planet WHERE [id] = @id" + }, + { + "engine": "SQL", + "id": "planetList", + "databaseName": "StarWars", + "isList": true, + "parametrizedQuery": "SELECT [id], [name] FROM planet" } ] } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql index f97e4f7955..0de74f0e92 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql @@ -1,11 +1,19 @@ -type Query { - characterList: characters - } +type Query { + characterList: [character] + characterById (id : ID!): character + planetById (id: ID!): planet + planetList: [planet] + } -type characters { - id : ID, - name : String, - type: String, - homePlanet: Int, - primaryFunction: String -} \ No newline at end of file +type character { + id : ID, + name : String, + type: String, + homePlanet: Int, + primaryFunction: String +} + +type planet { + id : ID, + name : String +} \ No newline at end of file From 5cc3a68438afd4391a3ebbc4d0a7a4af487efa9c Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:41:44 -0700 Subject: [PATCH 29/81] Add Sql.Rest library --- Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj | 10 +++ .../QueryHandler/IQueryExecutor.cs | 38 +++++++++ .../QueryHandler/QueryExecutor.cs | 72 ++++++++++++++++ .../Utils/DbConnectionService.cs | 82 +++++++++++++++++++ .../Utils/IDbConnectionService.cs | 19 +++++ 5 files changed, 221 insertions(+) create mode 100644 Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj create mode 100644 Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs create mode 100644 Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs create mode 100644 Microsoft.Sql.Rest/Utils/DbConnectionService.cs create mode 100644 Microsoft.Sql.Rest/Utils/IDbConnectionService.cs diff --git a/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj b/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj new file mode 100644 index 0000000000..6bc8b72b07 --- /dev/null +++ b/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj @@ -0,0 +1,10 @@ + + + net5.0 + + + + + + + diff --git a/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs b/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs new file mode 100644 index 0000000000..fbe110cf77 --- /dev/null +++ b/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading.Tasks; + +namespace Microsoft.Sql.Rest.QueryHandler +{ + /// + /// Interface for query execution. + /// + public interface IQueryExecutor + { + /// + /// Execute sql text that return result set. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// DbDataReader object for reading the result set. + public Task ExecuteQueryAsync(string sqltext, string database); + + /// + /// Execute sql text with parameters and return result set. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// The parameters used to execute the SQL text. + /// DbDataReader object for reading the result set. + public Task ExecuteQueryAsync(string sqltext, string database, List parameters); + + /// + /// Execute sql text returns no result set. For example, insert statement. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// Task representing the async operation. + public Task ExecuteNonQueryAsync(string sqltext, string database); + } +} \ No newline at end of file diff --git a/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs b/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs new file mode 100644 index 0000000000..f674e9c161 --- /dev/null +++ b/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; +using Microsoft.Sql.Rest.Utils; + +namespace Microsoft.Sql.Rest.QueryHandler +{ + /// + /// Execute the query and return the response. + /// + public class QueryExecutor : IQueryExecutor + { + private readonly IDbConnectionService _dbConnectionService; + + /// + /// Initializes a new instance of the class. + /// Constructor for QueryExecutor. We are using .NET dependency injection to inject IDbConnectionService. + /// + /// DbConnectionService for setting up connection. + public QueryExecutor(IDbConnectionService dbConnectionService) + { + _dbConnectionService = dbConnectionService; + } + + /// + /// Execute sql text that return result set. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// DbDataReader object for reading the result set. + public async Task ExecuteQueryAsync(string sqltext, string databaseName) + { + return await ExecuteQueryAsync(sqltext, databaseName, null); + } + + /// + /// Execute sql text that return result set. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// DbDataReader object for reading the result set. + public async Task ExecuteQueryAsync(string sqltext, string databaseName, List parameters) + { + SqlConnection conn = await _dbConnectionService.GetOpenedConnection(databaseName); + SqlCommand cmd = new SqlCommand(sqltext, conn); + + if (parameters != null) + { + foreach(SqlParameter parameter in parameters) + { + cmd.Parameters.Add(parameter); + } + } + + return await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection); + } + + /// + /// Execute sql text returns no result set. For example, insert statement. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// Task representing the async operation. + public Task ExecuteNonQueryAsync(string sqltext, string database) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Sql.Rest/Utils/DbConnectionService.cs b/Microsoft.Sql.Rest/Utils/DbConnectionService.cs new file mode 100644 index 0000000000..a2efeb9129 --- /dev/null +++ b/Microsoft.Sql.Rest/Utils/DbConnectionService.cs @@ -0,0 +1,82 @@ +using System; +using System.Threading.Tasks; +using LruCacheNet; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Sql.Rest.Utils +{ + /// + /// Service for managing the database connection. + /// + public class DbConnectionService : IDbConnectionService + { + private readonly LruCache _connStringCache = new(10_000); + private readonly ILogger _logger; + private readonly string _server; + private readonly string _proxyUser; + private readonly string _proxyPassword; + + /// + /// Initializes a new instance of the class. + /// given an Ilogger and server name. + /// + public DbConnectionService(ILogger logger, string server) + { + _logger = logger; + _server = server; + } + + /// + /// Get a connection to a database. Cache the connection string after the first access. + /// + /// Database name. + /// Opened sql connection. + public async Task GetOpenedConnection(string databaseName) + { + string connString = GetConnectionString(databaseName); + + SqlConnection conn = new(connString); + await conn.OpenAsync(); + return conn; + } + + /// + /// Get a connection string to a given database. + /// + /// Database name. + /// + public string GetConnectionString(string databaseName) + { + if(!_connStringCache.TryGetValue(databaseName, out string connString)) + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder + { + InitialCatalog = databaseName, + DataSource = _server, + }; + + // Use SQL Login as a proxy user if it exists. + // Otherwise, use integrated security. + if(!string.IsNullOrWhiteSpace(_proxyUser) && !string.IsNullOrWhiteSpace(_proxyPassword)) + { + builder.UserID = _proxyUser; + builder.Password = _proxyPassword; + } + else + { + builder.IntegratedSecurity = true; + } + + _connStringCache[databaseName] = connString = builder.ToString(); + + if(_logger != null) + { + _logger.LogTrace($"Create and cache new connection string for {databaseName}"); + } + } + + return connString; + } + } +} diff --git a/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs b/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs new file mode 100644 index 0000000000..79187bc873 --- /dev/null +++ b/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; + +namespace Microsoft.Sql.Rest.Utils +{ + /// + /// Interface representing services for managing the database connection. + /// + public interface IDbConnectionService + { + /// + /// Get a connection to a database. Cache the connection string after the first access. + /// The caller is responsible for closing the connection. + /// + /// Database name. + /// Opened sql connection. + public Task GetOpenedConnection(string databaseName); + } +} From 22ef260f1cc4fb97c9ca1e8aa3faa646d9b8810a Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:41:58 -0700 Subject: [PATCH 30/81] Add dependency on SqlRest --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln | 8 +++++++- .../Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln index 2fafc0da1d..bef87f0dcf 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.31205.134 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service", "Cosmos.GraphQL.Service\Cosmos.GraphQL.Service.csproj", "{208FC26C-A21C-4C96-98EE-F10FDAEAC508}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cosmos.GraphQL.Service.Tests", "Cosmos.GraphQL.Service.Tests\Cosmos.GraphQL.Service.Tests.csproj", "{4E50C9B0-818E-4041-B18B-5BB17E4D409F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service.Tests", "Cosmos.GraphQL.Service.Tests\Cosmos.GraphQL.Service.Tests.csproj", "{4E50C9B0-818E-4041-B18B-5BB17E4D409F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Sql.Rest", "..\Microsoft.Sql.Rest\Microsoft.Sql.Rest.csproj", "{448D66FA-854B-4C42-BCE0-FECD61D52E11}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Release|Any CPU.Build.0 = Release|Any CPU + {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index fb1d0e7774..90a004527a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -30,9 +30,8 @@ - - + From 993b49f634ee991bca30f0178142c22dc283c56a Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:51:31 -0700 Subject: [PATCH 31/81] appsettings change to use MSSQL --- .../Cosmos.GraphQL.Service/appsettings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index c905f7f8a3..2672d8dbb4 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -8,12 +8,12 @@ }, "AllowedHosts": "*", "DatabaseConnection": { - "DatabaseType": "COSMOS", + "DatabaseType": "MSSQL", "Credentials": { "ServerEndpointUrl": "", "AuthorizationKey": "", "Container": "", - "Database": "", + "Server": "localhost", "ConnectionString": "" } } From fc1ddc32a756dea5615fbd096e49769f89b07b34 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Tue, 14 Sep 2021 14:52:03 -0700 Subject: [PATCH 32/81] Modify git ignore to ignore the bin, obj folders --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 077b9433cb..0ad8ec404a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/obj/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/.idea/* */.idea/* +*/bin/* +*/obj/* # Visual Studio 2015 cache/options directory .vs/ \ No newline at end of file From 55993bca80d5d4204741addcebbe55ca86efb775 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Thu, 16 Sep 2021 15:28:03 -0700 Subject: [PATCH 33/81] Fix build issues after merge --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 4e6b74a507..2ec28f9e67 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -49,6 +49,8 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton, CosmosClientProvider>(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); break; case DatabaseType.MsSql: MSSQLCredentials creds = (MSSQLCredentials)configurations.ConfigurationProvider.getInstance().Creds; @@ -64,8 +66,6 @@ public void ConfigureServices(IServiceCollection services) throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. Please check the configuration file.", dbType)); } - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddControllers(); From 765caeba8447558e987258d355652f62bfd20cd1 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:50:35 -0700 Subject: [PATCH 34/81] Remove Sql.Rest as a library --- .../Cosmos.GraphQL.Service.sln | 6 -- Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj | 10 --- .../QueryHandler/IQueryExecutor.cs | 38 --------- .../QueryHandler/QueryExecutor.cs | 72 ---------------- .../Utils/DbConnectionService.cs | 82 ------------------- .../Utils/IDbConnectionService.cs | 19 ----- 6 files changed, 227 deletions(-) delete mode 100644 Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj delete mode 100644 Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs delete mode 100644 Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs delete mode 100644 Microsoft.Sql.Rest/Utils/DbConnectionService.cs delete mode 100644 Microsoft.Sql.Rest/Utils/IDbConnectionService.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln index bef87f0dcf..c88514f918 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service", "C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service.Tests", "Cosmos.GraphQL.Service.Tests\Cosmos.GraphQL.Service.Tests.csproj", "{4E50C9B0-818E-4041-B18B-5BB17E4D409F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Sql.Rest", "..\Microsoft.Sql.Rest\Microsoft.Sql.Rest.csproj", "{448D66FA-854B-4C42-BCE0-FECD61D52E11}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,10 +21,6 @@ Global {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E50C9B0-818E-4041-B18B-5BB17E4D409F}.Release|Any CPU.Build.0 = Release|Any CPU - {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Release|Any CPU.ActiveCfg = Release|Any CPU - {448D66FA-854B-4C42-BCE0-FECD61D52E11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj b/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj deleted file mode 100644 index 6bc8b72b07..0000000000 --- a/Microsoft.Sql.Rest/Microsoft.Sql.Rest.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - net5.0 - - - - - - - diff --git a/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs b/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs deleted file mode 100644 index fbe110cf77..0000000000 --- a/Microsoft.Sql.Rest/QueryHandler/IQueryExecutor.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Threading.Tasks; - -namespace Microsoft.Sql.Rest.QueryHandler -{ - /// - /// Interface for query execution. - /// - public interface IQueryExecutor - { - /// - /// Execute sql text that return result set. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// DbDataReader object for reading the result set. - public Task ExecuteQueryAsync(string sqltext, string database); - - /// - /// Execute sql text with parameters and return result set. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// The parameters used to execute the SQL text. - /// DbDataReader object for reading the result set. - public Task ExecuteQueryAsync(string sqltext, string database, List parameters); - - /// - /// Execute sql text returns no result set. For example, insert statement. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// Task representing the async operation. - public Task ExecuteNonQueryAsync(string sqltext, string database); - } -} \ No newline at end of file diff --git a/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs b/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs deleted file mode 100644 index f674e9c161..0000000000 --- a/Microsoft.Sql.Rest/QueryHandler/QueryExecutor.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Threading.Tasks; -using Microsoft.Data.SqlClient; -using Microsoft.Sql.Rest.Utils; - -namespace Microsoft.Sql.Rest.QueryHandler -{ - /// - /// Execute the query and return the response. - /// - public class QueryExecutor : IQueryExecutor - { - private readonly IDbConnectionService _dbConnectionService; - - /// - /// Initializes a new instance of the class. - /// Constructor for QueryExecutor. We are using .NET dependency injection to inject IDbConnectionService. - /// - /// DbConnectionService for setting up connection. - public QueryExecutor(IDbConnectionService dbConnectionService) - { - _dbConnectionService = dbConnectionService; - } - - /// - /// Execute sql text that return result set. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// DbDataReader object for reading the result set. - public async Task ExecuteQueryAsync(string sqltext, string databaseName) - { - return await ExecuteQueryAsync(sqltext, databaseName, null); - } - - /// - /// Execute sql text that return result set. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// DbDataReader object for reading the result set. - public async Task ExecuteQueryAsync(string sqltext, string databaseName, List parameters) - { - SqlConnection conn = await _dbConnectionService.GetOpenedConnection(databaseName); - SqlCommand cmd = new SqlCommand(sqltext, conn); - - if (parameters != null) - { - foreach(SqlParameter parameter in parameters) - { - cmd.Parameters.Add(parameter); - } - } - - return await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection); - } - - /// - /// Execute sql text returns no result set. For example, insert statement. - /// - /// SQL text to be executed. - /// Database to execute the SQL text. - /// Task representing the async operation. - public Task ExecuteNonQueryAsync(string sqltext, string database) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/Microsoft.Sql.Rest/Utils/DbConnectionService.cs b/Microsoft.Sql.Rest/Utils/DbConnectionService.cs deleted file mode 100644 index a2efeb9129..0000000000 --- a/Microsoft.Sql.Rest/Utils/DbConnectionService.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Threading.Tasks; -using LruCacheNet; -using Microsoft.Data.SqlClient; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Sql.Rest.Utils -{ - /// - /// Service for managing the database connection. - /// - public class DbConnectionService : IDbConnectionService - { - private readonly LruCache _connStringCache = new(10_000); - private readonly ILogger _logger; - private readonly string _server; - private readonly string _proxyUser; - private readonly string _proxyPassword; - - /// - /// Initializes a new instance of the class. - /// given an Ilogger and server name. - /// - public DbConnectionService(ILogger logger, string server) - { - _logger = logger; - _server = server; - } - - /// - /// Get a connection to a database. Cache the connection string after the first access. - /// - /// Database name. - /// Opened sql connection. - public async Task GetOpenedConnection(string databaseName) - { - string connString = GetConnectionString(databaseName); - - SqlConnection conn = new(connString); - await conn.OpenAsync(); - return conn; - } - - /// - /// Get a connection string to a given database. - /// - /// Database name. - /// - public string GetConnectionString(string databaseName) - { - if(!_connStringCache.TryGetValue(databaseName, out string connString)) - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder - { - InitialCatalog = databaseName, - DataSource = _server, - }; - - // Use SQL Login as a proxy user if it exists. - // Otherwise, use integrated security. - if(!string.IsNullOrWhiteSpace(_proxyUser) && !string.IsNullOrWhiteSpace(_proxyPassword)) - { - builder.UserID = _proxyUser; - builder.Password = _proxyPassword; - } - else - { - builder.IntegratedSecurity = true; - } - - _connStringCache[databaseName] = connString = builder.ToString(); - - if(_logger != null) - { - _logger.LogTrace($"Create and cache new connection string for {databaseName}"); - } - } - - return connString; - } - } -} diff --git a/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs b/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs deleted file mode 100644 index 79187bc873..0000000000 --- a/Microsoft.Sql.Rest/Utils/IDbConnectionService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Sql.Rest.Utils -{ - /// - /// Interface representing services for managing the database connection. - /// - public interface IDbConnectionService - { - /// - /// Get a connection to a database. Cache the connection string after the first access. - /// The caller is responsible for closing the connection. - /// - /// Database name. - /// Opened sql connection. - public Task GetOpenedConnection(string databaseName); - } -} From e049da377562e4dbb6afad875ea130e3fbf05f04 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:54:03 -0700 Subject: [PATCH 35/81] Add IDbConnectionService as implementing IClientProvider --- .../Resolvers/CosmosClientProvider.cs | 2 +- .../Resolvers/IClientProvider.cs | 11 +-- .../Resolvers/IDbConnectionService.cs | 19 +++++ .../Resolvers/MSSQLClientProvider.cs | 69 +++++++++++++------ .../Resolvers/SQLClientProvider.cs | 20 ------ 5 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs index 93447d871d..dbfd6b95c1 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosClientProvider.cs @@ -16,7 +16,7 @@ private static void init() _cosmosClient = new CosmosClientBuilder(cred.ConnectionString).WithContentResponseOnWrite(true).Build(); } - public CosmosClient getClient() + public CosmosClient GetClient() { return getCosmosClient(); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs index 0052d448c7..3355e3918d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IClientProvider.cs @@ -1,16 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.Resolvers +namespace Cosmos.GraphQL.Service.Resolvers { /// /// Interface representing database clients with retrieval method. /// - /// Type of database client (i.e. SqlConnection or CosmosClient) + /// Type of database client (i.e. DbConnection or CosmosClient) public interface IClientProvider { - public T getClient(); + public T GetClient(); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs new file mode 100644 index 0000000000..9b009abcad --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs @@ -0,0 +1,19 @@ +using System.Data.Common; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Interface representing services for managing the database connection. + /// + public interface IDbConnectionService : IClientProvider + { + /// + /// Gets an open connection to the given database. + /// The caller is responsible for closing the connection. + /// + /// Database name. + /// Opened sql connection. + public Task GetOpenedConnection(string databaseName); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs index b187e8a493..f76bcdfc16 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Data.Common; using System.Threading.Tasks; using Microsoft.Data.SqlClient; using Cosmos.GraphQL.Service.configurations; @@ -8,35 +6,66 @@ namespace Cosmos.GraphQL.Service.Resolvers { /// - /// Creates, returns, and maintains SqlConnection for all resources that make SQL database calls. + /// Client provider for MsSql. /// - public class MSSQLClientProvider: IClientProvider + public class MsSqlClientProvider : IDbConnectionService { /// - /// Connection object shared across engines that require database access. + /// Credentials provided in the config. /// - private static SqlConnection _sqlConnection; - private static readonly object syncLock = new object(); + private readonly MsSqlCredentials _sqlCredentials; - private void init() + /// + /// Constructor + /// + public MsSqlClientProvider() { - _sqlConnection = new SqlConnection(ConfigurationProvider.getInstance().Creds.ConnectionString); + _sqlCredentials = (MsSqlCredentials)ConfigurationProvider.getInstance().Creds; } - public SqlConnection getClient() + /// + /// Gets an open connection using the connection string provided in appsettings.json. + /// + public DbConnection GetClient() + { + return GetOpenedConnection().Result; + } + + /// + /// Gets a connection to a database. The caller should close this connection. + /// + /// Database name, optional. If not provided, the connection string + /// from appsettings is used. + /// Opened sql connection. + public async Task GetOpenedConnection(string databaseName = "") { - if (_sqlConnection == null) + string connString = _sqlCredentials.ConnectionString; + + if (string.IsNullOrEmpty(connString)) { - lock (syncLock) - { - if (_sqlConnection == null) - { - init(); - } - } + connString = GetConnectionString(databaseName); } - return _sqlConnection; + SqlConnection conn = new(connString); + await conn.OpenAsync(); + return conn; + } + + /// + /// Constructs a connection string to the given database. + /// + /// Database name. + /// the constructed connection string + public string GetConnectionString(string databaseName) + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder + { + InitialCatalog = databaseName, + DataSource = _sqlCredentials.Server, + }; + + builder.IntegratedSecurity = true; + return builder.ToString(); } } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs deleted file mode 100644 index b1d71fece5..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLClientProvider.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using Microsoft.Sql.Rest.Utils; - -namespace Cosmos.GraphQL.Service.Resolvers -{ - public class SQLClientProvider: IClientProvider - { - private static DbConnectionService _sqlConnectionService; - - public SQLClientProvider(IDbConnectionService dbConnectionService) - { - _sqlConnectionService = (DbConnectionService)dbConnectionService; - } - - public DbConnectionService getClient() - { - return _sqlConnectionService; - } - } -} From 9aece99dde00dce7d728ede3c4424f7c8ff7e2be Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:54:55 -0700 Subject: [PATCH 36/81] Rename to MsSqlCredentials --- .../configurations/ConfigurationProvider.cs | 2 +- .../Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index 2bf0e385e5..dcbef1bc6c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -50,7 +50,7 @@ private void init() Creds = section.Get(); break; case DatabaseType.MsSql: - Creds = section.Get(); + Creds = section.Get(); break; default: break; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs index 4460db5599..d7236b33c6 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs @@ -6,9 +6,9 @@ namespace Cosmos.GraphQL.Service.configurations { /// - /// Representation of MSSQL specific credential properties + /// Representation of MsSql specific credential properties /// - public class MSSQLCredentials : IDatabaseCredentials + public class MsSqlCredentials : IDatabaseCredentials { /// /// Fully constructed connection string with user credentials. From 40a1fd797ca775736dd6fed7179266aaa4877113 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:55:15 -0700 Subject: [PATCH 37/81] Add IQueryExecutor --- .../Resolvers/IQueryExecutor.cs | 22 ++++++++ .../Resolvers/QueryExecutor.cs | 52 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs new file mode 100644 index 0000000000..726d8de1e6 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Interface for query execution. + /// + public interface IQueryExecutor + { + /// + /// Execute sql text with parameters and return result set. + /// + /// SQL text to be executed. + /// Database to execute the SQL text. + /// The parameters used to execute the SQL text. + /// DbDataReader object for reading the result set. + public Task ExecuteQueryAsync(string sqltext, string database, List parameters); + } +} \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs new file mode 100644 index 0000000000..96114a0a77 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading.Tasks; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Encapsulates query execution apis. + /// + public class QueryExecutor : IQueryExecutor + { + /// + /// The clientProvider useful for connecting to the backend. + /// + private readonly IDbConnectionService _clientProvider; + + /// + /// Initializes a new instance of the class. + /// Constructor for QueryExecutor. + /// + /// ClientProvider for setting up connection. + public QueryExecutor(IDbConnectionService clientProvider) + { + _clientProvider = clientProvider; + } + + /// + /// Executes sql text that return result set. + /// + /// Sql text to be executed. + /// Database to execute the SQL text. + /// DbDataReader object for reading the result set. + public async Task ExecuteQueryAsync(string sqltext, string databaseName, List parameters) + { + DbConnection conn = await _clientProvider.GetOpenedConnection(databaseName); + DbCommand cmd = conn.CreateCommand(); + cmd.CommandText = sqltext; + cmd.CommandType = CommandType.Text; + + if (parameters != null) + { + foreach (IDataParameter parameter in parameters) + { + cmd.Parameters.Add(parameter); + } + } + + return await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection); + } + } +} \ No newline at end of file From 43c0cf550bf081693a20dd67ede0137535bcafc0 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:56:09 -0700 Subject: [PATCH 38/81] Rename to SqlQueryEngine --- .../Resolvers/SQLQueryEngine.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index 5590d0a2d3..d133c74d25 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -1,26 +1,20 @@ using System; using System.Collections.Generic; using System.Data.Common; -using System.Configuration; -using System.Reflection; using System.Text.Json; using System.Threading.Tasks; -using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Models; using Cosmos.GraphQL.Service.Resolvers; using GraphQL.Execution; -using Microsoft.Azure.Cosmos; using Microsoft.Data.SqlClient; -using Microsoft.Sql.Rest.QueryHandler; -using Newtonsoft.Json.Linq; using System.Data; namespace Cosmos.GraphQL.Services { // - // SQLQueryEngine to ExecuteAsync against SQL Db. + // SqlQueryEngine to ExecuteAsync against Sql Db. // - public class SQLQueryEngine : IQueryEngine + public class SqlQueryEngine : IQueryEngine { private IMetadataStoreProvider _metadataStoreProvider; private readonly IQueryExecutor _queryExecutor; @@ -31,7 +25,7 @@ public class SQLQueryEngine : IQueryEngine // // Constructor. // - public SQLQueryEngine(IMetadataStoreProvider metadataStoreProvider, IQueryExecutor queryExecutor) + public SqlQueryEngine(IMetadataStoreProvider metadataStoreProvider, IQueryExecutor queryExecutor) { _metadataStoreProvider = metadataStoreProvider; _queryExecutor = queryExecutor; From 5f89f527318e25176eeb2a08e366216a03e811eb Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:56:34 -0700 Subject: [PATCH 39/81] Remove Sql.Rest --- .../Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj index 90a004527a..256f26a49f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.csproj @@ -30,8 +30,5 @@ - - - From 50fde720cf556be5283ff8ced4f6338cc47f4c3e Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:57:33 -0700 Subject: [PATCH 40/81] Remove need for indirection - MsSqlClientProvider is the DbConnectionService --- .../Cosmos.GraphQL.Service/Startup.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 2ec28f9e67..ec70c17453 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -1,4 +1,3 @@ -using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Resolvers; using Cosmos.GraphQL.Services; using Microsoft.AspNetCore.Builder; @@ -7,9 +6,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Sql.Rest.QueryHandler; -using Microsoft.Sql.Rest.Utils; using System; namespace Cosmos.GraphQL.Service @@ -53,14 +49,10 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); break; case DatabaseType.MsSql: - MSSQLCredentials creds = (MSSQLCredentials)configurations.ConfigurationProvider.getInstance().Creds; - services.AddSingleton(provider => - new DbConnectionService(provider.GetService(), - creds.Server)); - services.AddSingleton, SQLClientProvider>(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); break; default: throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. Please check the configuration file.", dbType)); From 88649bcee66e3ab7c196ac928f30751b123864d7 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:58:05 -0700 Subject: [PATCH 41/81] Remove unnecessary code --- .../Resolvers/MutationEngine.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index cdfc708e7e..689aff4fad 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -3,32 +3,24 @@ using System.Reflection; using System.Text.Json; using System.Threading.Tasks; -using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Models; -using Cosmos.GraphQL.Service.Resolvers; using Cosmos.GraphQL.Services; using GraphQL.Execution; -using GraphQL.Language.AST; using Microsoft.Azure.Cosmos; -using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Microsoft.Sql.Rest.Utils; namespace Cosmos.GraphQL.Service.Resolvers { public class MutationEngine { - private readonly IClientProvider _clientProvider; - private readonly IMetadataStoreProvider _metadataStoreProvider; private ScriptOptions scriptOptions; - public MutationEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + public MutationEngine(IMetadataStoreProvider metadataStoreProvider) { - this._clientProvider = clientProvider; this._metadataStoreProvider = metadataStoreProvider; } @@ -55,7 +47,7 @@ private JObject execute(IDictionary parameters, MutationR jObject.Add("id", Guid.NewGuid().ToString()); } - //var container = _clientProvider.getClient().GetDatabase(resolver.databaseName) + //var container = _clientProvider.GetClient().GetDatabase(resolver.databaseName) // .GetContainer(resolver.containerName); // TODO: check insertion type From e39621fa70e7622a122e7581d87081402310f385 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:58:21 -0700 Subject: [PATCH 42/81] Fix tests to work with new classes --- .../MSSQLClientProviderTests.cs | 12 ++++-------- .../Cosmos.GraphQL.Service.Tests/SchemaTests.cs | 2 +- .../SqlClientProviderTests.cs | 13 +++++-------- .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 4 ++-- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs index 88d8786224..d3d96ffc5a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs @@ -1,22 +1,18 @@ using Cosmos.GraphQL.Service.Resolvers; -using Microsoft.Data.SqlClient; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Data; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Data.Common; namespace Cosmos.GraphQL.Service.Tests { [TestClass] public class MSSQLClientProviderTests { - private IClientProvider _clientProvider; + private IDbConnectionService _clientProvider; public MSSQLClientProviderTests() { - _clientProvider = new MSSQLClientProvider(); + _clientProvider = new MsSqlClientProvider(); } /// /// Ensure a connection is successfully opened within the [Database]ClientProvider, @@ -26,7 +22,7 @@ public MSSQLClientProviderTests() [TestMethod] public void TestOpenConnection() { - SqlConnection connection = _clientProvider.getClient(); + DbConnection connection = _clientProvider.GetClient(); connection.Open(); Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); Console.WriteLine("State: {0}", connection.State); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index 2d6cff1f7e..d0f31118d4 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -21,7 +21,7 @@ public async Task TestAddSchemaAsync() CosmosClientProvider clientProvider = new CosmosClientProvider(); IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); CosmosQueryEngine queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); + MutationEngine mutationEngine = new MutationEngine(metadataStoreProvider); GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); var graphql_schema = TestHelper.GraphQLTestSchema; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs index af037fa819..9891c5988f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs @@ -1,22 +1,19 @@ using Cosmos.GraphQL.Service.Resolvers; -using Microsoft.Data.SqlClient; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Data; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Data.Common; namespace Cosmos.GraphQL.Service.Tests { [TestClass] public class SqlClientProviderTests { - private IClientProvider _clientProvider; + private IDbConnectionService _clientProvider; + public SqlClientProviderTests() { - _clientProvider = new SQLClientProvider(); + _clientProvider = new MsSqlClientProvider(); } /// /// Ensure a connection is successfully opened within the [Database]ClientProvider, @@ -26,7 +23,7 @@ public SqlClientProviderTests() [TestMethod] public void TestOpenConnection() { - SqlConnection connection = _clientProvider.getClient(); + DbConnection connection = _clientProvider.GetClient(); connection.Open(); Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); Console.WriteLine("State: {0}", connection.State); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index 62821eb6bd..3d59c7dd44 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -40,11 +40,11 @@ private void Init() CosmosCredentials creds = (CosmosCredentials)ConfigurationProvider.getInstance().Creds; string databaseName = creds.Database; string containerId = creds.Container; - clientProvider.getClient().GetContainer(databaseName,containerId).CreateItemAsync(sourceItem, new PartitionKey(uid)); + clientProvider.GetClient().GetContainer(databaseName,containerId).CreateItemAsync(sourceItem, new PartitionKey(uid)); metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); + mutationEngine = new MutationEngine(metadataStoreProvider); graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); graphQLService.parseAsync(TestHelper.GraphQLTestSchema); controller = new GraphQLController(null, queryEngine, mutationEngine, graphQLService); From 54a2ee06431e3821aaa25b96590a202fc5604879 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Fri, 17 Sep 2021 21:58:57 -0700 Subject: [PATCH 43/81] Latest diagrams --- ...ClientProvider.cd => CosmosQueryEngine.cd} | 33 ++-- .../Class Diagrams/SQLClientProvider.cd | 89 ----------- .../Class Diagrams/SqlQueryEngine.cd | 141 ++++++++++++++++++ 3 files changed, 162 insertions(+), 101 deletions(-) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/{CosmosClientProvider.cd => CosmosQueryEngine.cd} (77%) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd similarity index 77% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd index 54d55b6b66..892e86671f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosClientProvider.cd +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd @@ -1,9 +1,9 @@  - + - AEAAAQAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAAAAAAAA= + AAAAAQAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAAABAAAA= Resolvers\CosmosClientProvider.cs @@ -12,7 +12,7 @@ - + AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= configurations\ConfigurationProvider.cs @@ -33,11 +33,11 @@ - + - + @@ -67,20 +67,22 @@ - - + + - AAAAAAAAAAgAAAAAAAAMAAAQEAAABgAAAAAAAAAAAAA= - Resolvers\QueryEngine.cs + AAAIAAAAAAAAABQAAAAAAAAAEAAABAAAAAAAAAAAAEA= + Resolvers\CosmosQueryEngine.cs + + - + - AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA= Resolvers\IClientProvider.cs @@ -92,11 +94,18 @@ - + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= configurations\IDatabaseCredentials.cs + + + + AAAIAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAEA= + Resolvers\IQueryEngine.cs + + \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd deleted file mode 100644 index 4cb0df1fc0..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SQLClientProvider.cd +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= - configurations\ConfigurationProvider.cs - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= - configurations\SQLCredentials.cs - - - - - - - gEAAAAAAAAAAAAAAAAAAAAgAAAAAAAIAAAAAAAAAAAA= - Resolvers\SQLClientProvider.cs - - - - - - - CAAAJAAAEAAAAAAAAAAAAkACAAAAAAIAABAAAAAAAAA= - Services\FileMetadataStoreProvider.cs - - - - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= - Services\GraphQLService.cs - - - - - - - - - AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Resolvers\IClientProvider.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= - configurations\IDatabaseCredentials.cs - - - - - - CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= - Services\IMetadataStoreProvider.cs - - - - \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd new file mode 100644 index 0000000000..2d79452caf --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd @@ -0,0 +1,141 @@ + + + + + + AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= + configurations\ConfigurationProvider.cs + + + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAgAAAAA= + configurations\MsSqlCredentials.cs + configurations\MSSQLCredentials.cs + + + + + + + BAAAAAAAAAAAAAAAAAAAAAgAAAAAAIAAAAAAAABAAAA= + Resolvers\MsSqlClientProvider.cs + Resolvers\SQLClientProvider.cs + + + + + + + + + + CAAAJAAAEAAAAAAAAAAAAkACAAAAAAIAABAAAAAAAAA= + Services\FileMetadataStoreProvider.cs + + + + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + Services\GraphQLService.cs + + + + + + AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= + Services\GraphQLService.cs + + + + + + + + + + AAAIAAAgAAAAABQAIAAAAAAAAAAABAAAAAAAAAAAEEA= + Resolvers\SqlQueryEngine.cs + Resolvers\SQLQueryEngine.cs + + + + + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAACAA= + Resolvers\QueryExecutor.cs + + + + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA= + Resolvers\IClientProvider.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= + configurations\IDatabaseCredentials.cs + + + + + + CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= + Services\IMetadataStoreProvider.cs + + + + + + AAAIAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAEA= + Resolvers\IQueryEngine.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAA= + Resolvers\IQueryExecutor.cs + QueryHandler\IQueryExecutor.cs + + + + + + BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + Resolvers\IDbConnectionService.cs + + + + \ No newline at end of file From 39613c28720b5e920f5aa29daa9131d6b590becf Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sat, 18 Sep 2021 15:52:34 -0700 Subject: [PATCH 44/81] Move DatabaseType to ConfigurationProvider --- .../Cosmos.GraphQL.Service/Startup.cs | 20 +++++--------- .../configurations/ConfigurationProvider.cs | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index ec70c17453..cd810c5aa0 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -1,3 +1,5 @@ +using System; +using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Resolvers; using Cosmos.GraphQL.Services; using Microsoft.AspNetCore.Builder; @@ -6,17 +8,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using System; namespace Cosmos.GraphQL.Service { - enum DatabaseType - { - MsSql, - Cosmos, - Postgres, - } - public class Startup { public Startup(IConfiguration configuration) @@ -34,11 +28,8 @@ public void ConfigureServices(IServiceCollection services) throw new NotSupportedException(String.Format("The configuration file is invalid and does not *contain* the DatabaseType key.")); } - if (!Enum.TryParse(Configuration.GetValue("DatabaseConnection:DatabaseType"), out DatabaseType dbType)) - { - throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); - } - + DatabaseType dbType = configurations.ConfigurationProvider.getInstance().DbType; + switch (dbType) { case DatabaseType.Cosmos: @@ -55,7 +46,8 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); break; default: - throw new NotSupportedException(String.Format("The provide enum value: {0} is currently not supported. Please check the configuration file.", dbType)); + throw new NotSupportedException(String.Format("The provided DatabaseType value: {0} is currently not supported." + + "Please check the configuration file.", dbType)); } services.AddSingleton(); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs index dcbef1bc6c..98aeb4b627 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/ConfigurationProvider.cs @@ -1,9 +1,18 @@ -using System.Configuration; using System; using Microsoft.Extensions.Configuration; namespace Cosmos.GraphQL.Service.configurations { + /// + /// The different Dbs this app supports. + /// + public enum DatabaseType + { + Cosmos, + MsSql, + PostgreSql, + } + /// /// Processes appsettings.json file containing dbtype /// and database connection credentials/connections strings. @@ -13,7 +22,12 @@ public class ConfigurationProvider private static ConfigurationProvider instance; private static readonly object lockObject = new object(); public IDatabaseCredentials Creds { get; private set; } - + + /// + /// Determines the type of Db this app targets. + /// + public DatabaseType DbType { get; set; } + public static ConfigurationProvider getInstance() { if (instance == null) @@ -39,12 +53,17 @@ private void init() .AddJsonFile("AppSettings.json").Build(); var section = config.GetSection("DatabaseConnection"); - if (!Enum.TryParse(section["DatabaseType"], out DatabaseType dbType)) + if (Enum.TryParse(section["DatabaseType"], out DatabaseType dbType)) + { + DbType = dbType; + } + else { throw new NotSupportedException(String.Format("The configuration file is invalid and does not contain a *valid* DatabaseType key.")); } + section = section.GetSection("Credentials"); - switch (dbType) + switch (DbType) { case DatabaseType.Cosmos: Creds = section.Get(); From 2c735f2b134a7ffd54e45491d510974613baa20e Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sat, 18 Sep 2021 15:53:07 -0700 Subject: [PATCH 45/81] Fix MsSqlClientProviderTests --- .../Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs | 3 +-- .../Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs index d3d96ffc5a..7bdb948b55 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/MSSQLClientProviderTests.cs @@ -14,16 +14,15 @@ public MSSQLClientProviderTests() { _clientProvider = new MsSqlClientProvider(); } + /// /// Ensure a connection is successfully opened within the [Database]ClientProvider, /// given a valid connection string. /// - /// [TestMethod] public void TestOpenConnection() { DbConnection connection = _clientProvider.GetClient(); - connection.Open(); Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); Console.WriteLine("State: {0}", connection.State); Assert.IsTrue(connection.State.Equals(ConnectionState.Open)); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs index 9b009abcad..332f80dd31 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs @@ -14,6 +14,6 @@ public interface IDbConnectionService : IClientProvider /// /// Database name. /// Opened sql connection. - public Task GetOpenedConnection(string databaseName); + public Task GetOpenedConnection(string databaseName = ""); } } From bbbab3c53f91229332ad5722d7f8fdd5407e207f Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sat, 18 Sep 2021 16:06:11 -0700 Subject: [PATCH 46/81] No initialization of schema for CosmosDb --- .../Services/GraphQLService.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index ef52412835..bdc0f7b551 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -1,20 +1,17 @@ -using Cosmos.GraphQL.Service.Models; -using GraphQL.Types; +using GraphQL.Types; using GraphQL; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Cosmos.GraphQL.Service; +using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Resolvers; using GraphQL.Instrumentation; using GraphQL.SystemTextJson; using GraphQL.Resolvers; -using Newtonsoft.Json.Linq; namespace Cosmos.GraphQL.Services { @@ -55,7 +52,10 @@ public GraphQLService(IQueryEngine queryEngine, MutationEngine mutationEngine, I this._metadataStoreProvider = metadataStoreProvider; this._writer = new MyDocumentWriter(this._writerPure); - InitializeSchemaAndResolvers(); + if (ConfigurationProvider.getInstance().DbType != DatabaseType.Cosmos) + { + InitializeSchemaAndResolvers(); + } } public void parseAsync(String data) From 9a1ab896780d8176f339182bc281a56b60294871 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sat, 18 Sep 2021 16:06:33 -0700 Subject: [PATCH 47/81] Remove old file --- .../SqlClientProviderTests.cs | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs deleted file mode 100644 index 9891c5988f..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SqlClientProviderTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Cosmos.GraphQL.Service.Resolvers; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Data; -using System.Data.Common; - -namespace Cosmos.GraphQL.Service.Tests -{ - [TestClass] - public class SqlClientProviderTests - { - private IDbConnectionService _clientProvider; - - public SqlClientProviderTests() - { - _clientProvider = new MsSqlClientProvider(); - } - /// - /// Ensure a connection is successfully opened within the [Database]ClientProvider, - /// given a valid connection string. - /// - /// - [TestMethod] - public void TestOpenConnection() - { - DbConnection connection = _clientProvider.GetClient(); - connection.Open(); - Console.WriteLine("ServerVersion: {0}", connection.ServerVersion); - Console.WriteLine("State: {0}", connection.State); - Assert.IsTrue(connection.State.Equals(ConnectionState.Open)); - connection.Dispose(); - } - } -} From 4388bce9c855eb12737044e3e1a8d1d29baad178 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:23:51 -0700 Subject: [PATCH 48/81] add new line at end of file --- .../Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs | 2 +- .../Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs index 726d8de1e6..4bbe911c25 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs @@ -19,4 +19,4 @@ public interface IQueryExecutor /// DbDataReader object for reading the result set. public Task ExecuteQueryAsync(string sqltext, string database, List parameters); } -} \ No newline at end of file +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs index 96114a0a77..d54061e245 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs @@ -49,4 +49,4 @@ public async Task ExecuteQueryAsync(string sqltext, string databas return await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection); } } -} \ No newline at end of file +} From d4f47f7efca0e7379d9d0db9836b0e2526e6d4f8 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:25:31 -0700 Subject: [PATCH 49/81] Remove commented code and bring back clientprovider --- .../Resolvers/MutationEngine.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs index 689aff4fad..0fd945e099 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs @@ -15,13 +15,16 @@ namespace Cosmos.GraphQL.Service.Resolvers { public class MutationEngine { + private readonly IClientProvider _clientProvider; + private readonly IMetadataStoreProvider _metadataStoreProvider; private ScriptOptions scriptOptions; - public MutationEngine(IMetadataStoreProvider metadataStoreProvider) + public MutationEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { - this._metadataStoreProvider = metadataStoreProvider; + _clientProvider = clientProvider; + _metadataStoreProvider = metadataStoreProvider; } public void registerResolver(MutationResolver resolver) @@ -47,12 +50,12 @@ private JObject execute(IDictionary parameters, MutationR jObject.Add("id", Guid.NewGuid().ToString()); } - //var container = _clientProvider.GetClient().GetDatabase(resolver.databaseName) - // .GetContainer(resolver.containerName); + var container = _clientProvider.GetClient().GetDatabase(resolver.databaseName) + .GetContainer(resolver.containerName); // TODO: check insertion type - // JObject res = container.UpsertItemAsync(jObject).Result.Resource; - return jObject; + JObject res = container.UpsertItemAsync(jObject).Result.Resource; + return res; } public async Task execute(string graphQLMutationName, From ae8022a3b49321e4140adafbc8d866f0e195972d Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:25:50 -0700 Subject: [PATCH 50/81] AsyncFieldResolver --- .../Cosmos.GraphQL.Service/Services/GraphQLService.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index bdc0f7b551..316387821a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -192,17 +192,17 @@ public void attachQueryResolverToSchema(string queryName) if (_queryEngine.IsListQuery(queryName)) { this._schema.Query.GetField(queryName).Resolver = - new FuncFieldResolver>(context => + new AsyncFieldResolver>(context => { - return _queryEngine.ExecuteListAsync(queryName, context.Arguments).Result; + return _queryEngine.ExecuteListAsync(queryName, context.Arguments); }); } else { this._schema.Query.GetField(queryName).Resolver = - new FuncFieldResolver(context => + new AsyncFieldResolver(context => { - return _queryEngine.ExecuteAsync(queryName, context.Arguments).Result; + return _queryEngine.ExecuteAsync(queryName, context.Arguments); }); } } From 60c9527b73682309947942bf5884a8d427abdc83 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:26:20 -0700 Subject: [PATCH 51/81] MutationEngine only for Cosmos --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index cd810c5aa0..7ee4d64ce6 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -38,6 +38,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); break; case DatabaseType.MsSql: services.AddSingleton(); @@ -50,7 +51,6 @@ public void ConfigureServices(IServiceCollection services) "Please check the configuration file.", dbType)); } - services.AddSingleton(); services.AddSingleton(); services.AddControllers(); } From 2f71a69045878f0a6c0b81da43851c5c09db7129 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:27:21 -0700 Subject: [PATCH 52/81] Use clientProvider for MutationEngine in tests --- .../Cosmos.GraphQL.Service.Tests/SchemaTests.cs | 2 +- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index d0f31118d4..2d6cff1f7e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -21,7 +21,7 @@ public async Task TestAddSchemaAsync() CosmosClientProvider clientProvider = new CosmosClientProvider(); IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); CosmosQueryEngine queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - MutationEngine mutationEngine = new MutationEngine(metadataStoreProvider); + MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); var graphql_schema = TestHelper.GraphQLTestSchema; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index 3d59c7dd44..8e3ebe0c83 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -44,7 +44,7 @@ private void Init() metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - mutationEngine = new MutationEngine(metadataStoreProvider); + mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); graphQLService.parseAsync(TestHelper.GraphQLTestSchema); controller = new GraphQLController(null, queryEngine, mutationEngine, graphQLService); From f5798f4dae120aa3a1d23aa491d12303a9bef7eb Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 08:58:37 -0700 Subject: [PATCH 53/81] Add IMutationEngine --- .../Controllers/GraphQLController.cs | 6 +- ...ationEngine.cs => CosmosMutationEngine.cs} | 21 +++++-- .../Resolvers/IMutationEngine.cs | 29 ++++++++++ .../Resolvers/MsSqlMutationEngine.cs | 55 +++++++++++++++++++ 4 files changed, 102 insertions(+), 9 deletions(-) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/{MutationEngine.cs => CosmosMutationEngine.cs} (81%) create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs create mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs index 58918ce404..967bb0c0af 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Controllers/GraphQLController.cs @@ -22,12 +22,12 @@ public class GraphQLController : ControllerBase string JsonData = @"{'serviceName':'datagateway', 'endpointType':'graphQL'}"; private readonly IQueryEngine _queryEngine; - private readonly MutationEngine _mutationEngine; + private readonly IMutationEngine _mutationEngine; private readonly ILogger _logger; private readonly GraphQLService _schemaManager; - public GraphQLController(ILogger logger, IQueryEngine queryEngine, MutationEngine mutationEngine, GraphQLService schemaManager) + public GraphQLController(ILogger logger, IQueryEngine queryEngine, IMutationEngine mutationEngine, GraphQLService schemaManager) { _logger = logger; @@ -55,7 +55,7 @@ public void addResolver(GraphQLQueryResolver resolver) [HttpPost] public void addMutationResolver(MutationResolver resolver) { - _mutationEngine.registerResolver(resolver); + _mutationEngine.RegisterResolver(resolver); _schemaManager.attachMutationResolverToSchema(resolver.id); } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs similarity index 81% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs index 0fd945e099..266622b126 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs @@ -13,21 +13,24 @@ namespace Cosmos.GraphQL.Service.Resolvers { - public class MutationEngine + public class CosmosMutationEngine : IMutationEngine { private readonly IClientProvider _clientProvider; private readonly IMetadataStoreProvider _metadataStoreProvider; - private ScriptOptions scriptOptions; - - public MutationEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) + public CosmosMutationEngine(IClientProvider clientProvider, IMetadataStoreProvider metadataStoreProvider) { _clientProvider = clientProvider; _metadataStoreProvider = metadataStoreProvider; } - public void registerResolver(MutationResolver resolver) + /// + /// Persists resolver configuration. When resolver config, + /// is received from REST endpoint and not configuration file. + /// + /// The given mutation resolver. + public void RegisterResolver(MutationResolver resolver) { // TODO: add into system container/rp @@ -58,7 +61,13 @@ private JObject execute(IDictionary parameters, MutationR return res; } - public async Task execute(string graphQLMutationName, + /// + /// Executes the mutation query and return result as JSON object asynchronously. + /// + /// name of the GraphQL mutation query. + /// parameters in the mutation query. + /// JSON object result + public async Task Execute(string graphQLMutationName, IDictionary parameters) { diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs new file mode 100644 index 0000000000..d6e51f306c --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs @@ -0,0 +1,29 @@ +using Cosmos.GraphQL.Service.Models; +using GraphQL.Execution; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Text.Json; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + /// + /// Interface for execution of GraphQL mutations against a database. + /// + public interface IMutationEngine + { + /// + /// Persists resolver configuration. + /// + /// The given mutation resolver. + public void RegisterResolver(MutationResolver resolver); + + /// + /// Executes the mutation query and returns result as JSON object asynchronously. + /// + /// name of the GraphQL mutation query. + /// parameters in the mutation query. + /// JSON object result + public Task Execute(string graphQLMutationName, + IDictionary parameters); + } +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs new file mode 100644 index 0000000000..c80053c039 --- /dev/null +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.Json; +using System.Threading.Tasks; +using Cosmos.GraphQL.Service.configurations; +using Cosmos.GraphQL.Service.Models; +using Cosmos.GraphQL.Service.Resolvers; +using Cosmos.GraphQL.Services; +using GraphQL.Execution; +using GraphQL.Language.AST; +using Microsoft.Azure.Cosmos; +using Microsoft.CodeAnalysis.CSharp.Scripting; +using Microsoft.CodeAnalysis.Scripting; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Microsoft.Sql.Rest.Utils; + +namespace Cosmos.GraphQL.Service.Resolvers +{ + public class MsSqlMutationEngine : IMutationEngine + { + private readonly IDbConnectionService _clientProvider; + + private readonly IMetadataStoreProvider _metadataStoreProvider; + + public MsSqlMutationEngine(IDbConnectionService clientProvider, IMetadataStoreProvider metadataStoreProvider) + { + this._clientProvider = clientProvider; + this._metadataStoreProvider = metadataStoreProvider; + } + + /// + /// Persists resolver configuration. This is a no-op for MsSql + /// since the it has been read from a config file. + /// + /// The given mutation resolver. + public void RegisterResolver(MutationResolver resolver) + { + // no op + } + + /// + /// Executes the mutation query and returns result as JSON object asynchronously. + /// + /// name of the GraphQL mutation query. + /// parameters in the mutation query. + /// JSON object result + public async Task Execute(string graphQLMutationName, + IDictionary parameters) + { + throw new NotImplementedException("Mutations against a Microsoft Sql Db are not yet supported."); + } + } +} \ No newline at end of file From 535649ad0f120234127c4f1e585969a4bbe87482 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:02:37 -0700 Subject: [PATCH 54/81] Add SqlMutationEngine service at startup --- ...MutationEngine.cs => SqlMutationEngine.cs} | 25 +++++++------------ .../Cosmos.GraphQL.Service/Startup.cs | 3 ++- 2 files changed, 11 insertions(+), 17 deletions(-) rename Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/{MsSqlMutationEngine.cs => SqlMutationEngine.cs} (66%) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs similarity index 66% rename from Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs rename to Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs index c80053c039..291cc2ff08 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MsSqlMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs @@ -1,33 +1,26 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Text.Json; using System.Threading.Tasks; -using Cosmos.GraphQL.Service.configurations; using Cosmos.GraphQL.Service.Models; -using Cosmos.GraphQL.Service.Resolvers; using Cosmos.GraphQL.Services; using GraphQL.Execution; -using GraphQL.Language.AST; -using Microsoft.Azure.Cosmos; -using Microsoft.CodeAnalysis.CSharp.Scripting; -using Microsoft.CodeAnalysis.Scripting; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Microsoft.Sql.Rest.Utils; namespace Cosmos.GraphQL.Service.Resolvers { - public class MsSqlMutationEngine : IMutationEngine + public class SqlMutationEngine : IMutationEngine { private readonly IDbConnectionService _clientProvider; private readonly IMetadataStoreProvider _metadataStoreProvider; - public MsSqlMutationEngine(IDbConnectionService clientProvider, IMetadataStoreProvider metadataStoreProvider) + /// + /// Constructor. + /// + public SqlMutationEngine(IDbConnectionService clientProvider, IMetadataStoreProvider metadataStoreProvider) { - this._clientProvider = clientProvider; - this._metadataStoreProvider = metadataStoreProvider; + _clientProvider = clientProvider; + _metadataStoreProvider = metadataStoreProvider; } /// @@ -49,7 +42,7 @@ public void RegisterResolver(MutationResolver resolver) public async Task Execute(string graphQLMutationName, IDictionary parameters) { - throw new NotImplementedException("Mutations against a Microsoft Sql Db are not yet supported."); + throw new NotImplementedException("Mutations against Sql Db are not yet supported."); } } -} \ No newline at end of file +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs index 7ee4d64ce6..99e0d9381d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Startup.cs @@ -38,13 +38,14 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); break; case DatabaseType.MsSql: services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); break; default: throw new NotSupportedException(String.Format("The provided DatabaseType value: {0} is currently not supported." + From a8fd8340c7c3a84b285dc68e4fe613e6e1f28cda Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:02:47 -0700 Subject: [PATCH 55/81] Fix summary --- .../Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs index de7cf8bd5e..4fa6bede38 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs @@ -7,7 +7,7 @@ namespace Cosmos.GraphQL.Services { // - // Interface for execution against the backend data source for different queries. + // Interface for execution of GraphQL queries against a database. // public interface IQueryEngine { From 709488e1a4c6a7508348231c05b64ab832e4a1df Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:03:14 -0700 Subject: [PATCH 56/81] Add IMutationEngine to GraphQLService --- .../Cosmos.GraphQL.Service/Services/GraphQLService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 316387821a..ee9c2e9477 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -42,10 +42,10 @@ public MyDocumentWriter(IDocumentWriter internalWriter) private readonly IDocumentWriter _writer; private readonly IQueryEngine _queryEngine; - private readonly MutationEngine _mutationEngine; + private readonly IMutationEngine _mutationEngine; private IMetadataStoreProvider _metadataStoreProvider; - public GraphQLService(IQueryEngine queryEngine, MutationEngine mutationEngine, IMetadataStoreProvider metadataStoreProvider) + public GraphQLService(IQueryEngine queryEngine, IMutationEngine mutationEngine, IMetadataStoreProvider metadataStoreProvider) { this._queryEngine = queryEngine; this._mutationEngine = mutationEngine; From 5b4290cb6a745821a0bcb2848af6b79bbd429f47 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:04:00 -0700 Subject: [PATCH 57/81] CosmosMutationEngine in tests --- .../Cosmos.GraphQL.Service.Tests/SchemaTests.cs | 2 +- .../Cosmos.GraphQL.Service.Tests/TestBase.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs index 2d6cff1f7e..4179fd4b4a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/SchemaTests.cs @@ -21,7 +21,7 @@ public async Task TestAddSchemaAsync() CosmosClientProvider clientProvider = new CosmosClientProvider(); IMetadataStoreProvider metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); CosmosQueryEngine queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - MutationEngine mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); + CosmosMutationEngine mutationEngine = new CosmosMutationEngine(clientProvider, metadataStoreProvider); GraphQLService graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); var graphql_schema = TestHelper.GraphQLTestSchema; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs index 8e3ebe0c83..0295915f72 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/TestBase.cs @@ -23,7 +23,7 @@ public class TestBase internal CosmosClientProvider clientProvider; internal IMetadataStoreProvider metadataStoreProvider; internal CosmosQueryEngine queryEngine; - internal MutationEngine mutationEngine; + internal CosmosMutationEngine mutationEngine; internal GraphQLController controller; public TestBase() @@ -44,7 +44,7 @@ private void Init() metadataStoreProvider = new CachedMetadataStoreProvider(new DocumentMetadataStoreProvider(clientProvider)); queryEngine = new CosmosQueryEngine(clientProvider, metadataStoreProvider); - mutationEngine = new MutationEngine(clientProvider, metadataStoreProvider); + mutationEngine = new CosmosMutationEngine(clientProvider, metadataStoreProvider); graphQLService = new GraphQLService(queryEngine, mutationEngine, metadataStoreProvider); graphQLService.parseAsync(TestHelper.GraphQLTestSchema); controller = new GraphQLController(null, queryEngine, mutationEngine, graphQLService); From e86b1c84f3762936764d733bd035820aac15b2d9 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:06:38 -0700 Subject: [PATCH 58/81] Remove unused code --- .../Resolvers/CosmosMutationEngine.cs | 16 ---------------- .../Services/GraphQLService.cs | 2 +- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs index 266622b126..e5e14f1290 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs @@ -115,21 +115,5 @@ public async Task Execute(string graphQLMutationName, // // result.Data = mimeBundle; // } - - - private async void executeInit() - { - Assembly netStandardAssembly = Assembly.Load("netstandard"); - this.scriptOptions = ScriptOptions.Default - .AddReferences( - Assembly.GetAssembly(typeof(Microsoft.Azure.Cosmos.CosmosClient)), - Assembly.GetAssembly(typeof(JsonObjectAttribute)), - Assembly.GetCallingAssembly(), - netStandardAssembly) - .WithImports( - "Microsoft.Azure.Cosmos", - "Newtonsoft.Json", - "Newtonsoft.Json.Linq"); - } } } \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index ee9c2e9477..1cb6bfd017 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -211,7 +211,7 @@ public void attachMutationResolverToSchema(string mutationName) { this._schema.Mutation.GetField(mutationName).Resolver = new AsyncFieldResolver(context => { - return this._mutationEngine.execute(mutationName, context.Arguments); + return this._mutationEngine.Execute(mutationName, context.Arguments); }); } From 3aed53ccd4d0e1139e180977856010434791a0b2 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:27:03 -0700 Subject: [PATCH 59/81] Add Server to appsettings.json --- .../Cosmos.GraphQL.Service/appsettings.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json index 2601764562..7a7c947199 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/appsettings.json @@ -10,11 +10,12 @@ "DatabaseConnection": { "DatabaseType": "", "Credentials": { - "ServerEndpointUrl": "", - "AuthorizationKey": "", - "Container": "", - "Database": "", - "ConnectionString": "" + "ServerEndpointUrl": "", + "AuthorizationKey": "", + "Server": "", + "Database": "", + "Container": "", + "ConnectionString": "" } } } From a4e8475684a0f56a1a644110fb2ae0809b007f79 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:27:23 -0700 Subject: [PATCH 60/81] Fix project guid of test proj --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln index c88514f918..2fafc0da1d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.31205.134 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service", "Cosmos.GraphQL.Service\Cosmos.GraphQL.Service.csproj", "{208FC26C-A21C-4C96-98EE-F10FDAEAC508}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.GraphQL.Service.Tests", "Cosmos.GraphQL.Service.Tests\Cosmos.GraphQL.Service.Tests.csproj", "{4E50C9B0-818E-4041-B18B-5BB17E4D409F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cosmos.GraphQL.Service.Tests", "Cosmos.GraphQL.Service.Tests\Cosmos.GraphQL.Service.Tests.csproj", "{4E50C9B0-818E-4041-B18B-5BB17E4D409F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 1b656e52efd27c2ca345f885fed888e05cbe7f11 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:28:34 -0700 Subject: [PATCH 61/81] Remove class diagrams from git --- .../Class Diagrams/CosmosQueryEngine.cd | 111 -------------- .../Class Diagrams/SqlQueryEngine.cd | 141 ------------------ 2 files changed, 252 deletions(-) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd deleted file mode 100644 index 892e86671f..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/CosmosQueryEngine.cd +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - AAAAAQAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAAABAAAA= - Resolvers\CosmosClientProvider.cs - - - - - - - - - - AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= - configurations\ConfigurationProvider.cs - - - - - - - - - DAAABAAAEAAACAAAAAAAAkAAAAAgAAAAABAABACAAAA= - Services\DocumentMetadataStoreProvider.cs - - - - - - - - - - - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= - Services\GraphQLService.cs - - - - - - - - - - AAAIAAAAAAAAABQAAAAAAAAAEAAABAAAAAAAAAAAAEA= - Resolvers\CosmosQueryEngine.cs - - - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA= - Resolvers\IClientProvider.cs - - - - - - CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= - Services\IMetadataStoreProvider.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= - configurations\IDatabaseCredentials.cs - - - - - - AAAIAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAEA= - Resolvers\IQueryEngine.cs - - - - \ No newline at end of file diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd deleted file mode 100644 index 2d79452caf..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Class Diagrams/SqlQueryEngine.cd +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - AAAAAAAAAAAAAAAQAAAAAAAAAABAAAYAAAAAAAAEAAA= - configurations\ConfigurationProvider.cs - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAgAAAAA= - configurations\MsSqlCredentials.cs - configurations\MSSQLCredentials.cs - - - - - - - BAAAAAAAAAAAAAAAAAAAAAgAAAAAAIAAAAAAAABAAAA= - Resolvers\MsSqlClientProvider.cs - Resolvers\SQLClientProvider.cs - - - - - - - - - - CAAAJAAAEAAAAAAAAAAAAkACAAAAAAIAABAAAAAAAAA= - Services\FileMetadataStoreProvider.cs - - - - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - Services\GraphQLService.cs - - - - - - AAAACABAAAAAQAAAAAABBAAEggAARCAAAAAAAIAAgMA= - Services\GraphQLService.cs - - - - - - - - - - AAAIAAAgAAAAABQAIAAAAAAAAAAABAAAAAAAAAAAEEA= - Resolvers\SqlQueryEngine.cs - Resolvers\SQLQueryEngine.cs - - - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAACAA= - Resolvers\QueryExecutor.cs - - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA= - Resolvers\IClientProvider.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAA= - configurations\IDatabaseCredentials.cs - - - - - - CAAABAAAEAAAAAAAAAAAAkAAAAAAAAAAABAAAAAAAAA= - Services\IMetadataStoreProvider.cs - - - - - - AAAIAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAEA= - Resolvers\IQueryEngine.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAA= - Resolvers\IQueryExecutor.cs - QueryHandler\IQueryExecutor.cs - - - - - - BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Resolvers\IDbConnectionService.cs - - - - \ No newline at end of file From 2c83fa24f0373030e8695a7fb3ba09c60c638021 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 09:50:00 -0700 Subject: [PATCH 62/81] ignore .cd files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0ad8ec404a..66a4aa4bec 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/.idea/* */.idea/* */bin/* */obj/* +*.cd # Visual Studio 2015 cache/options directory .vs/ \ No newline at end of file From 6a6a8e03958ac27a25e5b1bc18c28ff6c13d29c0 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 10:01:23 -0700 Subject: [PATCH 63/81] New lines --- .gitignore | 4 +--- .../Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs | 2 +- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 66a4aa4bec..324de5ffe2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,7 @@ Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/obj/* Cosmos.GraphQL.Service/Cosmos.GraphQL.Service.Tests/.idea/* */.idea/* -*/bin/* -*/obj/* *.cd # Visual Studio 2015 cache/options directory -.vs/ \ No newline at end of file +.vs/ diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs index e5e14f1290..355c3e9094 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs @@ -116,4 +116,4 @@ public async Task Execute(string graphQLMutationName, // result.Data = mimeBundle; // } } -} \ No newline at end of file +} diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql index 627eef8de4..16c8debad2 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql @@ -16,4 +16,4 @@ type character { type planet { id : ID, name : String -} \ No newline at end of file +} From 571f4971ce9e026069193730b543db27fb2a71d5 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 10:02:24 -0700 Subject: [PATCH 64/81] empty values in config json --- .../Cosmos.GraphQL.Service/config.json | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 8db8e10de3..0fbda63967 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -2,32 +2,11 @@ "GraphQLSchema": "", "Resolvers": [ { - "engine": "SQL", - "id": "characterById", - "databaseName": "StarWars", + "engine": "", + "id": "", + "databaseName": "", "isList": false, - "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM character WHERE [id] = @id" - }, - { - "engine": "SQL", - "id": "characterList", - "databaseName": "StarWars", - "isList": true, - "parametrizedQuery": "SELECT [id], [name], [type], [homePlanet], [primaryFunction] FROM character" - }, - { - "engine": "SQL", - "id": "planetById", - "databaseName": "StarWars", - "isList": false, - "parametrizedQuery": "SELECT [id], [name] FROM planet WHERE [id] = @id" - }, - { - "engine": "SQL", - "id": "planetList", - "databaseName": "StarWars", - "isList": true, - "parametrizedQuery": "SELECT [id], [name] FROM planet" + "parametrizedQuery": "" } ] } From e4d61d6c18703ade835e928d27dcd7fe35d06db0 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde Date: Sun, 19 Sep 2021 11:27:30 -0700 Subject: [PATCH 65/81] Remove unneeded interface --- .../configurations/IConfigurationProvider.cs | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs deleted file mode 100644 index 7f042a0d6d..0000000000 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/IConfigurationProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.configurations -{ - /// - /// Provider for the singleton instance of a connection provider to a specific database - /// - public interface IConfigurationProvider - { - public IConfigurationProvider getInstance(); - } -} From 6b4b4ec623fecd863816c6540afba33bbf0d8bdd Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:23:06 -0700 Subject: [PATCH 66/81] Remove unused using --- .../configurations/MSSQLCredentials.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs index d7236b33c6..52def58eac 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/configurations/MSSQLCredentials.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Cosmos.GraphQL.Service.configurations +namespace Cosmos.GraphQL.Service.configurations { /// /// Representation of MsSql specific credential properties From b86b99698bfaca577f618ecbc0da9ac51549d4ef Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:23:44 -0700 Subject: [PATCH 67/81] Remove unused using --- .../Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs index 09c5fa38f8..eee797e314 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs @@ -4,9 +4,7 @@ using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; using Cosmos.GraphQL.Services; -using GraphQL.Execution; using Microsoft.Azure.Cosmos; -using Microsoft.CodeAnalysis.Scripting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; From 7fd8fb36a3443f679d1af5f4793d3839161aea81 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:24:13 -0700 Subject: [PATCH 68/81] Add await to async task --- .../Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs index fd4ae53388..6a36319e5c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosQueryEngine.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Text.Json; +using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; using Cosmos.GraphQL.Service.Resolvers; using Microsoft.Azure.Cosmos; @@ -88,12 +89,12 @@ public async Task> ExecuteListAsync(string graphQLQuer } } - FeedIterator resultSetIterator = container.GetItemQueryIterator(querySpec); + FeedIterator resultSetIterator = container.GetItemQueryIterator(querySpec); List resultsAsList = new List(); while (resultSetIterator.HasMoreResults) { - var nextPage = resultSetIterator.ReadNextAsync().Result; + var nextPage = await resultSetIterator.ReadNextAsync(); IEnumerator enumerator = nextPage.GetEnumerator(); while (enumerator.MoveNext()) { From 5d01c33bbf74ace651ae81828b9076b64176bf54 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:25:36 -0700 Subject: [PATCH 69/81] Remove isList and use object for hotchocolate --- .../Resolvers/IMutationEngine.cs | 3 +-- .../Resolvers/IQueryEngine.cs | 10 ++-------- .../Resolvers/SQLQueryEngine.cs | 17 ++++------------- .../Resolvers/SqlMutationEngine.cs | 3 +-- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs index d6e51f306c..f9453447de 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs @@ -1,5 +1,4 @@ using Cosmos.GraphQL.Service.Models; -using GraphQL.Execution; using System.Collections.Generic; using System.Threading.Tasks; using System.Text.Json; @@ -24,6 +23,6 @@ public interface IMutationEngine /// parameters in the mutation query. /// JSON object result public Task Execute(string graphQLMutationName, - IDictionary parameters); + IDictionary parameters); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs index 4fa6bede38..571339b597 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryEngine.cs @@ -2,7 +2,6 @@ using System.Text.Json; using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; -using GraphQL.Execution; namespace Cosmos.GraphQL.Services { @@ -19,16 +18,11 @@ public interface IQueryEngine // // Executes the given named graphql query on the backend and expecting a single Json back. // - public Task ExecuteAsync(string graphQLQueryName, IDictionary parameters); + public Task ExecuteAsync(string graphQLQueryName, IDictionary parameters); // // Executes the given named graphql query on the backend and expecting a list of Jsons back. // - public Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters); - - // - // Returns if the given query is a list query. - // - public bool IsListQuery(string queryName); + public Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index d133c74d25..1c0dd3e26d 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; using Cosmos.GraphQL.Service.Resolvers; -using GraphQL.Execution; using Microsoft.Data.SqlClient; using System.Data; @@ -43,7 +42,7 @@ public void RegisterResolver(GraphQLQueryResolver resolver) // // ExecuteAsync the given named graphql query on the backend. // - public async Task ExecuteAsync(string graphQLQueryName, IDictionary parameters) + public async Task ExecuteAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another table @@ -62,7 +61,7 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar { foreach (var parameterEntry in parameters) { - queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value.Value)); + queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value)); } } @@ -92,7 +91,7 @@ public async Task ExecuteAsync(string graphQLQueryName, IDictionar // // Executes the given named graphql query on the backend and expecting a list of Jsons back. // - public async Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters) + public async Task> ExecuteListAsync(string graphQLQueryName, IDictionary parameters) { // TODO: add support for nesting // TODO: add support for join query against another container @@ -111,7 +110,7 @@ public async Task> ExecuteListAsync(string graphQLQuer { foreach (var parameterEntry in parameters) { - queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value.Value)); + queryParameters.Add(new SqlParameter("@" + parameterEntry.Key, parameterEntry.Value)); } } @@ -137,13 +136,5 @@ public async Task> ExecuteListAsync(string graphQLQuer return resultsAsList; } - - // - // Returns if the given query is a list query. - // - public bool IsListQuery(string queryName) - { - return _metadataStoreProvider.GetQueryResolver(queryName).isList; - } } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs index 291cc2ff08..5e8422d10a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Cosmos.GraphQL.Service.Models; using Cosmos.GraphQL.Services; -using GraphQL.Execution; namespace Cosmos.GraphQL.Service.Resolvers { @@ -40,7 +39,7 @@ public void RegisterResolver(MutationResolver resolver) /// parameters in the mutation query. /// JSON object result public async Task Execute(string graphQLMutationName, - IDictionary parameters) + IDictionary parameters) { throw new NotImplementedException("Mutations against Sql Db are not yet supported."); } From 13252ed8bc5ee275d8f049acd97c61c2ab7a4bec Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:26:26 -0700 Subject: [PATCH 70/81] No need to attach resolver for each query field explicitly --- .../Cosmos.GraphQL.Service/Services/GraphQLService.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index c4600f8343..12968f35aa 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -91,14 +91,6 @@ private void InitializeSchemaAndResolvers() if (!string.IsNullOrEmpty(graphqlSchema)) { parseAsync(graphqlSchema); - - // Loop through all the query fields and attach the resolvers for - // each query before hand. - // - foreach (FieldType queryField in Schema.Query.Fields) - { - attachQueryResolverToSchema(queryField.Name); - } } } From afb82dafba0ac80992f42f7f55555d54b1a629cc Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:26:55 -0700 Subject: [PATCH 71/81] Fix naming convention --- .../Services/ResolverMiddleware.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs index 1d0f3249a5..4a782893f3 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs @@ -15,10 +15,10 @@ namespace Cosmos.GraphQL.Services public class ResolverMiddleware { private readonly FieldDelegate _next; - private readonly QueryEngine _queryEngine; - private readonly MutationEngine _mutationEngine; + private readonly IQueryEngine _queryEngine; + private readonly IMutationEngine _mutationEngine; - public ResolverMiddleware(FieldDelegate next, QueryEngine queryEngine, MutationEngine mutationEngine) + public ResolverMiddleware(FieldDelegate next, IQueryEngine queryEngine, IMutationEngine mutationEngine) { _next = next; _queryEngine = queryEngine; @@ -36,7 +36,7 @@ public async Task InvokeAsync(IMiddlewareContext context) { IDictionary parameters = GetParametersFromContext(context); - context.Result = _mutationEngine.execute(context.Selection.Field.Name.Value, parameters).Result; + context.Result = _mutationEngine.Execute(context.Selection.Field.Name.Value, parameters).Result; } if (context.Selection.Field.Coordinate.TypeName.Value == "Query") @@ -45,11 +45,11 @@ public async Task InvokeAsync(IMiddlewareContext context) if (context.Selection.Type.IsListType()) { - context.Result = _queryEngine.executeList(context.Selection.Field.Name.Value, parameters); + context.Result = _queryEngine.ExecuteListAsync(context.Selection.Field.Name.Value, parameters); } else { - context.Result = _queryEngine.execute(context.Selection.Field.Name.Value, parameters); + context.Result = _queryEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters); } } From 14531566328586bab2b2ddc67ce05f24e319a2d6 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 00:03:27 -0700 Subject: [PATCH 72/81] Add comments --- .../Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs | 2 +- .../Resolvers/SqlMutationEngine.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs index 1c0dd3e26d..8fb9f0ce57 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SQLQueryEngine.cs @@ -36,7 +36,7 @@ public SqlQueryEngine(IMetadataStoreProvider metadataStoreProvider, IQueryExecut public void RegisterResolver(GraphQLQueryResolver resolver) { // Registration of Resolvers is already done at startup. - // _metadataStoreProvider.StoreQueryResolver(resolver); + // no-op } // diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs index 5e8422d10a..c2818d0c54 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs @@ -7,6 +7,9 @@ namespace Cosmos.GraphQL.Service.Resolvers { + /// + /// Implements the mutation engine interface for mutations against Sql like databases. + /// public class SqlMutationEngine : IMutationEngine { private readonly IDbConnectionService _clientProvider; @@ -23,8 +26,8 @@ public SqlMutationEngine(IDbConnectionService clientProvider, IMetadataStoreProv } /// - /// Persists resolver configuration. This is a no-op for MsSql - /// since the it has been read from a config file. + /// Persists resolver configuration. This is a no-op for Sql like databases + /// since it has been read from a config file. /// /// The given mutation resolver. public void RegisterResolver(MutationResolver resolver) @@ -41,7 +44,7 @@ public void RegisterResolver(MutationResolver resolver) public async Task Execute(string graphQLMutationName, IDictionary parameters) { - throw new NotImplementedException("Mutations against Sql Db are not yet supported."); + throw new NotImplementedException("Mutations against Sql like databases are not yet supported."); } } } From 0580f263bd8e50fbfa41a2a725bb295b1496bdcd Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 00:16:48 -0700 Subject: [PATCH 73/81] Add comments --- .../Cosmos.GraphQL.Service/Services/GraphQLService.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs index 12968f35aa..09ce740ee9 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/GraphQLService.cs @@ -19,10 +19,15 @@ public class GraphQLService public GraphQLService(IQueryEngine queryEngine, IMutationEngine mutationEngine, IMetadataStoreProvider metadataStoreProvider) { - this._queryEngine = queryEngine; - this._mutationEngine = mutationEngine; - this._metadataStoreProvider = metadataStoreProvider; + _queryEngine = queryEngine; + _mutationEngine = mutationEngine; + _metadataStoreProvider = metadataStoreProvider; + // For CosmosDB, we need to provide the schema and resolver to a POST endpoint after + // startup before executing the GraphQL queries. + // For Sql-like databases, where the schema is known upfront, it is initialized + // from predefined config files. + // if (ConfigurationProvider.getInstance().DbType != DatabaseType.Cosmos) { InitializeSchemaAndResolvers(); From 14dd0de9ce4834204253c0651cde9b090354d3a6 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 00:17:27 -0700 Subject: [PATCH 74/81] Async renames --- .../Resolvers/CosmosMutationEngine.cs | 9 +++++---- .../Resolvers/IDbConnectionService.cs | 2 +- .../Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs | 2 +- .../Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs | 2 +- .../Resolvers/SqlMutationEngine.cs | 2 +- .../Services/ResolverMiddleware.cs | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs index eee797e314..80bd47ddcc 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/CosmosMutationEngine.cs @@ -33,7 +33,7 @@ public void RegisterResolver(MutationResolver resolver) this._metadataStoreProvider.StoreMutationResolver(resolver); } - private JObject execute(IDictionary inputDict, MutationResolver resolver) + private async Task executeAsync(IDictionary inputDict, MutationResolver resolver) { // TODO: add support for all mutation types // we only support CreateOrUpdate (Upsert) for now @@ -56,7 +56,8 @@ private JObject execute(IDictionary inputDict, MutationResolver .GetContainer(resolver.containerName); // TODO: check insertion type - JObject res = container.UpsertItemAsync(jObject).Result.Resource; + var response = await container.UpsertItemAsync(jObject); + JObject res = response.Resource; return res; } @@ -66,14 +67,14 @@ private JObject execute(IDictionary inputDict, MutationResolver /// name of the GraphQL mutation query. /// parameters in the mutation query. /// JSON object result - public async Task Execute(string graphQLMutationName, + public async Task ExecuteAsync(string graphQLMutationName, IDictionary parameters) { var resolver = _metadataStoreProvider.GetMutationResolver(graphQLMutationName); // TODO: we are doing multiple round of serialization/deserialization // fixme - JObject jObject = execute(parameters, resolver); + JObject jObject = await executeAsync(parameters, resolver); return JsonDocument.Parse(jObject.ToString()); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs index 332f80dd31..1008409f29 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs @@ -14,6 +14,6 @@ public interface IDbConnectionService : IClientProvider /// /// Database name. /// Opened sql connection. - public Task GetOpenedConnection(string databaseName = ""); + public Task GetOpenedConnectionAsync(string databaseName = ""); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs index f9453447de..92ac33f37e 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IMutationEngine.cs @@ -22,7 +22,7 @@ public interface IMutationEngine /// name of the GraphQL mutation query. /// parameters in the mutation query. /// JSON object result - public Task Execute(string graphQLMutationName, + public Task ExecuteAsync(string graphQLMutationName, IDictionary parameters); } } diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs index d54061e245..1ef55dd6bd 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/QueryExecutor.cs @@ -33,7 +33,7 @@ public QueryExecutor(IDbConnectionService clientProvider) /// DbDataReader object for reading the result set. public async Task ExecuteQueryAsync(string sqltext, string databaseName, List parameters) { - DbConnection conn = await _clientProvider.GetOpenedConnection(databaseName); + DbConnection conn = await _clientProvider.GetOpenedConnectionAsync(databaseName); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = sqltext; cmd.CommandType = CommandType.Text; diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs index c2818d0c54..078f1d8c17 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/SqlMutationEngine.cs @@ -41,7 +41,7 @@ public void RegisterResolver(MutationResolver resolver) /// name of the GraphQL mutation query. /// parameters in the mutation query. /// JSON object result - public async Task Execute(string graphQLMutationName, + public async Task ExecuteAsync(string graphQLMutationName, IDictionary parameters) { throw new NotImplementedException("Mutations against Sql like databases are not yet supported."); diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs index 4a782893f3..af6d7652a8 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs @@ -36,7 +36,7 @@ public async Task InvokeAsync(IMiddlewareContext context) { IDictionary parameters = GetParametersFromContext(context); - context.Result = _mutationEngine.Execute(context.Selection.Field.Name.Value, parameters).Result; + context.Result = _mutationEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters).Result; } if (context.Selection.Field.Coordinate.TypeName.Value == "Query") From 62ffd8bc540a0871b351c1b0e1c173eb95533b6a Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 00:17:44 -0700 Subject: [PATCH 75/81] Async renames --- .../Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs index f76bcdfc16..e679351c5b 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/MSSQLClientProvider.cs @@ -28,7 +28,7 @@ public MsSqlClientProvider() /// public DbConnection GetClient() { - return GetOpenedConnection().Result; + return GetOpenedConnectionAsync().Result; } /// @@ -37,7 +37,7 @@ public DbConnection GetClient() /// Database name, optional. If not provided, the connection string /// from appsettings is used. /// Opened sql connection. - public async Task GetOpenedConnection(string databaseName = "") + public async Task GetOpenedConnectionAsync(string databaseName = "") { string connString = _sqlCredentials.ConnectionString; From ee9b2452fb938eabbbf55e6498c10aedd3baa383 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 01:24:11 -0700 Subject: [PATCH 76/81] Use await with async --- .../Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs index af6d7652a8..6a1b9ec9cf 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs @@ -45,11 +45,11 @@ public async Task InvokeAsync(IMiddlewareContext context) if (context.Selection.Type.IsListType()) { - context.Result = _queryEngine.ExecuteListAsync(context.Selection.Field.Name.Value, parameters); + context.Result = await _queryEngine.ExecuteListAsync(context.Selection.Field.Name.Value, parameters); } else { - context.Result = _queryEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters); + context.Result = await _queryEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters); } } From c8779090f3f924a30981ae58baf81366f98b91a8 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 01:36:34 -0700 Subject: [PATCH 77/81] isList is not required anymore --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json | 1 - 1 file changed, 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 0fbda63967..18233b3d9a 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -5,7 +5,6 @@ "engine": "", "id": "", "databaseName": "", - "isList": false, "parametrizedQuery": "" } ] From c923185ebab0b589290dd9ee03e7faa905a0ead5 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 12:53:19 -0700 Subject: [PATCH 78/81] For Pg/Sql only --- .../Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs | 3 ++- .../Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs index 1008409f29..c409aa102c 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IDbConnectionService.cs @@ -4,7 +4,8 @@ namespace Cosmos.GraphQL.Service.Resolvers { /// - /// Interface representing services for managing the database connection. + /// Interface representing services for managing the database connection for Sql like databases + /// e.g. MsSql, PostgredSql /// public interface IDbConnectionService : IClientProvider { diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs index 4bbe911c25..346ab89636 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Resolvers/IQueryExecutor.cs @@ -6,7 +6,7 @@ namespace Cosmos.GraphQL.Service.Resolvers { /// - /// Interface for query execution. + /// Interface for query execution for Sql like databases (eg. MsSql, PostgresSql). /// public interface IQueryExecutor { From 2496d15654df41de72ae6e194e20a3a7fe101078 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 12:53:28 -0700 Subject: [PATCH 79/81] Use async --- .../Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs index 6a1b9ec9cf..de84df600f 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/Services/ResolverMiddleware.cs @@ -36,7 +36,7 @@ public async Task InvokeAsync(IMiddlewareContext context) { IDictionary parameters = GetParametersFromContext(context); - context.Result = _mutationEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters).Result; + context.Result = await _mutationEngine.ExecuteAsync(context.Selection.Field.Name.Value, parameters); } if (context.Selection.Field.Coordinate.TypeName.Value == "Query") From 08d4b9efcfc6249a89612a88a40dd0c83fd1537e Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 12:53:47 -0700 Subject: [PATCH 80/81] containerName and tableName --- Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json index 18233b3d9a..88c2eb5137 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/config.json @@ -5,6 +5,8 @@ "engine": "", "id": "", "databaseName": "", + "containerName": "", + "tableName": "", "parametrizedQuery": "" } ] From 7f9c35974c44c3453c55b933746a6cbe7777de84 Mon Sep 17 00:00:00 2001 From: Aniruddh Munde <3513779+Aniruddh25@users.noreply.github.com> Date: Wed, 22 Sep 2021 12:54:07 -0700 Subject: [PATCH 81/81] PascalCase for gql --- .../Cosmos.GraphQL.Service/schema.gql | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql index 16c8debad2..1234a1d6f1 100644 --- a/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql +++ b/Cosmos.GraphQL.Service/Cosmos.GraphQL.Service/schema.gql @@ -1,11 +1,11 @@ -type Query { - characterList: [character] - characterById (id : ID!): character - planetById (id: ID!): planet - planetList: [planet] - } +type Query { + characterList: [Character] + characterById (id : ID!): Character + planetById (id: ID!): Planet + planetList: [Planet] + } -type character { +type Character { id : ID, name : String, type: String, @@ -13,7 +13,7 @@ type character { primaryFunction: String } -type planet { +type Planet { id : ID, name : String }