├── installers ├── docker │ ├── .gitignore │ └── .dockerignore ├── msi │ └── .gitignore ├── winget │ ├── .gitignore │ └── grate │ │ └── manifests │ │ └── e │ │ └── erikbra │ │ └── grate │ │ ├── 0.10.0 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 0.10.1 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 0.11.0 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 0.9.4 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 0.9.5 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 0.9.6 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 1.0.0 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ ├── 1.1.0 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml │ │ └── 1.2.0 │ │ ├── erikbra.grate.yaml │ │ ├── erikbra.grate.locale.en-US.yaml │ │ └── erikbra.grate.installer.yaml ├── deb │ ├── .gitignore │ └── template │ │ └── DEBIAN │ │ ├── prerm │ │ ├── postinst │ │ └── control └── chocolatey │ ├── .gitignore │ ├── grate │ └── tools │ │ └── VERIFICATION.txt │ └── Create-Package.ps1 ├── examples ├── docker │ ├── output │ │ └── .gitignore │ ├── db │ │ ├── views │ │ │ └── test.sql │ │ ├── runFirstAfterUp │ │ │ └── 001_greeting.sql │ │ └── up │ │ │ └── 001_create_table.sql │ ├── build-and-run.ps1 │ ├── readme.md │ └── docker-compose.yml ├── scripts │ └── sqlite │ │ ├── up │ │ └── 01_up_one_time_script.sql │ │ ├── indexes │ │ └── index1_will_run_when_changed.sql │ │ ├── sprocs │ │ └── sproc1_will_run_when_changed.sql │ │ ├── views │ │ └── view1_will_run_when_changed.sql │ │ ├── functions │ │ └── function1_will_run_when_changed.sql │ │ ├── runAfterCreateDatabase │ │ └── 01_after_create_c.sql │ │ ├── triggers │ │ └── trigger1_will_run_when_changed.sql │ │ ├── beforeMigration │ │ └── 01_before_this_will_run_every_time.sql │ │ ├── permissions │ │ └── fix_permissions_will_be_run_every_time.sql │ │ ├── runFirstAfterUp │ │ └── 01_first_after_up_one_time_script.sql │ │ ├── afterMigration │ │ └── after_migration_will_be_run_every_time.sql │ │ ├── alterDatabase │ │ └── 01_alter_this_will_run_any_time_it_is_changed.sql │ │ ├── runBeforeUp │ │ └── 01_before_up_this_will_run_any_time_it_is_changed.sql │ │ └── runAfterOtherAnyTimeScripts │ │ └── 01_after_other_this_will_when_changed.sql ├── github-actions │ └── grate-workflow.yml ├── k8s │ ├── initcontainer │ │ ├── sql │ │ │ ├── views │ │ │ │ └── test.sql │ │ │ ├── runFirstAfterUp │ │ │ │ └── 001_greeting.sql │ │ │ └── up │ │ │ │ └── 001_create_table.sql │ │ ├── sample-service │ │ │ ├── Program.cs │ │ │ ├── appsettings.json │ │ │ ├── sample-service.csproj │ │ │ └── Controllers │ │ │ │ └── GrateController.cs │ │ ├── Dockerfile-db │ │ └── Dockerfile │ └── multitenancy │ │ ├── sql │ │ ├── views │ │ │ └── test.sql │ │ ├── runFirstAfterUp │ │ │ └── 001_greeting.sql │ │ └── up │ │ │ └── 001_create_table.sql │ │ ├── Dockerfile-db │ │ ├── sample-service │ │ ├── sample-service.csproj │ │ ├── appsettings.json │ │ ├── Extensions │ │ │ └── ConnectionStringExtension.cs │ │ ├── Program.cs │ │ └── Controllers │ │ │ └── GrateController.cs │ │ ├── Dockerfile │ │ └── script │ │ └── migrate.sh ├── local │ ├── db │ │ ├── up │ │ │ ├── 002-Add-Test-Data.ENV.Test.sql │ │ │ ├── 003-Add-Deleted-Column.sql │ │ │ └── 001-Create-TestTable.sql │ │ ├── views │ │ │ └── vw_CurrentTestData.sql │ │ ├── sprocs │ │ │ └── sp_GetTestById.sql │ │ └── indexes │ │ │ └── ix_TestData_Name.sql │ └── run-migration.ps1 └── test-integration │ └── sample-test-integration │ ├── SampleDatabase │ ├── readme.md │ ├── db │ │ └── sprocs │ │ │ └── 000_sample_proc.sql │ └── SampleDatabase.csproj │ ├── global.json │ ├── readme.md │ └── Tests │ └── DatabaseTest.cs ├── test-infra └── terraform │ ├── .gitignore │ ├── test-environment │ ├── resource-group.tf │ ├── aca-env.tf │ ├── db-passwords.tf │ ├── main.tf │ ├── variables.tf │ └── aca-env-subnets.tf │ └── init │ ├── locals.tf │ ├── variables.tf │ ├── github.tf │ ├── resource-group.tf │ ├── README.md │ ├── tfstate-storage-container.tf │ └── main.tf ├── unittests ├── TestCommon │ ├── Usings.cs │ └── TestInfrastructure │ │ ├── GrateTestConfig.cs │ │ ├── GrateMigratorExtensions.cs │ │ ├── SqlStatements.cs │ │ ├── Net6PolyFills.cs │ │ ├── TestDatabaseFixture.cs │ │ ├── ITestDatabase.cs │ │ ├── DescriptiveTestObjects.cs │ │ └── RandomExtensions.cs ├── Basic_tests │ ├── GlobalUsings.cs │ ├── Startup.cs │ ├── xunit.runner.json │ ├── Infrastructure │ │ ├── HashGenerator_.cs │ │ └── MockDbMigratorLogger.cs │ └── DependencyInjection │ │ └── AddGrate.cs ├── MariaDB │ ├── Usings.cs │ ├── xunit.runner.json │ ├── MigrationTables.cs │ ├── Database.cs │ ├── Running_MigrationScripts │ │ ├── ScriptsRun_Table.cs │ │ ├── TokenScripts.cs │ │ ├── DropDatabase.cs │ │ ├── Anytime_scripts.cs │ │ ├── Everytime_scripts.cs │ │ ├── One_time_scripts.cs │ │ ├── Order_Of_Scripts.cs │ │ ├── Environment_scripts.cs │ │ ├── Versioning_The_Database.cs │ │ ├── Run_After_Create_Database_scripts.cs │ │ └── Failing_Scripts.cs │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_structure_is_not_latest_version.cs │ │ └── When_Grate_internal_structure_does_not_exist.cs │ ├── Reported_issues │ │ └── Non_ascii_characters_in_script │ │ │ ├── ScriptsRunTable.cs │ │ │ └── ScriptsRunErrorsTable.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── TestInfrastructure │ │ └── InspectableMariaDbDatabase.cs │ └── Startup.cs ├── Oracle │ ├── Usings.cs │ ├── xunit.runner.json │ ├── Database.cs │ ├── Running_MigrationScripts │ │ ├── Order_Of_Scripts.cs │ │ ├── ScriptsRun_Table.cs │ │ ├── Everytime_scripts.cs │ │ ├── DropDatabase.cs │ │ ├── Anytime_scripts.cs │ │ ├── Environment_scripts.cs │ │ ├── Run_After_Create_Database_scripts.cs │ │ ├── One_time_scripts.cs │ │ ├── TokenScripts.cs │ │ └── Versioning_The_Database.cs │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_structure_is_not_latest_version.cs │ │ └── When_Grate_internal_structure_does_not_exist.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── Reported_issues │ │ └── Non_ascii_characters_in_script │ │ │ ├── ScriptsRunTable.cs │ │ │ └── ScriptsRunErrorsTable.cs │ ├── Startup.cs │ ├── Basic_tests │ │ └── StatementSplitter_.cs │ └── MigrationTables.cs ├── Sqlite │ ├── Usings.cs │ ├── xunit.runner.json │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_already_exists.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_internal_structure_does_not_exist.cs │ │ └── When_Grate_structure_is_not_latest_version.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── Running_MigrationScripts │ │ ├── DropDatabase.cs │ │ ├── TokenScripts.cs │ │ ├── One_time_scripts.cs │ │ ├── Order_Of_Scripts.cs │ │ ├── Anytime_scripts.cs │ │ ├── Everytime_scripts.cs │ │ ├── ScriptsRun_Table.cs │ │ ├── Environment_scripts.cs │ │ └── Versioning_The_Database.cs │ ├── Reported_issues │ │ └── Reported_issues │ │ │ └── Non_ascii_characters_in_script │ │ │ ├── ScriptsRunTable.cs │ │ │ └── ScriptsRunErrorsTable.cs │ ├── MigrationTables.cs │ └── Startup.cs ├── SqlServer │ ├── Usings.cs │ ├── xunit.runner.json │ ├── Running_MigrationScripts │ │ ├── SqlServerScriptsBase.cs │ │ ├── DropDatabase.cs │ │ ├── One_time_scripts.cs │ │ ├── Order_Of_Scripts.cs │ │ ├── ScriptsRun_Table.cs │ │ ├── TokenScripts.cs │ │ ├── Anytime_scripts.cs │ │ ├── Everytime_scripts.cs │ │ ├── Environment_scripts.cs │ │ ├── Versioning_The_Database.cs │ │ └── Run_After_Create_Database_scripts.cs │ ├── TestInfrastructure │ │ └── InspectableSqlServerDatabase.cs │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_internal_structure_is_changed.cs │ │ ├── When_Grate_structure_is_not_latest_version.cs │ │ └── When_Grate_internal_structure_does_not_exist.cs │ ├── Reported_issues │ │ └── Non_ascii_characters_in_script │ │ │ ├── ScriptsRunTable.cs │ │ │ └── ScriptsRunErrorsTable.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── MigrationTables.cs │ ├── Basic_tests │ │ ├── StatementSplitter_.cs │ │ └── TokenReplacerTests.cs │ └── Startup.cs ├── SqlServerCaseSensitive │ ├── Usings.cs │ ├── xunit.runner.json │ ├── Database.cs │ ├── Running_MigrationScripts │ │ ├── SqlServerScriptsBase.cs │ │ ├── TokenScripts.cs │ │ ├── DropDatabase.cs │ │ ├── Anytime_scripts.cs │ │ ├── Everytime_scripts.cs │ │ ├── ScriptsRun_Table.cs │ │ ├── One_time_scripts.cs │ │ ├── Order_Of_Scripts.cs │ │ ├── Environment_scripts.cs │ │ ├── Versioning_The_Database.cs │ │ └── Run_After_Create_Database_scripts.cs │ ├── TestInfrastructure │ │ └── InspectableSqlServerDatabase.cs │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_internal_structure_does_not_exist.cs │ │ └── When_Grate_structure_is_not_latest_version.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── MigrationTables.cs │ ├── Basic_tests │ │ ├── StatementSplitter_.cs │ │ └── TokenReplacerTests.cs │ └── Startup.cs ├── PostgreSQL │ ├── Usings.cs │ ├── xunit.runner.json │ ├── Database.cs │ ├── MigrationTables.cs │ ├── Running_MigrationScripts │ │ ├── DropDatabase.cs │ │ ├── TokenScripts.cs │ │ ├── ScriptsRun_Table.cs │ │ ├── One_time_scripts.cs │ │ ├── Order_Of_Scripts.cs │ │ ├── Environment_scripts.cs │ │ ├── Versioning_The_Database.cs │ │ ├── Anytime_scripts.cs │ │ └── Run_After_Create_Database_scripts.cs │ ├── Bootstrapping │ │ ├── Grate_Internal_Scripts.cs │ │ ├── When_Grate_structure_does_not_exist.cs │ │ ├── When_Grate_structure_already_exists.cs │ │ ├── When_Grate_structure_is_not_latest_version.cs │ │ └── When_Grate_internal_structure_does_not_exist.cs │ ├── Reported_issues │ │ └── Non_ascii_characters_in_script │ │ │ ├── ScriptsRunTable.cs │ │ │ └── ScriptsRunErrorsTable.cs │ ├── DependencyInjection │ │ └── ServiceCollectionTest.cs │ ├── Startup.cs │ └── Statement_Splitting │ │ └── NpgsqlQueryParser_.cs ├── CommandLine │ ├── CommandLine.Common │ │ ├── GrateExecutablePathAttribute.cs │ │ ├── Startup.cs │ │ └── Startup_T.cs │ ├── CommandLine.MariaDB │ │ └── Startup.cs │ ├── CommandLine.SqlServer │ │ └── Startup.cs │ ├── CommandLine.Sqlite │ │ └── Startup.cs │ ├── CommandLine.PostgreSQL │ │ └── Startup.cs │ ├── CommandLine.Oracle │ │ └── Startup.cs │ └── IncludeTests.targets └── Docker │ ├── Docker.MariaDB │ └── Startup.cs │ ├── Docker.SqlServer │ └── Startup.cs │ ├── Docker.Sqlite │ └── Startup.cs │ ├── Docker.PostgreSQL │ └── Startup.cs │ ├── Docker.Oracle │ └── Startup.cs │ └── IncludeTests.targets ├── docs ├── _sass │ └── custom │ │ └── custom.scss ├── _config.yml ├── ScriptTypes │ └── index.md └── ConfigurationOptions │ └── ResponseFiles.md ├── GitVersion.yml ├── global.json ├── src ├── grate.core │ ├── Migration │ │ ├── ConnectionType.cs │ │ ├── TransactionHandling.cs │ │ ├── MigrationResult.cs │ │ └── IGrateMigrator.cs │ ├── Infrastructure │ │ ├── IHashGenerator.cs │ │ ├── TokenExtensions.cs │ │ ├── EnumerableExtensions.cs │ │ ├── ISyntax.cs │ │ ├── BatchSplitterReplacer.cs │ │ └── TokenReplacer.cs │ ├── Configuration │ │ ├── MigrationType.cs │ │ ├── MigrationStatus.cs │ │ ├── IFoldersConfiguration.cs │ │ ├── IKnownFolderNames.cs │ │ └── GrateConfigurationBuilder.Factory.cs │ └── Exceptions │ │ ├── InvalidFolderConfiguration.cs │ │ ├── OneTimeScriptChanged.cs │ │ ├── UnknownConnectionType.cs │ │ ├── UnknownTransactionHandling.cs │ │ └── MigrationException.cs ├── grate.mariadb │ ├── Bootstrapping │ │ └── Sql │ │ │ ├── GrateStructure │ │ │ └── up │ │ │ │ ├── 01c_version_add_status_column_calling_store_proc.sql │ │ │ │ ├── 00_02b_fix_version_table_casing_calling_proc.sql │ │ │ │ ├── 01d_version_add_status_column_drop_store_proc.sql │ │ │ │ ├── 00_02c_fix_version_table_casing_drop_proc.sql │ │ │ │ ├── 00_03b_fix_scriptsrun_table_casing_calling_proc.sql │ │ │ │ ├── 00_03c_fix_scriptsrun_table_casing_drop_proc.sql │ │ │ │ ├── 00_03b_fix_scriptsrunerrors_table_casing_calling_proc.sql │ │ │ │ ├── 00_03c_fix_scriptsrunerrors_table_casing_drop_proc.sql │ │ │ │ ├── 02_scripts_run_unicode_support.sql │ │ │ │ ├── 03_version_table_unicode_support.sql │ │ │ │ ├── 03_scripts_run_errors_unicode_support.sql │ │ │ │ ├── 01b_version_add_status_column.sql │ │ │ │ ├── 00_02a_fix_version_table_casing.sql │ │ │ │ ├── 00_03a_fix_scriptsrun_table_casing.sql │ │ │ │ └── 00_03a_fix_scriptsrunerrors_table_casing.sql │ │ │ └── Baseline │ │ │ └── up │ │ │ ├── 04_create_version_table.sql │ │ │ ├── 02_create_scripts_run_table.sql │ │ │ └── 03_create_scripts_run_errors_table.sql │ ├── grate.mariadb.csproj │ ├── DependencyInjection │ │ └── RegistrationExtensions.cs │ └── Infrastructure │ │ └── MariaDbScriptFailed.cs ├── grate.postgresql │ ├── Bootstrapping │ │ └── Sql │ │ │ ├── GrateStructure │ │ │ └── up │ │ │ │ ├── 01_version_add_status_column.sql │ │ │ │ ├── 00_01_fix_schema_casing.sql │ │ │ │ ├── 00_02_fix_version_table_casing.sql │ │ │ │ ├── 00_03_fix_scriptsrun_table_casing.sql │ │ │ │ └── 00_03_fix_scriptsrunerrors_table_casing.sql │ │ │ └── Baseline │ │ │ └── up │ │ │ ├── 01_create_schema_grate.ENV.GrateInternalBoostrap-a61456d0-e00a-4933-b692-c6a5d7d51539.sql │ │ │ ├── 04_create_version_table.sql │ │ │ ├── 02_create_scripts_run_table.sql │ │ │ └── 03_create_scripts_run_errors_table.sql │ ├── Infrastructure │ │ └── Npgsql │ │ │ ├── DummyPlaceholderType.cs │ │ │ ├── DummyNpgsqlParameter.cs │ │ │ ├── DummyNpgsqlCommand.cs │ │ │ ├── DummyThrowHelper.cs │ │ │ ├── DummyNpgsqlParameterCollection.cs │ │ │ └── DummyBatchCommand.cs │ ├── grate.postgresql.csproj │ └── DependencyInjection │ │ └── RegistrationExtensions.cs ├── grate.sqlserver │ ├── Bootstrapping │ │ └── Sql │ │ │ ├── GrateStructure │ │ │ └── up │ │ │ │ ├── 02_scripts_run_unicode_support.sql │ │ │ │ ├── 01_version_add_status_column.sql │ │ │ │ └── 03_scripts_run_errors_unicode_support.sql │ │ │ └── Baseline │ │ │ └── up │ │ │ ├── 01_create_schema_grate.ENV.GrateInternalBoostrap-a61456d0-e00a-4933-b692-c6a5d7d51539.sql │ │ │ ├── 04_create_version_table.sql │ │ │ ├── 02_create_scripts_run_table.sql │ │ │ └── 03_create_scripts_run_errors_table.sql │ ├── grate.sqlserver.csproj │ └── DependencyInjection │ │ └── RegistrationExtensions.cs ├── grate │ ├── Configuration │ │ ├── DatabaseType.cs │ │ ├── CommandLineGrateConfiguration.cs │ │ ├── CommandLineGrateEnvironment.cs │ │ └── ArgumentParsers.cs │ └── Infrastructure │ │ └── CliCommandsExtensions.cs ├── grate.oracle │ ├── Bootstrapping │ │ └── Sql │ │ │ ├── GrateStructure │ │ │ └── up │ │ │ │ └── 01_version_add_status_column.sql │ │ │ └── Baseline │ │ │ └── up │ │ │ ├── 04_create_version_table.sql │ │ │ ├── 02_create_scripts_run_table.sql │ │ │ └── 03_create_scripts_run_errors_table.sql │ ├── grate.oracle.csproj │ └── DependencyInjection │ │ └── RegistrationExtensions.cs └── grate.sqlite │ ├── Bootstrapping │ └── Sql │ │ └── Baseline │ │ └── up │ │ ├── 04_create_version_table.sql │ │ ├── 02_create_scripts_run_table.sql │ │ └── 03_create_scripts_run_errors_table.sql │ ├── grate.sqlite.csproj │ └── DependencyInjection │ └── RegistrationExtensions.cs ├── .github ├── dependabot.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── .devcontainer └── devcontainer.json /installers/docker/.gitignore: -------------------------------------------------------------------------------- 1 | grate -------------------------------------------------------------------------------- /examples/docker/output/.gitignore: -------------------------------------------------------------------------------- 1 | * -------------------------------------------------------------------------------- /installers/msi/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | wix -------------------------------------------------------------------------------- /installers/winget/.gitignore: -------------------------------------------------------------------------------- 1 | winget -------------------------------------------------------------------------------- /installers/deb/.gitignore: -------------------------------------------------------------------------------- 1 | debian 2 | *.deb -------------------------------------------------------------------------------- /test-infra/terraform/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform -------------------------------------------------------------------------------- /installers/chocolatey/.gitignore: -------------------------------------------------------------------------------- 1 | **/*.nupkg 2 | **/*.exe -------------------------------------------------------------------------------- /installers/docker/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .gitignore -------------------------------------------------------------------------------- /unittests/TestCommon/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | -------------------------------------------------------------------------------- /unittests/Basic_tests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | -------------------------------------------------------------------------------- /examples/scripts/sqlite/up/01_up_one_time_script.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /docs/_sass/custom/custom.scss: -------------------------------------------------------------------------------- 1 | .main-content dt { 2 | text-align: default; 3 | } -------------------------------------------------------------------------------- /examples/docker/db/views/test.sql: -------------------------------------------------------------------------------- 1 | create or alter view test as 2 | select 1 as test; -------------------------------------------------------------------------------- /examples/github-actions/grate-workflow.yml: -------------------------------------------------------------------------------- 1 | ../../.github/workflows/grate-workflow.yml -------------------------------------------------------------------------------- /examples/scripts/sqlite/indexes/index1_will_run_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/sprocs/sproc1_will_run_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/views/view1_will_run_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /unittests/MariaDB/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using Xunit.Abstractions; 3 | -------------------------------------------------------------------------------- /unittests/Oracle/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using Xunit.Abstractions; 3 | -------------------------------------------------------------------------------- /unittests/Sqlite/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using Xunit.Abstractions; 3 | -------------------------------------------------------------------------------- /examples/scripts/sqlite/functions/function1_will_run_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/runAfterCreateDatabase/01_after_create_c.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/triggers/trigger1_will_run_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /unittests/SqlServer/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using Xunit.Abstractions; 3 | -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sql/views/test.sql: -------------------------------------------------------------------------------- 1 | create or alter view test as 2 | select 1 as test; -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sql/views/test.sql: -------------------------------------------------------------------------------- 1 | create or alter view test as 2 | select 1 as test; -------------------------------------------------------------------------------- /examples/scripts/sqlite/beforeMigration/01_before_this_will_run_every_time.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/permissions/fix_permissions_will_be_run_every_time.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/runFirstAfterUp/01_first_after_up_one_time_script.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using Xunit.Abstractions; 3 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | branches: 2 | master: 3 | regex: (^master$|^origin\/master$|^main$|^origin\/main$) 4 | -------------------------------------------------------------------------------- /examples/scripts/sqlite/afterMigration/after_migration_will_be_run_every_time.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/alterDatabase/01_alter_this_will_run_any_time_it_is_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/scripts/sqlite/runBeforeUp/01_before_up_this_will_run_any_time_it_is_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/docker/db/runFirstAfterUp/001_greeting.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO grate_test(name) VALUES ('Hello grate from docker !'); -------------------------------------------------------------------------------- /examples/scripts/sqlite/runAfterOtherAnyTimeScripts/01_after_other_this_will_when_changed.sql: -------------------------------------------------------------------------------- 1 | SELECT sqlite_version(); -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sql/runFirstAfterUp/001_greeting.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO grate_test(name) VALUES ('Hello grate from k8s!'); -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sql/runFirstAfterUp/001_greeting.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO grate_test(name) VALUES ('Hello grate from k8s!'); -------------------------------------------------------------------------------- /examples/local/db/up/002-Add-Test-Data.ENV.Test.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into TestTable (Name) values 3 | ('Tom'), 4 | ('Dick'), 5 | ('Harry'); 6 | -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/SampleDatabase/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Your grate database project. Nothing fancy needed here. -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "10.0.0", 4 | "rollForward": "major", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /unittests/PostgreSQL/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Testcontainers.PostgreSql; 2 | global using Xunit; 3 | global using Xunit.Abstractions; 4 | -------------------------------------------------------------------------------- /examples/docker/build-and-run.ps1: -------------------------------------------------------------------------------- 1 | #!/bin/env pwsh 2 | 3 | # App versioning is normally provided by your CI/CD pipelines... 4 | docker-compose up -------------------------------------------------------------------------------- /examples/local/db/views/vw_CurrentTestData.sql: -------------------------------------------------------------------------------- 1 | create or alter view vw_CurrentTestData 2 | as 3 | 4 | select * from TestTable where IsDeleted = 0; -------------------------------------------------------------------------------- /src/grate.core/Migration/ConnectionType.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Migration; 2 | 3 | public enum ConnectionType 4 | { 5 | Default, 6 | Admin 7 | } 8 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/01c_version_add_status_column_calling_store_proc.sql: -------------------------------------------------------------------------------- 1 | CALL create_{{SchemaName}}_{{VersionTable}}(); -------------------------------------------------------------------------------- /unittests/Basic_tests/Startup.cs: -------------------------------------------------------------------------------- 1 | namespace Basic_tests; 2 | 3 | // ReSharper disable once UnusedType.Global 4 | public class Startup 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_02b_fix_version_table_casing_calling_proc.sql: -------------------------------------------------------------------------------- 1 | CALL create_{{SchemaName}}_fix_version_table_casing(); -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/01d_version_add_status_column_drop_store_proc.sql: -------------------------------------------------------------------------------- 1 | DROP PROCEDURE create_{{SchemaName}}_{{VersionTable}}; -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_02c_fix_version_table_casing_drop_proc.sql: -------------------------------------------------------------------------------- 1 | DROP PROCEDURE create_{{SchemaName}}_fix_version_table_casing; -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03b_fix_scriptsrun_table_casing_calling_proc.sql: -------------------------------------------------------------------------------- 1 | CALL create_{{SchemaName}}_fix_scriptsrun_table_casing(); -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/resource-group.tf: -------------------------------------------------------------------------------- 1 | data "azurerm_resource_group" "grate-integration-tests" { 2 | name = "grate-integration-tests" 3 | } -------------------------------------------------------------------------------- /src/grate.core/Migration/TransactionHandling.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Migration; 2 | 3 | public enum TransactionHandling 4 | { 5 | Default, 6 | Autonomous 7 | } 8 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03c_fix_scriptsrun_table_casing_drop_proc.sql: -------------------------------------------------------------------------------- 1 | DROP PROCEDURE create_{{SchemaName}}_fix_scriptsrun_table_casing; -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/IHashGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure; 2 | 3 | internal interface IHashGenerator 4 | { 5 | string Hash(string text); 6 | } 7 | -------------------------------------------------------------------------------- /src/grate.core/Configuration/MigrationType.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Configuration; 2 | 3 | public enum MigrationType 4 | { 5 | Once, 6 | AnyTime, 7 | EveryTime 8 | } 9 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03b_fix_scriptsrunerrors_table_casing_calling_proc.sql: -------------------------------------------------------------------------------- 1 | CALL create_{{SchemaName}}_fix_scriptsrunerrors_table_casing(); -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03c_fix_scriptsrunerrors_table_casing_drop_proc.sql: -------------------------------------------------------------------------------- 1 | DROP PROCEDURE create_{{SchemaName}}_fix_scriptsrunerrors_table_casing; -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pmarsceill/just-the-docs 2 | 3 | # Aux links for the upper right navigation 4 | aux_links: 5 | "grate on GitHub": 6 | - "//github.com/grate-devs/grate" -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/SampleDatabase/db/sprocs/000_sample_proc.sql: -------------------------------------------------------------------------------- 1 | 2 | create or alter proc sample_proc 3 | as 4 | 5 | select 10 as [Result]; 6 | 7 | GO -------------------------------------------------------------------------------- /test-infra/terraform/init/locals.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | default_audience_name = "api://AzureADTokenExchange" 3 | github_issuer_url = "https://token.actions.githubusercontent.com" 4 | } -------------------------------------------------------------------------------- /test-infra/terraform/init/variables.tf: -------------------------------------------------------------------------------- 1 | variable "github_organisation_target" { 2 | default = "erikbra" 3 | } 4 | 5 | variable "github_repository_name" { 6 | default = "grate" 7 | } -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.0", 4 | "rollForward": "latestMinor", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/GrateStructure/up/01_version_add_status_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "{{SchemaName}}"."{{VersionTable}}" 2 | ADD COLUMN IF NOT EXISTS status varchar(50) NULL; -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/GrateStructure/up/02_scripts_run_unicode_support.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE {{SchemaName}}.{{ScriptsRunTable}} 2 | ALTER COLUMN text_of_script NVARCHAR(MAX) NULL -------------------------------------------------------------------------------- /unittests/MariaDB/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /unittests/Oracle/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /unittests/PostgreSQL/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /unittests/SqlServer/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /unittests/Sqlite/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyPlaceholderType.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | public enum DummyPlaceholderType 4 | { 5 | Positional, 6 | Whatever 7 | } 8 | -------------------------------------------------------------------------------- /test-infra/terraform/init/github.tf: -------------------------------------------------------------------------------- 1 | # resource "github_repository_environment" "integration-tests" { 2 | # environment = "integration-tests" 3 | # repository = github_repository.example.name 4 | # } -------------------------------------------------------------------------------- /unittests/Basic_tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "methodDisplay": "method", 4 | "methodDisplayOptions": "all" 5 | } -------------------------------------------------------------------------------- /examples/k8s/multitenancy/Dockerfile-db: -------------------------------------------------------------------------------- 1 | FROM grate-devs/grate:latest as base 2 | WORKDIR /app 3 | COPY sql/ /db 4 | COPY script/ ./ 5 | RUN chmod +x ./migrate.sh 6 | RUN mkdir /output 7 | ENTRYPOINT ["./migrate.sh"] -------------------------------------------------------------------------------- /examples/docker/db/up/001_create_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE grate_test ( 2 | id int IDENTITY(1,1) NOT NULL PRIMARY KEY, 3 | name nvarchar(255) NOT NULL 4 | ) -------------------------------------------------------------------------------- /examples/local/db/up/003-Add-Deleted-Column.sql: -------------------------------------------------------------------------------- 1 | 2 | -- we can run alter statements here because we know grate will create the table for us first in the 001 script 3 | alter table TestTable add IsDeleted bit not null default(0); 4 | -------------------------------------------------------------------------------- /docs/ScriptTypes/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Script types 4 | permalink: /script-types/ 5 | nav_order: 4 6 | has_children: true 7 | --- 8 | 9 | # Script types 10 | 11 | grate has three different types of scripts. -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sql/up/001_create_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE grate_test ( 2 | id int IDENTITY(1,1) NOT NULL PRIMARY KEY, 3 | name nvarchar(255) NOT NULL 4 | ) -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sql/up/001_create_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE grate_test ( 2 | id int IDENTITY(1,1) NOT NULL PRIMARY KEY, 3 | name nvarchar(255) NOT NULL 4 | ) -------------------------------------------------------------------------------- /installers/deb/template/DEBIAN/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # Automatically added by dh_installdocs 4 | if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/grate ]; then 5 | rm -f /usr/doc/grate 6 | fi 7 | # End automatically added section -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/GrateStructure/up/00_01_fix_schema_casing.sql: -------------------------------------------------------------------------------- 1 | DO LANGUAGE plpgsql 2 | $$ 3 | BEGIN 4 | ALTER SCHEMA {{SchemaName}} RENAME TO "{{SchemaName}}"; 5 | EXCEPTION WHEN duplicate_schema or invalid_schema_name THEN 6 | END; 7 | $$; -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyNpgsqlParameter.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | public class DummyNpgsqlParameter 4 | { 5 | public string ParameterName { get; set; } = null!; 6 | public bool IsInputDirection => true; 7 | } 8 | -------------------------------------------------------------------------------- /src/grate/Configuration/DatabaseType.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable InconsistentNaming 2 | namespace grate.Configuration; 3 | 4 | public enum DatabaseType 5 | { 6 | SQLServer, 7 | Oracle, 8 | PostgreSQL, 9 | MariaDB, 10 | SQLite 11 | } 12 | 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | 8 | - package-ecosystem: "nuget" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" -------------------------------------------------------------------------------- /installers/deb/template/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # Automatically added by dh_installdocs 4 | if [ "$1" = "configure" ]; then 5 | if [ -d /usr/doc -a ! -e /usr/doc/grate -a -d /usr/share/doc/grate ]; then 6 | ln -sf ../share/doc/grate /usr/doc/grate 7 | fi 8 | fi -------------------------------------------------------------------------------- /src/grate.core/Configuration/MigrationStatus.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Configuration; 2 | 3 | public static class MigrationStatus 4 | { 5 | public const string InProgress = "In Progress"; 6 | public const string Error = "Error"; 7 | public const string Finished = "Finished"; 8 | } 9 | -------------------------------------------------------------------------------- /test-infra/terraform/init/resource-group.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_resource_group" "grate-integration-tests" { 2 | name = "grate-integration-tests" 3 | location = "eastus" 4 | } 5 | 6 | # data "azurerm_resource_group" "grate-tests-infra" { 7 | # name = "grate-tests-infra" 8 | # } -------------------------------------------------------------------------------- /src/grate.core/Configuration/IFoldersConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Configuration; 2 | 3 | public interface IFoldersConfiguration : IDictionary 4 | { 5 | MigrationsFolder? CreateDatabase { get; set; } 6 | MigrationsFolder? DropDatabase { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/GrateStructure/up/00_02_fix_version_table_casing.sql: -------------------------------------------------------------------------------- 1 | DO LANGUAGE plpgsql 2 | $$ 3 | BEGIN 4 | ALTER TABLE "{{SchemaName}}"."{{VersionTableLowerCase}}" RENAME TO "{{VersionTable}}"; 5 | EXCEPTION WHEN undefined_table or duplicate_table THEN 6 | END; 7 | $$; -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.Common/GrateExecutablePathAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace CommandLine.Common; 2 | 3 | [AttributeUsage(AttributeTargets.Assembly)] 4 | public class GrateExecutablePathAttribute(string path) : Attribute 5 | { 6 | public string Path { get; set; } = path; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/GrateStructure/up/00_03_fix_scriptsrun_table_casing.sql: -------------------------------------------------------------------------------- 1 | DO LANGUAGE plpgsql 2 | $$ 3 | BEGIN 4 | ALTER TABLE "{{SchemaName}}"."{{ScriptsRunTableLowerCase}}" RENAME TO "{{ScriptsRunTable}}"; 5 | EXCEPTION WHEN undefined_table or duplicate_table THEN 6 | END; 7 | $$; -------------------------------------------------------------------------------- /examples/local/db/sprocs/sp_GetTestById.sql: -------------------------------------------------------------------------------- 1 | create or alter proc sp_GetTestById 2 | @id int 3 | as 4 | 5 | Select Id, Name 6 | from vw_CurrentTestData 7 | where Id = @id; 8 | 9 | GO 10 | 11 | -- we could do permissions here if we needed 12 | -- grant execute on sp_GetTestById to some_user; 13 | -------------------------------------------------------------------------------- /installers/chocolatey/grate/tools/VERIFICATION.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | VERIFICATION 4 | Verification is intended to assist the Chocolatey moderators and community 5 | in verifying that this package's contents are trustworthy. 6 | 7 | Made by me from scratch. Releases here: https://github.com/grate-devs/grate/releases -------------------------------------------------------------------------------- /src/grate.core/Exceptions/InvalidFolderConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Exceptions; 2 | 3 | public class InvalidFolderConfiguration( 4 | string? folderConfiguration, 5 | string? propertyName) 6 | : Exception("Invalid property name: " + propertyName + ". Folder configuration: " + folderConfiguration); 7 | -------------------------------------------------------------------------------- /examples/local/db/indexes/ix_TestData_Name.sql: -------------------------------------------------------------------------------- 1 | -- we could have created this in the `UP` script as well if we preferred... 2 | 3 | create index ix_TestData_Name 4 | on TestTable(Name) 5 | where IsDeleted = 0 -- More complex features like filtered indexes/compression on disk are trivial. 6 | with (data_compression=page); -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/GrateStructure/up/01_version_add_status_column.sql: -------------------------------------------------------------------------------- 1 | IF NOT EXISTS( 2 | SELECT 1 FROM sys.columns WHERE name = 'status' 3 | AND OBJECT_NAME(object_id) = '{{VersionTable}}') 4 | BEGIN 5 | ALTER TABLE {{SchemaName}}.{{VersionTable}} 6 | ADD status nvarchar(50) NULL 7 | END -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/GrateStructure/up/00_03_fix_scriptsrunerrors_table_casing.sql: -------------------------------------------------------------------------------- 1 | DO LANGUAGE plpgsql 2 | $$ 3 | BEGIN 4 | ALTER TABLE "{{SchemaName}}"."{{ScriptsRunErrorsTableLowerCase}}" RENAME TO "{{ScriptsRunErrorsTable}}"; 5 | EXCEPTION WHEN undefined_table or duplicate_table THEN 6 | END; 7 | $$; -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sample-service/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.DependencyInjection; 3 | var builder = WebApplication.CreateBuilder(args); 4 | builder.Services.AddControllers(); 5 | var app = builder.Build(); 6 | app.UseRouting(); 7 | app.MapControllers(); 8 | app.Run(); 9 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/02_scripts_run_unicode_support.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE {{SchemaName}}_{{ScriptsRunTable}} 2 | MODIFY script_name varchar(255) CHARACTER SET utf8mb4 NULL, 3 | MODIFY text_of_script text CHARACTER SET utf8mb4 NULL, 4 | MODIFY entered_by varchar(50) CHARACTER SET utf8mb4 NULL -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/Baseline/up/01_create_schema_grate.ENV.GrateInternalBoostrap-a61456d0-e00a-4933-b692-c6a5d7d51539.sql: -------------------------------------------------------------------------------- 1 | -- We need to do 'if not exists' on this, as it is run twice, one for the Grate... tables, 2 | -- and one for the "standard" migration tables 3 | CREATE SCHEMA IF NOT EXISTS "{{SchemaName}}"; -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/GrateTestConfig.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | 3 | public record GrateTestConfig 4 | { 5 | public string? AdminConnectionString { get; set; } = null!; 6 | public string? DockerImage { get; set; } = null!; 7 | public bool ConnectToDockerInternal { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/TokenExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | 3 | namespace grate.Infrastructure; 4 | 5 | internal static class TokenExtensions 6 | { 7 | //helpers to centralise converting various types to a token 8 | 9 | public static string? ToToken(this MigrationsFolder? folder) => folder?.Path; 10 | } 11 | -------------------------------------------------------------------------------- /src/grate.oracle/Bootstrapping/Sql/GrateStructure/up/01_version_add_status_column.sql: -------------------------------------------------------------------------------- 1 | DECLARE 2 | column_exists EXCEPTION; 3 | PRAGMA EXCEPTION_INIT (column_exists , -01430); 4 | BEGIN 5 | EXECUTE IMMEDIATE 'ALTER TABLE {{SchemaName}}_{{VersionTable}} ADD status VARCHAR2(50)'; 6 | EXCEPTION 7 | WHEN column_exists THEN NULL; 8 | END; -------------------------------------------------------------------------------- /examples/local/db/up/001-Create-TestTable.sql: -------------------------------------------------------------------------------- 1 | create table TestTable 2 | ( 3 | Id int not null identity(1,1), 4 | Name varchar(20), 5 | 6 | constraint PK_Test PRIMARY KEY CLUSTERED 7 | ( 8 | Id ASC 9 | ) with (data_compression = page) -- Note we can use all the features of Sql Server because we're just .sql files... 10 | 11 | ); -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure; 2 | 3 | internal static class EnumerableExtensions 4 | { 5 | public static IEnumerable Safe(this T[]? source) => source ?? Enumerable.Empty(); 6 | public static IEnumerable Safe(this IEnumerable? source) => source ?? Enumerable.Empty(); 7 | } 8 | -------------------------------------------------------------------------------- /src/grate.core/Exceptions/OneTimeScriptChanged.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | 3 | namespace grate.Exceptions; 4 | 5 | public class OneTimeScriptChanged : MigrationException 6 | { 7 | public OneTimeScriptChanged(MigrationsFolder folder, string file, string errorMessage) 8 | : base(folder, file, errorMessage) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test-infra/terraform/init/README.md: -------------------------------------------------------------------------------- 1 | # Init 2 | 3 | This sets up the infrastructure in the azure subscription which is used to set up the test infrastructure on each test run. 4 | 5 | It creates a resource group, and a service principal with full access to that resource group, to make it easier to control access. 6 | 7 | This folder is typically only run once-ish. -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.0/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.0 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.1/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.1 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.11.0/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.11.0 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.4/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.4 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.5/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.5 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.6/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.6 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.0.0/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.0.0 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.1.0/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.1.0 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.2.0/erikbra.grate.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.2.0 6 | DefaultLocale: en-US 7 | ManifestType: version 8 | ManifestVersion: 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /unittests/Oracle/Database.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace Oracle; 6 | 7 | [Collection(nameof(OracleGrateTestContext))] 8 | public class Database(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : GenericDatabase(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /test-infra/terraform/init/tfstate-storage-container.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_storage_container" "grate-tests-setup" { 2 | name = "grate-tests-setup" 3 | storage_account_name = "grateconfig" 4 | } 5 | 6 | data "azurerm_storage_account" "grateconfig" { 7 | name = "grateconfig" 8 | resource_group_name = "grate-tests-infra" 9 | } 10 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/GrateMigratorExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Migration; 2 | 3 | namespace TestCommon.TestInfrastructure; 4 | 5 | internal static class GrateMigratorExtensions 6 | { 7 | public static IDbMigrator GetDbMigrator(this IGrateMigrator migrator) 8 | { 9 | return (migrator as GrateMigrator)!.DbMigrator; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sample-service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "DefaultConnection": "Server=localhost;Database=grate_test;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True" 10 | } 11 | } -------------------------------------------------------------------------------- /unittests/PostgreSQL/Database.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace PostgreSQL; 6 | 7 | [Collection(nameof(PostgreSqlGrateTestContext))] 8 | public class Database(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) : 9 | GenericDatabase(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace MariaDB; 6 | 7 | [Collection(nameof(MariaDbGrateTestContext))] 8 | public class MigrationTables(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) : 9 | GenericMigrationTables(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/03_version_table_unicode_support.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE {{SchemaName}}_{{VersionTable}} 2 | MODIFY repository_path varchar(255) CHARACTER SET utf8mb4 NULL, 3 | MODIFY version varchar(50) CHARACTER SET utf8mb4 NULL, 4 | MODIFY entered_by varchar(50) CHARACTER SET utf8mb4 NULL, 5 | MODIFY status varchar(50) CHARACTER SET utf8mb4 NULL -------------------------------------------------------------------------------- /examples/k8s/initcontainer/Dockerfile-db: -------------------------------------------------------------------------------- 1 | FROM grate-devs/grate:latest as base 2 | WORKDIR /app 3 | COPY sql/ /db 4 | RUN mkdir /output 5 | ENTRYPOINT ./grate \ 6 | --sqlfilesdirectory=/db \ 7 | --version=$VERSION \ 8 | --connstring="$APP_CONNSTRING" \ 9 | --silent \ 10 | --databasetype=sqlserver \ 11 | --outputPath=/output -------------------------------------------------------------------------------- /src/grate.sqlite/Bootstrapping/Sql/Baseline/up/04_create_version_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{VersionTable}}( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | repository_path nvarchar(255) NULL, 4 | version nvarchar(50) NULL, 5 | entry_date datetime NULL, 6 | modified_date datetime NULL, 7 | entered_by nvarchar(50) NULL, 8 | status nvarchar(50) NULL 9 | ) 10 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Database.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | public class Database(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.GenericDatabase(testContext, testOutput); 9 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/SqlServerScriptsBase.cs: -------------------------------------------------------------------------------- 1 | using TestCommon.Generic.Running_MigrationScripts; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | public abstract class SqlServerScriptsBase(IGrateTestContext context, ITestOutputHelper testOutput) : 7 | MigrationsScriptsBase(context, testOutput); 8 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace PostgreSQL; 6 | 7 | [Collection(nameof(PostgreSqlGrateTestContext))] 8 | public class MigrationTables(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) : 9 | GenericMigrationTables(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /installers/chocolatey/Create-Package.ps1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pwsh 2 | 3 | param ( 4 | [Parameter(Mandatory=$true)] [string] $grateExe, 5 | [Parameter(Mandatory=$true)] [string] $version 6 | ) 7 | 8 | $Root = Resolve-Path "$($PSScriptRoot)"; 9 | $toolsDir=Get-Item -Path $(Join-Path $Root "grate/tools") 10 | 11 | Copy-Item $grateExe $toolsDir 12 | 13 | choco pack --version=$version ./grate/grate.nuspec 14 | -------------------------------------------------------------------------------- /src/grate.core/Exceptions/UnknownConnectionType.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace grate.Exceptions; 4 | 5 | public class UnknownConnectionType( 6 | object? connectionType, 7 | [CallerArgumentExpression(nameof(connectionType))] 8 | string argumentName = "") 9 | : ArgumentOutOfRangeException(argumentName, connectionType, "Unknown connection type: " + connectionType); 10 | -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/aca-env.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_container_app_environment" "grate-tests" { 2 | name = "grate-integration-tests" 3 | location = data.azurerm_resource_group.grate-integration-tests.location 4 | resource_group_name = data.azurerm_resource_group.grate-integration-tests.name 5 | 6 | infrastructure_subnet_id = azurerm_subnet.aca-env.id 7 | } 8 | -------------------------------------------------------------------------------- /unittests/MariaDB/Database.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace MariaDB; 6 | 7 | [Collection(nameof(MariaDbGrateTestContext))] 8 | // ReSharper disable once UnusedType.Global 9 | public class Database(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : GenericDatabase(testContext, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /examples/local/run-migration.ps1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pwsh 2 | 3 | # Feel free to rem this out once grate is installed to speed up the script 4 | winget install erikbra.grate 5 | 6 | grate ` 7 | --files=.\db ` 8 | --env=Local ` 9 | --connstring="Server=(localdb)\MSSQLLocalDB;Integrated Security=true;Database=grate_test" ` 10 | --version=1.0 ` 11 | --silent 12 | # add --drop if you want grate to drop the whole db and start again. -------------------------------------------------------------------------------- /src/grate.oracle/Bootstrapping/Sql/Baseline/up/04_create_version_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{VersionTable}}( 2 | id NUMBER(19) GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, 3 | repository_path VARCHAR2(255) NULL, 4 | version VARCHAR2(50) NULL, 5 | entry_date timestamp NULL, 6 | modified_date timestamp NULL, 7 | entered_by VARCHAR2(50) NULL, 8 | status VARCHAR2(50) NULL 9 | ) 10 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | public class Order_Of_Scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 9 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | public class ScriptsRun_Table(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 9 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | public class ScriptsRun_Table(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 9 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/SqlServerScriptsBase.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.Generic.Running_MigrationScripts; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace SqlServer.Running_MigrationScripts; 6 | 7 | public abstract class SqlServerScriptsBase(SqlServerGrateTestContext context, ITestOutputHelper testOutput) : 8 | MigrationsScriptsBase(context, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/GrateStructure/up/03_scripts_run_errors_unicode_support.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE {{SchemaName}}.{{ScriptsRunErrorsTable}} 2 | ALTER COLUMN text_of_script NVARCHAR(MAX) NULL 3 | 4 | ALTER TABLE {{SchemaName}}.{{ScriptsRunErrorsTable}} 5 | ALTER COLUMN erroneous_part_of_script NVARCHAR(MAX) NULL 6 | 7 | ALTER TABLE {{SchemaName}}.{{ScriptsRunErrorsTable}} 8 | ALTER COLUMN error_message NVARCHAR(MAX) NULL 9 | -------------------------------------------------------------------------------- /src/grate/Configuration/CommandLineGrateConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace grate.Configuration; 4 | 5 | internal record CommandLineGrateConfiguration : GrateConfiguration 6 | { 7 | /// 8 | /// Database type to use. 9 | /// 10 | public DatabaseType DatabaseType { get; set; } 11 | 12 | public LogLevel Verbosity { get; init; } = LogLevel.Information; 13 | } 14 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | public class TokenScripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | public class DropDatabase(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 9 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/Everytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | public class Everytime_scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.Everytime_scripts(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sample-service/sample-service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetFramework) 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/Baseline/up/04_create_version_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{VersionTable}}( 2 | id bigint NOT NULL AUTO_INCREMENT, 3 | repository_path varchar(255) NULL, 4 | version varchar(50) NULL, 5 | entry_date timestamp NULL, 6 | modified_date timestamp NULL, 7 | entered_by varchar(50) NULL, 8 | status varchar(50) NULL, 9 | CONSTRAINT PK_{{VersionTable}}_id PRIMARY KEY (id) 10 | ) 11 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | public class TokenScripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sample-service/sample-service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetFramework) 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/grate.core/Exceptions/UnknownTransactionHandling.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace grate.Exceptions; 4 | 5 | public class UnknownTransactionHandling( 6 | object? transactionHandling, 7 | [CallerArgumentExpression(nameof(transactionHandling))] 8 | string argumentName = "") 9 | : ArgumentOutOfRangeException(argumentName, transactionHandling, 10 | "Unknown transaction handling : " + transactionHandling); 11 | -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyNpgsqlCommand.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | public class DummyNpgsqlCommand 4 | { 5 | public DummyNpgsqlCommand(string sql) 6 | { 7 | CommandText = sql; 8 | } 9 | 10 | public string CommandText { get; set; } 11 | public DummyNpgsqlParameterCollection Parameters { get; } = new(); 12 | public List InternalBatchCommands { get; } = new(); 13 | } 14 | -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/Baseline/up/01_create_schema_grate.ENV.GrateInternalBoostrap-a61456d0-e00a-4933-b692-c6a5d7d51539.sql: -------------------------------------------------------------------------------- 1 | -- We need to do 'if not exists' on this, as it is run twice, one for the Grate... tables, 2 | -- and one for the "standard" migration tables 3 | IF NOT EXISTS (SELECT * 4 | FROM sys.schemas 5 | WHERE name COLLATE DATABASE_DEFAULT = N'{{SchemaName}}' COLLATE DATABASE_DEFAULT) 6 | BEGIN 7 | EXEC('CREATE SCHEMA {{SchemaName}}') 8 | END -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | public class ScriptsRun_Table(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /src/grate.core/Migration/MigrationResult.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Migration; 2 | 3 | // ReSharper disable once ClassNeverInstantiated.Global 4 | internal record MigrationResult 5 | { 6 | private readonly List _scriptsRun = []; 7 | 8 | public IReadOnlyList ScriptsRun => _scriptsRun.AsReadOnly(); 9 | public bool IsUpToDate { get; set; } = true; 10 | 11 | public void AddScriptRun(string scriptName) => _scriptsRun.Add(scriptName); 12 | } 13 | -------------------------------------------------------------------------------- /src/grate.sqlite/Bootstrapping/Sql/Baseline/up/02_create_scripts_run_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunTable}}( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | version_id BIGINT NULL, 4 | script_name nvarchar(255) NULL, 5 | text_of_script ntext NULL, 6 | text_hash nvarchar(512) NULL, 7 | one_time_script bit NULL, 8 | entry_date datetime NULL, 9 | modified_date datetime NULL, 10 | entered_by nvarchar(50) NULL 11 | ) 12 | -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/Baseline/up/04_create_version_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "{{SchemaName}}"."{{VersionTable}}"( 2 | id bigint GENERATED ALWAYS AS IDENTITY NOT NULL, 3 | repository_path varchar(255) NULL, 4 | version varchar(50) NULL, 5 | entry_date timestamp NULL, 6 | modified_date timestamp NULL, 7 | entered_by varchar(50) NULL, 8 | status varchar(50) NULL, 9 | CONSTRAINT PK_{{VersionTable}}_id PRIMARY KEY (id) 10 | ) 11 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | // ReSharper disable once UnusedType.Global 7 | [Collection(nameof(OracleGrateTestContext))] 8 | public class DropDatabase(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once UnusedType.Global 8 | public class DropDatabase(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Oracle/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | 3 | namespace Oracle.Bootstrapping; 4 | 5 | [Collection(nameof(OracleGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class Grate_Internal_Scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Bootstrapping; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class Grate_Internal_Scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Anytime_scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/TestInfrastructure/InspectableSqlServerDatabase.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | using grate.SqlServer.Migration; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace SqlServer.TestInfrastructure; 6 | 7 | // ReSharper disable once ClassNeverInstantiated.Global 8 | public record InspectableSqlServerDatabase(ILogger logger): SqlServerDatabase(logger) 9 | { 10 | public DbConnection GetConnection() => base.Connection; 11 | } 12 | -------------------------------------------------------------------------------- /unittests/Docker/Docker.MariaDB/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using MariaDB.TestInfrastructure; 3 | 4 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 5 | 6 | namespace Docker.MariaDB; 7 | 8 | // ReSharper disable once UnusedType.Global 9 | public class Startup: Docker.Common.Startup 10 | { 11 | protected override DatabaseType DatabaseType => DatabaseType.MariaDB; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Anytime_scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class Grate_Internal_Scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class DropDatabase(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sample-service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "DefaultConnection": "Server=localhost;Database=grate_test;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True", 10 | "AdminConnection": "Server=localhost;Database=master;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True" 11 | } 12 | } -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Everytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Everytime_scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Everytime_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class One_time_scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Order_Of_Scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Bootstrapping; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class Grate_Internal_Scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.0/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.0 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.1/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.1 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.11.0/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.11.0 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.4/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.4 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.5/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.5 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.6/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.6 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.0.0/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.0.0 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.1.0/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.1.0 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.2.0/erikbra.grate.locale.en-US.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.2.0 6 | PackageLocale: en-US 7 | Publisher: erikbra 8 | PackageName: grate 9 | License: MIT License 10 | ShortDescription: grate - sql for the 20s 11 | ManifestType: defaultLocale 12 | ManifestVersion: 1.0.0 13 | 14 | -------------------------------------------------------------------------------- /src/grate.oracle/Bootstrapping/Sql/Baseline/up/02_create_scripts_run_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunTable}}( 2 | id NUMBER(19) GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, 3 | version_id NUMBER(19) NULL, 4 | script_name VARCHAR2(255) NULL, 5 | text_of_script CLOB NULL, 6 | text_hash VARCHAR2(512) NULL, 7 | one_time_script CHAR(1) NULL, 8 | entry_date timestamp NULL, 9 | modified_date timestamp NULL, 10 | entered_by VARCHAR2(50) NULL 11 | ) 12 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Environment_scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Oracle/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.DependencyInjection; 3 | 4 | namespace Oracle.DependencyInjection; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | public class ServiceCollectionTest(OracleGrateTestContext testContext) 8 | : GrateServiceCollectionTest(testContext) 9 | { 10 | protected override string VarcharType => "VARCHAR2"; 11 | protected override string BigintType => "NUMBER(19)"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | // ReSharper disable once UnusedType.Global 7 | [Collection(nameof(OracleGrateTestContext))] 8 | public class Environment_scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class One_time_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Order_Of_Scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class ScriptsRun_Table(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class TokenScripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput); 10 | 11 | 12 | -------------------------------------------------------------------------------- /unittests/Docker/Docker.SqlServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using SqlServer.TestInfrastructure; 3 | 4 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 5 | 6 | namespace Docker.SqlServer; 7 | 8 | // ReSharper disable once UnusedType.Global 9 | public class Startup: Docker.Common.Startup 10 | { 11 | protected override DatabaseType DatabaseType => DatabaseType.SQLServer; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class One_time_scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Order_Of_Scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Anytime_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Everytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Everytime_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Everytime_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.MariaDB/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using MariaDB.TestInfrastructure; 3 | 4 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 5 | 6 | namespace CommandLine.MariaDB; 7 | 8 | // ReSharper disable once UnusedType.Global 9 | public class Startup: CommandLine.Common.Startup 10 | { 11 | protected override DatabaseType DatabaseType => DatabaseType.MariaDB; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.SqlServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using SqlServer.TestInfrastructure; 3 | 4 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 5 | 6 | namespace CommandLine.SqlServer; 7 | 8 | // ReSharper disable once UnusedType.Global 9 | public class Startup: Common.Startup 10 | { 11 | protected override DatabaseType DatabaseType => DatabaseType.SQLServer; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/Docker/Docker.Sqlite/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Sqlite.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 6 | 7 | namespace Docker.Sqlite; 8 | 9 | // ReSharper disable once UnusedType.Global 10 | public class Startup: Docker.Common.Startup 11 | { 12 | protected override DatabaseType DatabaseType => DatabaseType.SQLite; 13 | } 14 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Environment_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/TestInfrastructure/InspectableSqlServerDatabase.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | using grate.SqlServer.Migration; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace SqlServerCaseSensitive.TestInfrastructure; 6 | 7 | // ReSharper disable once ClassNeverInstantiated.Global 8 | public record InspectableSqlServerDatabase(ILogger logger): SqlServerDatabase(logger) 9 | { 10 | public DbConnection GetConnection() => base.Connection; 11 | } 12 | -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/SampleDatabase/SampleDatabase.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test-infra/terraform/init/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "azurerm" { 3 | resource_group_name = "grate-tests-infra" 4 | storage_account_name = "grateconfig" 5 | container_name = "grate-tests-infra-setup" 6 | key = "init.tfstate" 7 | } 8 | 9 | required_providers { 10 | azurerm = { 11 | source = "hashicorp/azurerm" 12 | } 13 | azuread = {} 14 | } 15 | } 16 | 17 | provider "azurerm" { 18 | features {} 19 | } 20 | 21 | provider "azuread" { 22 | } 23 | -------------------------------------------------------------------------------- /unittests/MariaDB/Reported_issues/Non_ascii_characters_in_script/ScriptsRunTable.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunTable(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/Oracle/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | 3 | namespace Oracle.Bootstrapping; 4 | 5 | [Collection(nameof(OracleGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_does_not_exist(OracleGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/SqlStatements.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | 3 | public record SqlStatements 4 | { 5 | public string SelectVersion { get; init; } = default!; 6 | public string? SleepTwoSeconds { get; init; } 7 | public Func CreateUser { get; init; } = (_ , _, _) => null; 8 | public Func GrantAccess { get; init; } = (_, _) => null; 9 | public string LineComment { get; init; } = "--"; 10 | } 11 | -------------------------------------------------------------------------------- /unittests/MariaDB/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Bootstrapping; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_does_not_exist(MariaDbGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/Oracle/Reported_issues/Non_ascii_characters_in_script/ScriptsRunTable.cs: -------------------------------------------------------------------------------- 1 | 2 | using Oracle.TestInfrastructure; 3 | 4 | namespace Oracle.Reported_issues.Non_ascii_characters_in_script; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class ScriptsRunTable(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunTable(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | 8 | // ReSharper disable once InconsistentNaming 9 | public class Environment_scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Versioning_The_Database.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Versioning_The_Database(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Versioning_The_Database(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Sqlite/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Bootstrapping; 5 | 6 | 7 | [Collection(nameof(SqliteTestDatabase))] 8 | // ReSharper disable once InconsistentNaming 9 | // ReSharper disable once UnusedType.Global 10 | public class Grate_Internal_Scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 12 | -------------------------------------------------------------------------------- /unittests/Sqlite/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using grate.Infrastructure; 2 | using grate.Sqlite.Migration; 3 | using Sqlite.TestInfrastructure; 4 | using TestCommon.TestInfrastructure; 5 | 6 | namespace Sqlite.DependencyInjection; 7 | public class ServiceCollectionTest(SqliteGrateTestContext context) : TestCommon.DependencyInjection.GrateServiceCollectionTest(context) 8 | { 9 | protected override string VarcharType => "nvarchar"; 10 | protected override string BigintType => "BIGINT"; 11 | } 12 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class DropDatabase(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyThrowHelper.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | public static class DummyThrowHelper 4 | { 5 | public static void ThrowInvalidOperationException(string message, string paramName) 6 | { 7 | throw new InvalidOperationException(message) { Data = { { "ParamName", paramName } } }; 8 | } 9 | 10 | public static void ThrowNotSupportedException(string message) 11 | { 12 | throw new NotSupportedException(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/Versioning_The_Database.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | namespace PostgreSQL.Running_MigrationScripts; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class Versioning_The_Database(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.Versioning_The_Database(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Reported_issues/Non_ascii_characters_in_script/ScriptsRunTable.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunTable(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class TokenScripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class TokenScripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/Baseline/up/02_create_scripts_run_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunTable}}( 2 | id bigint NOT NULL AUTO_INCREMENT, 3 | version_id BIGINT NULL, 4 | script_name varchar(255) NULL, 5 | text_of_script text NULL, 6 | text_hash varchar(512) NULL, 7 | one_time_script boolean NULL, 8 | entry_date timestamp NULL, 9 | modified_date timestamp NULL, 10 | entered_by varchar(50) NULL, 11 | CONSTRAINT PK_{{ScriptsRunTable}}_id PRIMARY KEY (id) 12 | ) 13 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.Sqlite/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Sqlite.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 6 | 7 | namespace CommandLine.Sqlite; 8 | 9 | // ReSharper disable once UnusedType.Global 10 | public class Startup: CommandLine.Common.Startup 11 | { 12 | protected override DatabaseType DatabaseType => DatabaseType.SQLite; 13 | } 14 | -------------------------------------------------------------------------------- /unittests/Oracle/Reported_issues/Non_ascii_characters_in_script/ScriptsRunErrorsTable.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | 3 | namespace Oracle.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(OracleGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunErrorsTable(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunErrorsTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Reported_issues/Non_ascii_characters_in_script/ScriptsRunTable.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunTable(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/SqlServer/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_does_not_exist(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.DependencyInjection; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | public class ServiceCollectionTest(SqlServerGrateTestContext context) 8 | : TestCommon.DependencyInjection.GrateServiceCollectionTest(context) 9 | { 10 | protected override string VarcharType => "nvarchar"; 11 | protected override string BigintType => "BIGINT"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Bootstrapping/Grate_Internal_Scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | 3 | namespace SqlServerCaseSensitive.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class Grate_Internal_Scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.Grate_Internal_Scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class One_time_scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Order_Of_Scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/MariaDB/Reported_issues/Non_ascii_characters_in_script/ScriptsRunErrorsTable.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunErrorsTable(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunErrorsTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/Oracle/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | 3 | namespace Oracle.Bootstrapping; 4 | 5 | [Collection(nameof(OracleGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_is_not_latest_version(OracleGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Bootstrapping; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_does_not_exist(PostgreSqlGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.DependencyInjection; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | public class ServiceCollectionTest(PostgreSqlGrateTestContext context) 8 | : TestCommon.DependencyInjection.GrateServiceCollectionTest(context) 9 | { 10 | protected override string VarcharType => "varchar"; 11 | protected override string BigintType => "BIGINT"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/DropDatabase.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class DropDatabase(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.DropDatabase(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | 7 | [Collection(nameof(SqliteTestDatabase))] 8 | // ReSharper disable once InconsistentNaming 9 | // ReSharper disable once UnusedType.Global 10 | public class Anytime_scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 12 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/Everytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Everytime_scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Everytime_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class ScriptsRun_Table(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /src/grate.sqlite/Bootstrapping/Sql/Baseline/up/03_create_scripts_run_errors_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunErrorsTable}}( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | repository_path nvarchar(255) NULL, 4 | version nvarchar(50) NULL, 5 | script_name nvarchar(255) NULL, 6 | text_of_script ntext NULL, 7 | erroneous_part_of_script ntext NULL, 8 | error_message ntext NULL, 9 | entry_date datetime NULL, 10 | modified_date datetime NULL, 11 | entered_by nvarchar(50) NULL 12 | ) 13 | 14 | -------------------------------------------------------------------------------- /unittests/MariaDB/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Bootstrapping; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_is_not_latest_version(MariaDbGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/Oracle/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | 3 | namespace Oracle.Bootstrapping; 4 | 5 | [Collection(nameof(OracleGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_does_not_exist(OracleGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Anytime_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Everytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Everytime_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Everytime_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/ScriptsRun_Table.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class ScriptsRun_Table(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.ScriptsRun_Table(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/MariaDB/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | 3 | namespace MariaDB.Bootstrapping; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_does_not_exist(MariaDbGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Bootstrapping/When_Grate_internal_structure_is_changed.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_is_changed(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_is_changed(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Reported_issues/Non_ascii_characters_in_script/ScriptsRunErrorsTable.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunErrorsTable(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunErrorsTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class One_time_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Order_Of_Scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Order_Of_Scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Order_Of_Scripts(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Reported_issues/Reported_issues/Non_ascii_characters_in_script/ScriptsRunTable.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | 3 | namespace Sqlite.Reported_issues.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(SqliteGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunTable(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Environment_scripts(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/Baseline/up/02_create_scripts_run_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "{{SchemaName}}"."{{ScriptsRunTable}}"( 2 | id bigint GENERATED ALWAYS AS IDENTITY NOT NULL, 3 | version_id BIGINT NULL, 4 | script_name varchar(255) NULL, 5 | text_of_script text NULL, 6 | text_hash varchar(512) NULL, 7 | one_time_script boolean NULL, 8 | entry_date timestamp NULL, 9 | modified_date timestamp NULL, 10 | entered_by varchar(50) NULL, 11 | CONSTRAINT PK_{{ScriptsRunTable}}_id PRIMARY KEY (id) 12 | ) 13 | -------------------------------------------------------------------------------- /src/grate/Infrastructure/CliCommandsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | using grate.Commands; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace grate.Infrastructure; 6 | 7 | internal static class CliCommandCollectionExtensions 8 | { 9 | public static IServiceCollection AddCliCommands(this IServiceCollection services) 10 | { 11 | services.AddSingleton(); 12 | services.AddSingleton(); 13 | 14 | return services; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /unittests/Docker/Docker.PostgreSQL/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using PostgreSQL.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 6 | 7 | namespace Docker.PostgreSQL; 8 | 9 | // ReSharper disable once UnusedType.Global 10 | public class Startup: Docker.Common.Startup 11 | { 12 | protected override DatabaseType DatabaseType => DatabaseType.PostgreSQL; 13 | } 14 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Reported_issues/Non_ascii_characters_in_script/ScriptsRunErrorsTable.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunErrorsTable(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunErrorsTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/Anytime_scripts.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace PostgreSQL.Running_MigrationScripts; 5 | 6 | [Collection(nameof(PostgreSqlGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Anytime_scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Anytime_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_is_not_latest_version(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Environment_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Environment_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Environment_scripts(testContext, testOutput); 10 | -------------------------------------------------------------------------------- /unittests/Sqlite/Bootstrapping/When_Grate_structure_already_exists.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Bootstrapping; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class When_Grate_structure_already_exists(SqliteGrateTestContext context, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_already_exists(context, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /unittests/Docker/Docker.Oracle/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Oraclde.TestInfrastructure; 3 | using Oracle.TestInfrastructure; 4 | using TestCommon.TestInfrastructure; 5 | 6 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 7 | 8 | namespace Docker.Oracle; 9 | 10 | // ReSharper disable once UnusedType.Global 11 | public class Startup: Common.Startup 12 | { 13 | protected override DatabaseType DatabaseType => DatabaseType.Oracle; 14 | } 15 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Bootstrapping/When_Grate_structure_already_exists.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Bootstrapping; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_already_exists( 9 | PostgreSqlGrateTestContext context, 10 | ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_already_exists(context, testOutput); 12 | 13 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Bootstrapping; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_is_not_latest_version(PostgreSqlGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServer/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | 3 | namespace SqlServer.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_does_not_exist(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Bootstrapping; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class When_Grate_structure_does_not_exist(SqliteGrateTestContext context, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/db-passwords.tf: -------------------------------------------------------------------------------- 1 | resource "random_password" "mariadb_admin" { 2 | length = 16 3 | special = true 4 | } 5 | 6 | resource "random_password" "mariadb_user" { 7 | length = 16 8 | special = true 9 | } 10 | 11 | resource "random_password" "oracle_admin" { 12 | length = 16 13 | special = false 14 | } 15 | 16 | resource "random_password" "postgresql_admin" { 17 | length = 16 18 | special = true 19 | } 20 | 21 | resource "random_password" "mssql_admin" { 22 | length = 16 23 | special = true 24 | } 25 | 26 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.PostgreSQL/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using PostgreSQL.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 6 | 7 | namespace CommandLine.PostgreSQL; 8 | 9 | // ReSharper disable once UnusedType.Global 10 | public class Startup: Common.Startup 11 | { 12 | protected override DatabaseType DatabaseType => DatabaseType.PostgreSQL; 13 | } 14 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Versioning_The_Database.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using MariaDB.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace MariaDB.Running_MigrationScripts; 6 | 7 | [Collection(nameof(MariaDbGrateTestContext))] 8 | // ReSharper disable once InconsistentNaming 9 | public class Versioning_The_Database(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Versioning_The_Database(testContext, testOutput); 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /unittests/Sqlite/Reported_issues/Reported_issues/Non_ascii_characters_in_script/ScriptsRunErrorsTable.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | 3 | namespace Sqlite.Reported_issues.Reported_issues.Non_ascii_characters_in_script; 4 | 5 | [Collection(nameof(SqliteGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | public class ScriptsRunErrorsTable(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Reported_issues.Non_ascii_characters_in_script.ScriptsRunErrorsTable(testContext, testOutput); 9 | 10 | -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/readme.md: -------------------------------------------------------------------------------- 1 | # Example of using grate in Automated Tests 2 | 3 | A simplified example of one way to use `grate` in your automated tests. 4 | 5 | This is certainly not the only way of integrating `grate` into your tests, but is a pattern that's been used in multiple companies with success. 6 | 7 | ⚠️ There's an implicit assumption that `grate` is installed on the system running the tests. Ensure you have a 8 | step in your pipeline to install `grate` on the build server for CI (and that it's installed locally for development). -------------------------------------------------------------------------------- /src/grate.oracle/Bootstrapping/Sql/Baseline/up/03_create_scripts_run_errors_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunErrorsTable}}( 2 | id NUMBER(19) GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, 3 | repository_path VARCHAR2(255) NULL, 4 | version VARCHAR2(50) NULL, 5 | script_name VARCHAR2(255) NULL, 6 | text_of_script CLOB NULL, 7 | erroneous_part_of_script CLOB NULL, 8 | error_message CLOB NULL, 9 | entry_date timestamp NULL, 10 | modified_date timestamp NULL, 11 | entered_by VARCHAR2(50) NULL 12 | ) 13 | 14 | -------------------------------------------------------------------------------- /unittests/MariaDB/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | namespace MariaDB.DependencyInjection; 4 | 5 | [Collection(nameof(MariaDbGrateTestContext))] 6 | // ReSharper disable once UnusedType.Global 7 | public class ServiceCollectionTest(MariaDbGrateTestContext context) 8 | : TestCommon.DependencyInjection.GrateServiceCollectionTest(context) 9 | { 10 | protected override string VarcharType => "varchar"; 11 | protected override string BigintType => "BIGINT"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Versioning_The_Database.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Versioning_The_Database(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Versioning_The_Database(testContext, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.Oracle/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Oraclde.TestInfrastructure; 3 | using Oracle.TestInfrastructure; 4 | using TestCommon.TestInfrastructure; 5 | 6 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 7 | 8 | namespace CommandLine.Oracle; 9 | 10 | // ReSharper disable once UnusedType.Global 11 | public class Startup: Common.Startup 12 | { 13 | protected override DatabaseType DatabaseType => DatabaseType.Oracle; 14 | } 15 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Bootstrapping/When_Grate_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | 3 | namespace SqlServerCaseSensitive.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_does_not_exist(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/DependencyInjection/ServiceCollectionTest.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.DependencyInjection; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | public class ServiceCollectionTest(SqlServerGrateTestContext context) 8 | : TestCommon.DependencyInjection.GrateServiceCollectionTest(context) 9 | { 10 | protected override string VarcharType => "nvarchar"; 11 | protected override string BigintType => "BIGINT"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using PostgreSQL.TestInfrastructure; 2 | 3 | namespace PostgreSQL.Bootstrapping; 4 | 5 | [Collection(nameof(PostgreSqlGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_does_not_exist( 9 | PostgreSqlGrateTestContext context, 10 | ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 12 | 13 | -------------------------------------------------------------------------------- /unittests/Sqlite/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite.Bootstrapping; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class When_Grate_internal_structure_does_not_exist(SqliteGrateTestContext context, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 11 | 12 | -------------------------------------------------------------------------------- /examples/docker/readme.md: -------------------------------------------------------------------------------- 1 | # Docker Example 2 | 3 | This directory shows a very simple way of building a docker container to apply your database migrations. This is not intended to be prod ready (passing environments etc) but just to get you started. 4 | 5 | ## Usage 6 | 7 | Simply `docker-compose up` to: 8 | - start a sql database server 9 | - run the `grate` migration against the server with script locate in `db` folder and store the backup script in `output` 10 | 11 | ## Notes 12 | 13 | - You wouldn't normally do db migrations using compose, this is just an example. 14 | 15 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/Run_After_Create_Database_scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Run_After_Create_Database_scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Run_After_Create_Database_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Run_After_Create_Database_scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Run_After_Create_Database_scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Run_After_Create_Database_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /unittests/Sqlite/Running_MigrationScripts/Versioning_The_Database.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Sqlite.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace Sqlite.Running_MigrationScripts; 6 | 7 | [Collection(nameof(SqliteTestDatabase))] 8 | // ReSharper disable once InconsistentNaming 9 | // ReSharper disable once UnusedType.Global 10 | public class Versioning_The_Database(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Running_MigrationScripts.Versioning_The_Database(testContext, testOutput); 12 | 13 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/03_scripts_run_errors_unicode_support.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE {{SchemaName}}_{{ScriptsRunErrorsTable}} 2 | MODIFY repository_path varchar(255) CHARACTER SET utf8mb4 NULL, 3 | MODIFY version varchar(50) CHARACTER SET utf8mb4 NULL, 4 | MODIFY script_name varchar(255) CHARACTER SET utf8mb4 NULL, 5 | MODIFY text_of_script text CHARACTER SET utf8mb4 NULL, 6 | MODIFY erroneous_part_of_script text CHARACTER SET utf8mb4 NULL, 7 | MODIFY error_message text CHARACTER SET utf8mb4 NULL, 8 | MODIFY entered_by varchar(50) CHARACTER SET utf8mb4 NULL -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Bootstrapping/When_Grate_internal_structure_does_not_exist.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | 3 | namespace SqlServerCaseSensitive.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_internal_structure_does_not_exist(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_internal_structure_does_not_exist(context, testOutput); 10 | 11 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | 3 | namespace SqlServerCaseSensitive.Bootstrapping; 4 | 5 | [Collection(nameof(SqlServerGrateTestContext))] 6 | // ReSharper disable once InconsistentNaming 7 | // ReSharper disable once UnusedType.Global 8 | public class When_Grate_structure_is_not_latest_version(SqlServerGrateTestContext context, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput); 10 | 11 | 12 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/Net6PolyFills.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | using System.IO; 3 | 4 | #if NET6_0 5 | public static class Net6PolyFills 6 | { 7 | public static class Directory 8 | { 9 | public static DirectoryInfo CreateTempSubdirectory() 10 | => CreateTempSubdirectory(Path.GetRandomFileName()); 11 | 12 | public static DirectoryInfo CreateTempSubdirectory(string name) 13 | { 14 | return new DirectoryInfo(Path.GetTempPath()).CreateSubdirectory(name); 15 | } 16 | } 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /unittests/SqlServer/Running_MigrationScripts/Run_After_Create_Database_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServer.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Run_After_Create_Database_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Run_After_Create_Database_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/Baseline/up/03_create_scripts_run_errors_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE {{SchemaName}}_{{ScriptsRunErrorsTable}}( 2 | id bigint NOT NULL AUTO_INCREMENT, 3 | repository_path varchar(255) NULL, 4 | version varchar(50) NULL, 5 | script_name varchar(255) NULL, 6 | text_of_script text NULL, 7 | erroneous_part_of_script text NULL, 8 | error_message text NULL, 9 | entry_date timestamp NULL, 10 | modified_date timestamp NULL, 11 | entered_by varchar(50) NULL, 12 | CONSTRAINT PK_{{ScriptsRunErrorsTable}}_id PRIMARY KEY (id) 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /unittests/MariaDB/TestInfrastructure/InspectableMariaDbDatabase.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | using grate.MariaDb.Migration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace MariaDB.TestInfrastructure; 7 | 8 | public record InspectableMariaDbDatabase : MariaDbDatabase 9 | { 10 | public InspectableMariaDbDatabase(IServiceProvider serviceProvider) 11 | : base(serviceProvider.GetRequiredService>()) 12 | { 13 | } 14 | 15 | public DbConnection GetConnection() => base.Connection; 16 | } 17 | -------------------------------------------------------------------------------- /unittests/Basic_tests/Infrastructure/HashGenerator_.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Infrastructure; 3 | 4 | namespace Basic_tests.Infrastructure; 5 | 6 | 7 | // ReSharper disable once InconsistentNaming 8 | public class HashGenerator_ 9 | { 10 | [Fact] 11 | public void Generates_the_correct_hash() 12 | { 13 | string text_to_hash = "I want to see what the freak is going on here"; 14 | string expected_hash = "TMGPZJmBhSO5uYbf/TBqNA=="; 15 | 16 | var hashGen = new HashGenerator(); 17 | hashGen.Hash(text_to_hash).Should().Be(expected_hash); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /unittests/Basic_tests/Infrastructure/MockDbMigratorLogger.cs: -------------------------------------------------------------------------------- 1 | using grate.Migration; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Basic_tests.Infrastructure; 5 | 6 | public class MockDbMigratorLogger: ILogger 7 | { 8 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) 9 | { 10 | } 11 | 12 | public bool IsEnabled(LogLevel logLevel) => false; 13 | 14 | public IDisposable? BeginScope(TState state) where TState : notnull 15 | { 16 | return null; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/grate.postgresql/Bootstrapping/Sql/Baseline/up/03_create_scripts_run_errors_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "{{SchemaName}}"."{{ScriptsRunErrorsTable}}"( 2 | id bigint GENERATED ALWAYS AS IDENTITY NOT NULL, 3 | repository_path varchar(255) NULL, 4 | version varchar(50) NULL, 5 | script_name varchar(255) NULL, 6 | text_of_script text NULL, 7 | erroneous_part_of_script text NULL, 8 | error_message text NULL, 9 | entry_date timestamp NULL, 10 | modified_date timestamp NULL, 11 | entered_by varchar(50) NULL, 12 | CONSTRAINT PK_{{ScriptsRunErrorsTable}}_id PRIMARY KEY (id) 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/One_time_scripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | 7 | [Collection(nameof(OracleGrateTestContext))] 8 | public class One_time_scripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) 10 | { 11 | protected override string CreateView1 => base.CreateView1 + " FROM DUAL"; 12 | protected override string CreateView2 => base.CreateView2 + " FROM DUAL"; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/grate.core/Migration/IGrateMigrator.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | 3 | namespace grate.Migration; 4 | public interface IGrateMigrator : IAsyncDisposable 5 | { 6 | /// 7 | /// Trigger grate migration with the given configuration 8 | /// 9 | /// 10 | Task Migrate(); 11 | 12 | GrateConfiguration Configuration { get; } 13 | 14 | IGrateMigrator WithConfiguration(GrateConfiguration configuration); 15 | IGrateMigrator WithConfiguration(Action builder); 16 | IGrateMigrator WithDatabase(IDatabase database); 17 | } 18 | -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/Baseline/up/04_create_version_table.sql: -------------------------------------------------------------------------------- 1 | IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'{{SchemaName}}.{{VersionTable}}') AND type in (N'U')) 2 | CREATE TABLE {{SchemaName}}.{{VersionTable}}( 3 | id bigint IDENTITY(1,1) NOT NULL, 4 | repository_path nvarchar(255) NULL, 5 | version nvarchar(50) NULL, 6 | entry_date datetime NULL, 7 | modified_date datetime NULL, 8 | entered_by nvarchar(50) NULL, 9 | status nvarchar(50) NULL, 10 | CONSTRAINT PK_{{VersionTable}}_id PRIMARY KEY CLUSTERED (id) 11 | ) 12 | -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyNpgsqlParameterCollection.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | public class DummyNpgsqlParameterCollection : Dictionary 4 | { 5 | public void Add(DummyNpgsqlParameter parameter) => Add(parameter.ParameterName, parameter); 6 | public DummyPlaceholderType PlaceholderType => DummyPlaceholderType.Whatever; 7 | 8 | public void AddRange(DummyNpgsqlParameter[] parameters) 9 | { 10 | foreach (var parameter in parameters) 11 | { 12 | Add(parameter.ParameterName, parameter); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/k8s/initcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build 2 | WORKDIR . 3 | 4 | COPY sample-service/ ./sample-service/ 5 | RUN dotnet publish ./sample-service/*.csproj -c release -o ./publish/app 6 | 7 | FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine as runtime 8 | WORKDIR /app 9 | 10 | COPY --from=build /publish/app . 11 | 12 | # Add globalization support to the OS so .Net can use cultures 13 | RUN apk add icu-libs 14 | ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false 15 | ENV ASPNETCORE_URLS=http://[::]:80 16 | ENV ASPNETCORE_ENVIRONMENT=Production 17 | 18 | ENTRYPOINT ["dotnet", "sample-service.dll"] -------------------------------------------------------------------------------- /unittests/Oracle/Running_MigrationScripts/TokenScripts.cs: -------------------------------------------------------------------------------- 1 | using Oracle.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Oracle.Running_MigrationScripts; 5 | 6 | [Collection(nameof(OracleGrateTestContext))] 7 | public class TokenScripts(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 8 | : TestCommon.Generic.Running_MigrationScripts.TokenScripts(testContext, testOutput) 9 | { 10 | protected override string CreateDatabaseName => base.CreateDatabaseName + " FROM DUAL"; 11 | protected override string CreateViewMyCustomToken => base.CreateViewMyCustomToken + " FROM DUAL"; 12 | } 13 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Running_MigrationScripts/Run_After_Create_Database_scripts.cs: -------------------------------------------------------------------------------- 1 | using SqlServerCaseSensitive.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace SqlServerCaseSensitive.Running_MigrationScripts; 5 | 6 | [Collection(nameof(SqlServerGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class Run_After_Create_Database_scripts(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.Running_MigrationScripts.Run_After_Create_Database_scripts(testContext, testOutput); 11 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build 2 | WORKDIR . 3 | 4 | COPY sample-service/ ./sample-service/ 5 | RUN dotnet publish ./sample-service/*.csproj -c release -o ./publish/app 6 | 7 | FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine as runtime 8 | WORKDIR /app 9 | 10 | COPY --from=build /publish/app . 11 | COPY sql/ /db 12 | 13 | # Add globalization support to the OS so .Net can use cultures 14 | RUN apk add icu-libs 15 | ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false 16 | ENV ASPNETCORE_URLS=http://[::]:80 17 | ENV ASPNETCORE_ENVIRONMENT=Production 18 | 19 | ENTRYPOINT ["dotnet", "sample-service.dll"] -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sample-service/Extensions/ConnectionStringExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using grate.Configuration; 3 | 4 | namespace SampleService.Extension; 5 | public static class ConnectionStringExtension 6 | { 7 | public static void SwitchDatabase(this GrateConfiguration grateConfiguration, string targetDatabase) 8 | { 9 | var pattern = new Regex("(.*;\\s*(?:Initial Catalog|Database)=)([^;]*)(.*)"); 10 | var replacement = $"$1{targetDatabase}$3"; 11 | var replaced = pattern.Replace(grateConfiguration.ConnectionString!, replacement); 12 | grateConfiguration.ConnectionString = replaced; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.0/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.0 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.10.0/grate-0.10.0.msi 11 | InstallerSha256: B3D26E111BE89BD23BEFB527BE6D26C71831223596CD6CD441B496B71FC4A585 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.10.1/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.10.1 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.10.1/grate-0.10.1.msi 11 | InstallerSha256: A17831A175607DAFD47F55B4B82D144889415CA1CF34B4EFF0BA58E2A3EC3398 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.11.0/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.11.0 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.11.0/grate-0.11.0.msi 11 | InstallerSha256: C1C4626D1DD9AAC4F477A6DF3D00846DCDD7F3FE0995582B52B2F529BEBC863C 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.4/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.4 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.9.4/grate-0.9.4.msi 11 | InstallerSha256: 3CA445B7E71C84195B8E6DD466EAEAFC0A6D1807EBA28A8F8CB840811219955F 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.5/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.5 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.9.5/grate-0.9.5.msi 11 | InstallerSha256: 9C297BC4A8A83AD9A1935B47904C03CCBCD18FD6D6C15A0A4562ED31A8567BCC 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/0.9.6/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.1.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 0.9.6 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/0.9.6/grate-0.9.6.msi 11 | InstallerSha256: 88FF79BB613AF142928A1FFA16B9044B50DACB704F38F194B511581765603727 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.0.0/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.3.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.0.0 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/1.0.0/grate-1.0.0.msi 11 | InstallerSha256: 1E3A6A3106DB1DBF21662155AA0C0C604791F34B54F97A78E79019089F7FC028 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.1.0/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.1.0 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/1.1.0/grate-1.1.0.msi 11 | InstallerSha256: 0BC98D32C78E11899E54F36D192B0A67A127F5C96F4F2ACCAB03BD24DF0401B5 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /installers/winget/grate/manifests/e/erikbra/grate/1.2.0/erikbra.grate.installer.yaml: -------------------------------------------------------------------------------- 1 | # Created using wingetcreate 0.4.4.1 2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.0.0.schema.json 3 | 4 | PackageIdentifier: erikbra.grate 5 | PackageVersion: 1.2.0 6 | Installers: 7 | - InstallerLocale: en-US 8 | Architecture: x64 9 | InstallerType: msi 10 | InstallerUrl: https://github.com/erikbra/grate/releases/download/1.2.0/grate-1.2.0.msi 11 | InstallerSha256: EF43B5468670BC2C58614BF451CCC4F7D08E1A0727AC91BAEA573568750F9932 12 | ProductCode: '{E281998A-D8A2-4926-AAA3-066EFA4B2E74}' 13 | ManifestType: installer 14 | ManifestVersion: 1.0.0 15 | 16 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/TestDatabaseFixture.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | 3 | public class TestDatabaseFixture(ITestDatabase testDatabase) : IAsyncLifetime 4 | { 5 | public ITestDatabase TestDatabase { get; } = testDatabase; 6 | 7 | public async Task InitializeAsync() 8 | { 9 | if (TestDatabase is IAsyncLifetime asyncLifetime) 10 | { 11 | await asyncLifetime.InitializeAsync(); 12 | } 13 | } 14 | 15 | public async Task DisposeAsync() 16 | { 17 | if (TestDatabase is IAsyncLifetime asyncLifetime) 18 | { 19 | await asyncLifetime.DisposeAsync(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.Common/Startup.cs: -------------------------------------------------------------------------------- 1 | using CommandLine.Common.TestInfrastructure; 2 | using grate.Configuration; 3 | using grate.Migration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace CommandLine.Common; 8 | 9 | // ReSharper disable once UnusedType.Global 10 | public abstract class Startup: TestCommon.Startup 11 | { 12 | protected abstract DatabaseType DatabaseType { get; } 13 | 14 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 15 | { 16 | services.AddSingleton(new CommandLineGrateMigrator(DatabaseType)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/grate.mariadb/grate.mariadb.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /unittests/SqlServer/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using SqlServer.TestInfrastructure; 2 | using TestCommon.Generic; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace SqlServer; 6 | 7 | [Collection(nameof(SqlServerGrateTestContext))] 8 | public class MigrationTables(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : GenericMigrationTables(testContext, testOutput) 10 | { 11 | protected override string CountTableSql(string schemaName, string tableName) 12 | { 13 | return $@" 14 | SELECT count(table_name) FROM INFORMATION_SCHEMA.TABLES 15 | WHERE 16 | TABLE_SCHEMA = '{schemaName}' AND 17 | TABLE_NAME = '{tableName}' COLLATE Latin1_General_CS_AS 18 | "; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/grate.postgresql/grate.postgresql.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /unittests/Sqlite/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using Sqlite.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace Sqlite; 5 | 6 | [Collection(nameof(SqliteTestDatabase))] 7 | // ReSharper disable once InconsistentNaming 8 | // ReSharper disable once UnusedType.Global 9 | public class MigrationTables(SqliteGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : TestCommon.Generic.GenericMigrationTables(testContext, testOutput) 11 | { 12 | 13 | protected override string CountTableSql(string schemaName, string tableName) 14 | { 15 | return $@" 16 | SELECT COUNT(name) FROM sqlite_master 17 | WHERE type ='table' AND 18 | name = '{tableName}'; 19 | "; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/grate.oracle/grate.oracle.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/grate.postgresql/Infrastructure/Npgsql/DummyBatchCommand.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure.Npgsql; 2 | 3 | /// 4 | /// Simple, minimal dummy implementation of the Npgsql BatchCommand, 5 | /// only to support the methods needed for parsing/splitting 6 | /// 7 | public class DummyBatchCommand 8 | { 9 | public string? FinalCommandText { get; set; } 10 | public string CommandText { get; set; } = null!; 11 | public DummyNpgsqlParameterCollection Parameters { get; set; } = null!; 12 | public DummyNpgsqlParameterCollection PositionalParameters { get; set; } = null!; 13 | 14 | public void Reset() 15 | { 16 | throw new System.NotImplementedException(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/grate.sqlite/grate.sqlite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /unittests/Sqlite/Bootstrapping/When_Grate_structure_is_not_latest_version.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Sqlite.TestInfrastructure; 3 | using TestCommon.TestInfrastructure; 4 | 5 | namespace Sqlite.Bootstrapping; 6 | 7 | [Collection(nameof(SqliteTestDatabase))] 8 | // ReSharper disable once InconsistentNaming 9 | // ReSharper disable once UnusedType.Global 10 | public class When_Grate_structure_is_not_latest_version(SqliteGrateTestContext context, ITestOutputHelper testOutput) 11 | : TestCommon.Generic.Bootstrapping.When_Grate_structure_is_not_latest_version(context, testOutput) 12 | { 13 | public override Task The_latest_version_is_applied(string versionTableName) => Task.CompletedTask; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/grate.sqlserver/grate.sqlserver.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "azurerm" { 3 | resource_group_name = "grate-tests-infra" 4 | storage_account_name = "grateconfig" 5 | container_name = "grate-tests-setup" 6 | key = "test-environment.tfstate" 7 | 8 | use_oidc = true 9 | use_azuread_auth = true 10 | } 11 | 12 | required_providers { 13 | azurerm = { 14 | source = "hashicorp/azurerm" 15 | } 16 | azuread = {} 17 | } 18 | } 19 | 20 | provider "azurerm" { 21 | #use_oidc = true 22 | skip_provider_registration = true 23 | features {} 24 | } 25 | 26 | provider "azuread" { 27 | } 28 | 29 | data "azurerm_client_config" "current" {} 30 | -------------------------------------------------------------------------------- /src/grate.core/Configuration/IKnownFolderNames.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Configuration; 2 | 3 | internal interface IKnownFolderNames 4 | { 5 | string BeforeMigration { get; } 6 | string CreateDatabase { get; } 7 | string DropDatabase { get; } 8 | string AlterDatabase { get; } 9 | string RunAfterCreateDatabase { get; } 10 | string RunBeforeUp { get; } 11 | string Up { get; } 12 | string RunFirstAfterUp { get; } 13 | string Functions { get; } 14 | string Views { get; } 15 | string Sprocs { get; } 16 | string Triggers { get; } 17 | string Indexes { get; } 18 | string RunAfterOtherAnyTimeScripts { get; } 19 | string Permissions { get; } 20 | string AfterMigration { get; } 21 | } 22 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Running_MigrationScripts/Run_After_Create_Database_scripts.cs: -------------------------------------------------------------------------------- 1 | using Dapper; 2 | using FluentAssertions; 3 | using grate.Configuration; 4 | using PostgreSQL.TestInfrastructure; 5 | using TestCommon.TestInfrastructure; 6 | using static grate.Configuration.KnownFolderKeys; 7 | 8 | namespace PostgreSQL.Running_MigrationScripts; 9 | 10 | [Collection(nameof(PostgreSqlGrateTestContext))] 11 | // ReSharper disable once InconsistentNaming 12 | // ReSharper disable once UnusedType.Global 13 | public class Run_After_Create_Database_scripts(PostgreSqlGrateTestContext testContext, ITestOutputHelper testOutput) 14 | : TestCommon.Generic.Running_MigrationScripts.Run_After_Create_Database_scripts(testContext, testOutput); 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | **Describe the solution you'd like** 14 | 15 | 16 | **Describe alternatives you've considered** 17 | 18 | 19 | **Additional context** 20 | 21 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using TestCommon.Generic; 2 | using TestCommon.TestInfrastructure; 3 | using SqlServerCaseSensitive.TestInfrastructure; 4 | 5 | namespace SqlServerCaseSensitive; 6 | 7 | [Collection(nameof(SqlServerGrateTestContext))] 8 | public class MigrationTables(SqlServerGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : GenericMigrationTables(testContext, testOutput) 10 | { 11 | protected override string CountTableSql(string schemaName, string tableName) 12 | { 13 | return $@" 14 | SELECT count(table_name) FROM INFORMATION_SCHEMA.TABLES 15 | WHERE 16 | TABLE_SCHEMA = '{schemaName}' AND 17 | TABLE_NAME = '{tableName}' COLLATE Latin1_General_CS_AS 18 | "; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /unittests/Sqlite/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.DependencyInjection; 2 | using grate.sqlite.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | using Sqlite.TestInfrastructure; 6 | using TestCommon.TestInfrastructure; 7 | 8 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 9 | 10 | namespace Sqlite; 11 | 12 | // ReSharper disable once UnusedType.Global 13 | public class Startup: TestCommon.Startup 14 | { 15 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 16 | { 17 | services 18 | .AddGrate() 19 | .UseSqlite(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | **To Reproduce** 14 | 15 | 16 | **Expected behavior** 17 | 18 | 19 | **Screenshots** 20 | 21 | 22 | **Desktop (please complete the following information):** 23 | - OS: [e.g. macOS, Linux] 24 | - Version: [e.g. 1.0.2] 25 | 26 | **Additional context** 27 | 28 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sample-service/Program.cs: -------------------------------------------------------------------------------- 1 | using grate; 2 | using grate.SqlServer; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.Extensions.DependencyInjection; 5 | var builder = WebApplication.CreateBuilder(args); 6 | var configuration = builder.Configuration; 7 | builder.Services.AddControllers(); 8 | builder.Services.AddGrate(grateBuilder => 9 | { 10 | grateBuilder.WithAdminConnectionString(configuration.GetConnectionString("AdminConnection")!); 11 | grateBuilder.WithConnectionString(configuration.GetConnectionString("DefaultConnection")!); 12 | grateBuilder.WithSqlFilesDirectory("/db"); 13 | grateBuilder.UseSqlServer(); 14 | }); 15 | var app = builder.Build(); 16 | app.UseRouting(); 17 | app.MapControllers(); 18 | app.Run(); 19 | -------------------------------------------------------------------------------- /examples/test-integration/sample-test-integration/Tests/DatabaseTest.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using Dapper; 3 | using Microsoft.Data.SqlClient; 4 | using Xunit; 5 | 6 | namespace Tests; 7 | 8 | [Collection(nameof(SqlServerCollection))] // tell XUnit we need the SqlServer fixture running before this test starts 9 | public sealed class DatabaseTest 10 | { 11 | [Fact] 12 | public async Task CheckDatabaseConnectivityAndEnsureMigrationRan() 13 | { 14 | var connString = SqlServerFixture.SysAdminConnString; 15 | 16 | await using var conn = new SqlConnection(connString); 17 | var result = await conn.ExecuteScalarAsync("sample_proc", commandType: CommandType.StoredProcedure); 18 | Assert.Equal(10, result); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /installers/deb/template/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: grate 2 | Version: %%%VERSION%%% 3 | Section: database 4 | Depends: libicu-dev (>= 66) 5 | Priority: optional 6 | Architecture: %%%ARCH%%% 7 | Maintainer: Erik A. Brandstadmoen 8 | Description: SQL for the 20s 9 | grate is a SQL scripts migration runner. 10 | . 11 | The goal of grate is to be largely backwards compatible with RoundhousE, 12 | which is an amazing tool. 13 | It is initiated by the main maintainer of RoundhousE for the 14 | last three years. 15 | . 16 | While early versions of grate may not support every last RoundhousE feature, 17 | those features that are implemented should work identically, 18 | or with only very small changes. For detailed information see the migration 19 | docco. -------------------------------------------------------------------------------- /unittests/Basic_tests/DependencyInjection/AddGrate.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Configuration; 3 | using grate.DependencyInjection; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Basic_tests.DependencyInjection; 7 | 8 | // ReSharper disable once InconsistentNaming 9 | public class AddGrate 10 | { 11 | [Fact] 12 | public void Registers_GrateConfiguration_in_the_ServiceCollection() 13 | { 14 | var serviceCollection = new ServiceCollection(); 15 | var builder = GrateConfigurationBuilder.Create(); 16 | var config = builder.Build(); 17 | serviceCollection.AddGrate(config); 18 | serviceCollection.Should().ContainSingle(s => s.ServiceType == typeof(GrateConfiguration)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/ITestDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | 3 | public interface ITestDatabase 4 | { 5 | string AdminConnectionString { get; } 6 | string ConnectionString(string database); 7 | string UserConnectionString(string database); 8 | 9 | /// 10 | /// An external representation of the database. Returns this instance by default, 11 | /// mostly used to be able to access Docker containers both from the outside and the internal docker network 12 | /// (from the inside when testing grate in a docker image, from the outside when performing assertions on the 13 | /// _database_ container from the unit tests afterwards) 14 | /// 15 | public ITestDatabase External => this; 16 | } 17 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/script/migrate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # https://erikbra.github.io/grate/getting-started/ 3 | # https://erikbra.github.io/grate/configuration-options/ 4 | # databasetype 14 | { 15 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 16 | { 17 | services 18 | .AddGrate() 19 | .UsePostgreSQL(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /unittests/Oracle/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.DependencyInjection; 2 | using grate.oracle.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | using Oraclde.TestInfrastructure; 6 | using Oracle.TestInfrastructure; 7 | using TestCommon.TestInfrastructure; 8 | 9 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 10 | 11 | namespace Oracle; 12 | 13 | // ReSharper disable once UnusedType.Global 14 | public class Startup: TestCommon.Startup 15 | { 16 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 17 | { 18 | services 19 | .AddGrate() 20 | .UseOracle(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Basic_tests/StatementSplitter_.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Infrastructure; 3 | using grate.SqlServer.Infrastructure; 4 | 5 | namespace SqlServerCaseSensitive.Basic_tests; 6 | 7 | 8 | // ReSharper disable once InconsistentNaming 9 | public class StatementSplitter_ 10 | { 11 | private readonly StatementSplitter _splitter; 12 | 13 | public StatementSplitter_() 14 | { 15 | _splitter = new StatementSplitter(new SqlServerSyntax()); 16 | } 17 | 18 | [Fact] 19 | public void Splits_and_removes_GO_statements() 20 | { 21 | var original = @" 22 | SELECT @@VERSION; 23 | 24 | 25 | GO 26 | SELECT 1 27 | "; 28 | var batches = _splitter.Split(original); 29 | 30 | batches.Should().HaveCount(2); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/Baseline/up/02_create_scripts_run_table.sql: -------------------------------------------------------------------------------- 1 | -- backwards compatibility, if the table already exists, let update scripts fix text column type issue 2 | IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'{{SchemaName}}.{{ScriptsRunTable}}') AND type in (N'U')) 3 | CREATE TABLE {{SchemaName}}.{{ScriptsRunTable}}( 4 | id bigint IDENTITY(1,1) NOT NULL, 5 | version_id BIGINT NULL, 6 | script_name nvarchar(255) NULL, 7 | text_of_script nvarchar(max) NULL, 8 | text_hash nvarchar(512) NULL, 9 | one_time_script bit NULL, 10 | entry_date datetime NULL, 11 | modified_date datetime NULL, 12 | entered_by nvarchar(50) NULL, 13 | CONSTRAINT PK_{{ScriptsRunTable}}_id PRIMARY KEY CLUSTERED (id) 14 | ) -------------------------------------------------------------------------------- /unittests/SqlServer/Basic_tests/StatementSplitter_.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Infrastructure; 3 | using grate.Migration; 4 | using grate.SqlServer.Infrastructure; 5 | 6 | namespace SqlServer.Statement_Splitting; 7 | 8 | 9 | // ReSharper disable once InconsistentNaming 10 | public class StatementSplitter_ 11 | { 12 | private readonly StatementSplitter _splitter; 13 | 14 | public StatementSplitter_() 15 | { 16 | _splitter = new StatementSplitter(new SqlServerSyntax()); 17 | } 18 | 19 | [Fact] 20 | public void Splits_and_removes_GO_statements() 21 | { 22 | var original = @" 23 | SELECT @@VERSION; 24 | 25 | 26 | GO 27 | SELECT 1 28 | "; 29 | var batches = _splitter.Split(original); 30 | 31 | batches.Should().HaveCount(2); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/01b_version_add_status_column.sql: -------------------------------------------------------------------------------- 1 | -- The MariaDB version below is more elegant, but it is not compatible with MySQL. 2 | -- ALTER TABLE {{SchemaName}}_{{VersionTable}} 3 | -- ADD COLUMN IF NOT EXISTS status varchar(50) NULL;; 4 | 5 | -- MySQL does not support the IF NOT EXISTS clause for ADD COLUMN, as MariaDB does. 6 | -- So, instead of the MariaDB version, we need to use a handler to ignore the error if the column already exists. 7 | -- This is a bit of a hack, but it works. 8 | -- The MariaDB version is more elegant, but it is not compatible with MySQL. 9 | CREATE PROCEDURE create_{{SchemaName}}_{{VersionTable}}() 10 | BEGIN 11 | DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; 12 | ALTER TABLE {{SchemaName}}_{{VersionTable}} 13 | ADD COLUMN status varchar(50) NULL; 14 | END; 15 | -------------------------------------------------------------------------------- /unittests/Oracle/Basic_tests/StatementSplitter_.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Infrastructure; 3 | using grate.Migration; 4 | using grate.Oracle.Infrastructure; 5 | 6 | namespace Oracle.Basic_tests; 7 | 8 | 9 | // ReSharper disable once InconsistentNaming 10 | public class StatementSplitter_ 11 | { 12 | private readonly StatementSplitter _splitter; 13 | 14 | public StatementSplitter_() 15 | { 16 | _splitter = new StatementSplitter(new OracleSyntax()); 17 | } 18 | 19 | [Fact] 20 | public void Splits_and_removes_GO_statements() 21 | { 22 | var original = @" 23 | SELECT * FROM v$version WHERE banner LIKE 'Oracle%'; 24 | 25 | 26 | / 27 | SELECT 1 28 | "; 29 | var batches = _splitter.Split(original); 30 | 31 | batches.Should().HaveCount(2); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /examples/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | db-migration: 4 | #build: . 5 | image: grate-devs/grate:latest 6 | environment: 7 | # don't configure passwords here for real. This is just a sample! 8 | APP_CONNSTRING: "Server=db;Database=grate_test;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True" 9 | VERSION: "1.0.0.0" 10 | DATABASE_TYPE: "sqlserver" # sqlite, oracle, postgresql, sqlserver, mariadb 11 | volumes: 12 | - ./db:/db 13 | - ./output:/output 14 | 15 | depends_on: 16 | - db 17 | db: 18 | image: mcr.microsoft.com/mssql/server:2019-latest 19 | environment: 20 | - SA_PASSWORD=gs8j4AS7h87jHg # again, plain text passwords are bad mmkay! 21 | - ACCEPT_EULA=Y 22 | - MSSQL_PID=Express 23 | ports: 24 | - "1433:1433" -------------------------------------------------------------------------------- /src/grate.core/Exceptions/MigrationException.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | 3 | namespace grate.Exceptions; 4 | 5 | public abstract class MigrationException : Exception 6 | { 7 | public MigrationException(MigrationsFolder folder, string file, string? message) 8 | : this(folder, file, message, null) {} 9 | 10 | public MigrationException(MigrationsFolder folder, string file, string? message, Exception? innerException) 11 | : base(message, innerException) 12 | { 13 | Folder = folder; 14 | File = file; 15 | _message = message; 16 | } 17 | 18 | public MigrationsFolder Folder { get; set; } 19 | public string File { get; set; } 20 | 21 | private readonly string? _message; 22 | 23 | public override string Message => $"{File}: { _message ?? InnerException?.Message}"; 24 | } 25 | -------------------------------------------------------------------------------- /src/grate/Configuration/CommandLineGrateEnvironment.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using grate.Infrastructure; 3 | 4 | namespace grate.Configuration; 5 | 6 | internal record CommandLineGrateEnvironment: GrateEnvironment, IEnumerable, IEnumerable 7 | { 8 | public CommandLineGrateEnvironment(string value) : base(value) 9 | { 10 | } 11 | 12 | public CommandLineGrateEnvironment(IEnumerable environments) : base(environments) 13 | { 14 | } 15 | 16 | IEnumerator IEnumerable.GetEnumerator() => 17 | new GrateEnvironment[] { this }.AsEnumerable().GetEnumerator(); 18 | 19 | public IEnumerator GetEnumerator() => Environments.GetEnumerator(); 20 | IEnumerator IEnumerable.GetEnumerator() => Environments.GetEnumerator(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.DependencyInjection; 2 | using grate.sqlserver.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.DependencyInjection.Extensions; 5 | using Microsoft.Extensions.Hosting; 6 | using SqlServerCaseSensitive.TestInfrastructure; 7 | using TestCommon; 8 | 9 | namespace SqlServerCaseSensitive; 10 | 11 | // ReSharper disable once UnusedType.Global 12 | public class Startup: Startup 13 | { 14 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 15 | { 16 | services 17 | .AddGrate() 18 | .UseSqlServer(); 19 | 20 | services.TryAddTransient(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/grate.oracle/DependencyInjection/RegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using grate.DependencyInjection; 3 | using grate.Migration; 4 | using grate.Oracle.Migration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace grate.oracle.DependencyInjection; 9 | 10 | public static class RegistrationExtensions 11 | { 12 | public static IServiceCollection UseOracle(this IServiceCollection services) 13 | { 14 | services.TryAddTransient(); 15 | return services; 16 | } 17 | 18 | public static IServiceCollection AddGrateWithOracle(this IServiceCollection services, GrateConfiguration? config = null) => 19 | services 20 | .AddGrate(config ?? GrateConfiguration.Default) 21 | .UseOracle(); 22 | } 23 | -------------------------------------------------------------------------------- /unittests/MariaDB/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.DependencyInjection; 2 | using grate.mariadb.DependencyInjection; 3 | using MariaDB.TestInfrastructure; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.DependencyInjection.Extensions; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 9 | 10 | namespace MariaDB; 11 | 12 | // ReSharper disable once UnusedType.Global 13 | public class Startup: TestCommon.Startup 14 | { 15 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 16 | { 17 | services 18 | .AddGrate() 19 | .UseMariaDb(); 20 | services.TryAddTransient(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/grate.mariadb/DependencyInjection/RegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using grate.DependencyInjection; 3 | using grate.MariaDb.Migration; 4 | using grate.Migration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace grate.mariadb.DependencyInjection; 9 | 10 | public static class RegistrationExtensions 11 | { 12 | public static IServiceCollection UseMariaDb(this IServiceCollection services) 13 | { 14 | services.TryAddTransient(); 15 | return services; 16 | } 17 | 18 | public static IServiceCollection AddGrateWithMariaDb(this IServiceCollection services, GrateConfiguration? config = null) => 19 | services 20 | .AddGrate(config ?? GrateConfiguration.Default) 21 | .UseMariaDb(); 22 | } 23 | -------------------------------------------------------------------------------- /unittests/SqlServer/Basic_tests/TokenReplacerTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Configuration; 3 | using grate.Infrastructure; 4 | using grate.Migration; 5 | 6 | namespace SqlServer.Basic_tests; 7 | 8 | public class TokenReplacerTests(IDatabase database) 9 | { 10 | [Fact] 11 | public void EnsureDbMakesItToTokens() 12 | { 13 | var config = new GrateConfiguration() 14 | { 15 | ConnectionString = "Server=(LocalDb)\\mssqllocaldb;Database=TestDb;", 16 | Folders = Folders.Default 17 | }; 18 | 19 | 20 | database.InitializeConnections(config); 21 | 22 | var provider = new TokenProvider(config, database); 23 | var tokens = provider.GetTokens(); 24 | 25 | tokens["DatabaseName"].Should().Be("TestDb"); 26 | tokens["ServerName"].Should().Be("(LocalDb)\\mssqllocaldb"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/DescriptiveTestObjects.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using grate.Configuration; 3 | 4 | namespace TestCommon.TestInfrastructure; 5 | 6 | public static class DescriptiveTestObjects 7 | { 8 | public static MigrationsFolderWithDescription? Describe(MigrationsFolder? folder, 9 | [CallerArgumentExpression(nameof(folder))] string description = "") => 10 | folder is { } ? new MigrationsFolderWithDescription(folder, description) : null; 11 | } 12 | 13 | public record MigrationsFolderWithDescription : MigrationsFolder 14 | { 15 | public MigrationsFolderWithDescription(MigrationsFolder baseFolder, string description) : base(baseFolder) 16 | { 17 | Description = description; 18 | } 19 | 20 | private string Description { get; } = null!; 21 | public override string ToString() => Description; 22 | } 23 | -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/ISyntax.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Infrastructure; 2 | 3 | /// 4 | /// Interface for the various SQL dialects that grate supports. 5 | /// 6 | public interface ISyntax 7 | { 8 | string StatementSeparatorRegex { get; } 9 | string CurrentDatabase { get; } 10 | string ListDatabases { get; } 11 | string CreateDatabase(string databaseName, string? password); 12 | /// 13 | /// Syntax to drop a database if it exists, and do nothing if not. 14 | /// 15 | /// 16 | /// 17 | string DropDatabase(string databaseName); 18 | string TableWithSchema(string schemaName, string tableName); 19 | string LimitN(string sql, int n); 20 | string ReturnId { get; } 21 | string ResetIdentity(string schemaName, string tableName, long value); 22 | } 23 | -------------------------------------------------------------------------------- /unittests/PostgreSQL/Statement_Splitting/NpgsqlQueryParser_.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Infrastructure.Npgsql; 3 | 4 | namespace PostgreSQL.Infrastructure; 5 | 6 | public class NpgsqlQueryParser_ 7 | { 8 | [Fact] 9 | public void Can_split_create_index_concurrently() 10 | { 11 | //var statements = ReflectionNpgsqlQueryParser.Split(sqlStatement); 12 | var statements = NativeSqlQueryParser.Split(sqlStatement); 13 | statements.Should().HaveCount(4); 14 | } 15 | 16 | private const string sqlStatement = @" 17 | DROP INDEX IF EXISTS IX_column1 CASCADE; 18 | CREATE INDEX CONCURRENTLY IX_column1 ON public.table1 19 | USING btree 20 | ( 21 | column1 22 | ); 23 | 24 | DROP INDEX IF EXISTS IX_column2 CASCADE; 25 | CREATE INDEX CONCURRENTLY IX_column2 ON public.table1 26 | USING btree 27 | ( 28 | column2 29 | ); 30 | "; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /unittests/SqlServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using grate.DependencyInjection; 2 | using grate.sqlserver.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.DependencyInjection.Extensions; 5 | using Microsoft.Extensions.Hosting; 6 | using SqlServer.TestInfrastructure; 7 | 8 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 9 | 10 | namespace SqlServer; 11 | 12 | // ReSharper disable once UnusedType.Global 13 | public class Startup: TestCommon.Startup 14 | { 15 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 16 | { 17 | services 18 | .AddGrate() 19 | .UseSqlServer(); 20 | 21 | services.TryAddTransient(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /unittests/SqlServerCaseSensitive/Basic_tests/TokenReplacerTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using grate.Configuration; 3 | using grate.Infrastructure; 4 | using grate.Migration; 5 | 6 | namespace SqlServerCaseSensitive.Basic_tests; 7 | 8 | public class TokenReplacerTests(IDatabase database) 9 | { 10 | [Fact] 11 | public void EnsureDbMakesItToTokens() 12 | { 13 | var config = new GrateConfiguration() 14 | { 15 | ConnectionString = "Server=(LocalDb)\\mssqllocaldb;Database=TestDb;", 16 | Folders = Folders.Default 17 | }; 18 | 19 | 20 | database.InitializeConnections(config); 21 | 22 | var provider = new TokenProvider(config, database); 23 | var tokens = provider.GetTokens(); 24 | 25 | tokens["DatabaseName"].Should().Be("TestDb"); 26 | tokens["ServerName"].Should().Be("(LocalDb)\\mssqllocaldb"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/grate.sqlserver/Bootstrapping/Sql/Baseline/up/03_create_scripts_run_errors_table.sql: -------------------------------------------------------------------------------- 1 | -- backwards compatibility, if the table already exists, let update scripts fix text column type issue 2 | IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'{{SchemaName}}.{{ScriptsRunErrorsTable}}') AND type in (N'U')) 3 | CREATE TABLE {{SchemaName}}.{{ScriptsRunErrorsTable}}( 4 | id bigint IDENTITY(1,1) NOT NULL, 5 | repository_path nvarchar(255) NULL, 6 | version nvarchar(50) NULL, 7 | script_name nvarchar(255) NULL, 8 | text_of_script nvarchar(max) NULL, 9 | erroneous_part_of_script nvarchar(max) NULL, 10 | error_message nvarchar(max) NULL, 11 | entry_date datetime NULL, 12 | modified_date datetime NULL, 13 | entered_by nvarchar(50) NULL, 14 | CONSTRAINT PK_{{ScriptsRunErrorsTable}}_id PRIMARY KEY CLUSTERED (id) 15 | ) -------------------------------------------------------------------------------- /src/grate/Configuration/ArgumentParsers.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine.Parsing; 2 | 3 | namespace grate.Configuration; 4 | 5 | internal static class ArgumentParsers 6 | { 7 | private static readonly char[] Delimiters = [',', ';']; 8 | 9 | // System.CommandLine beta3 has broken support for basic public constructors in order to provide better support for trimming assemblies. 10 | // Specify a parser to work around this, see https://github.com/dotnet/command-line-api/issues/1664 11 | public static CommandLineGrateEnvironment? ParseEnvironment(ArgumentResult result) 12 | { 13 | return result.Tokens.Any() 14 | ? new CommandLineGrateEnvironment(result.Tokens.SelectMany(GetEnvironments)) 15 | : null; 16 | } 17 | 18 | private static IEnumerable GetEnvironments(Token token) 19 | { 20 | return token.Value.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/variables.tf: -------------------------------------------------------------------------------- 1 | # variable "MARIADB_ROOT_PASSWORD" { 2 | # sensitive = false 3 | # } 4 | 5 | locals { 6 | mariadb_images = [ 7 | #"mariadb:5.5", 8 | #"mariadb:10.0", 9 | "mariadb:10.10" 10 | ] 11 | 12 | # Cannot get these to work yet, for some reason... need to look into it 13 | oracle_images = [ 14 | "gvenzl/oracle-free:latest-faststart", 15 | "gvenzl/oracle-xe:latest-faststart", 16 | "gvenzl/oracle-xe:18-faststart", 17 | #"gvenzl/oracle-xe:11-faststart" 18 | ] 19 | 20 | postgresql_images = [ 21 | "postgres:16", 22 | "postgres:15", 23 | "postgres:14", 24 | "postgres:13", 25 | "postgres:12" 26 | ] 27 | 28 | sqlserver_images = [ 29 | #"mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04", 30 | "mcr.microsoft.com/mssql/server:2022-latest", 31 | "mcr.microsoft.com/mssql/server:2019-latest", 32 | "mcr.microsoft.com/mssql/server:2017-latest" 33 | ] 34 | } -------------------------------------------------------------------------------- /src/grate.sqlite/DependencyInjection/RegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using grate.DependencyInjection; 3 | using grate.Migration; 4 | using grate.Sqlite.Migration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace grate.sqlite.DependencyInjection; 9 | 10 | public static class RegistrationExtensions 11 | { 12 | // ReSharper disable once InconsistentNaming 13 | public static IServiceCollection UseSqlite(this IServiceCollection services) 14 | { 15 | services.TryAddTransient(); 16 | return services; 17 | } 18 | 19 | // ReSharper disable once InconsistentNaming 20 | public static IServiceCollection AddGrateWithSqlite(this IServiceCollection services, GrateConfiguration? config = null) => 21 | services 22 | .AddGrate(config ?? GrateConfiguration.Default) 23 | .UseSqlite(); 24 | } 25 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_02a_fix_version_table_casing.sql: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE create_{{SchemaName}}_fix_version_table_casing() 2 | BEGIN 3 | DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; 4 | IF EXISTS (SELECT 1 5 | FROM INFORMATION_SCHEMA.TABLES 6 | WHERE table_schema = DATABASE() 7 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{VersionTableLowerCase}}' -- exists in db 8 | ) 9 | THEN 10 | -- we need to make sure the target table is not existing, otherwise, mariadb will throw an error like table already exists 11 | IF NOT EXISTS (SELECT 1 12 | FROM INFORMATION_SCHEMA.COLUMNS 13 | WHERE table_schema = DATABASE() 14 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{VersionTable}}' 15 | ) 16 | THEN 17 | RENAME TABLE `{{SchemaName}}_{{VersionTableLowerCase}}` TO `{{SchemaName}}_{{VersionTable}}`; 18 | END IF; 19 | END IF; 20 | END; 21 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03a_fix_scriptsrun_table_casing.sql: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE create_{{SchemaName}}_fix_scriptsrun_table_casing() 2 | BEGIN 3 | DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; 4 | IF EXISTS (SELECT 1 5 | FROM INFORMATION_SCHEMA.TABLES 6 | WHERE table_schema = DATABASE() 7 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{ScriptsRunTableLowerCase}}' -- exists in db 8 | ) 9 | THEN 10 | -- we need to make sure the target table is not existing, otherwise, mariadb will throw an error like table already exists 11 | IF NOT EXISTS (SELECT 1 12 | FROM INFORMATION_SCHEMA.COLUMNS 13 | WHERE table_schema = DATABASE() 14 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{ScriptsRunTable}}' 15 | ) 16 | THEN 17 | RENAME TABLE `{{SchemaName}}_{{ScriptsRunTableLowerCase}}` TO `{{SchemaName}}_{{ScriptsRunTable}}`; 18 | END IF; 19 | END IF; 20 | END; 21 | -------------------------------------------------------------------------------- /src/grate.sqlserver/DependencyInjection/RegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using grate.DependencyInjection; 3 | using grate.Migration; 4 | using grate.SqlServer.Migration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace grate.sqlserver.DependencyInjection; 9 | 10 | public static class RegistrationExtensions 11 | { 12 | // ReSharper disable once InconsistentNaming 13 | public static IServiceCollection UseSqlServer(this IServiceCollection services) 14 | { 15 | services.TryAddTransient(); 16 | return services; 17 | } 18 | 19 | // ReSharper disable once InconsistentNaming 20 | public static IServiceCollection AddGrateWithSqlServer(this IServiceCollection services, GrateConfiguration? config = null) => 21 | services 22 | .AddGrate(config ?? GrateConfiguration.Default) 23 | .UseSqlServer(); 24 | } 25 | -------------------------------------------------------------------------------- /unittests/Oracle/MigrationTables.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using Oracle.TestInfrastructure; 3 | using TestCommon.Generic; 4 | using TestCommon.TestInfrastructure; 5 | 6 | namespace Oracle; 7 | 8 | [Collection(nameof(OracleGrateTestContext))] 9 | public class MigrationTables(OracleGrateTestContext testContext, ITestOutputHelper testOutput) 10 | : GenericMigrationTables(testContext, testOutput) 11 | { 12 | 13 | protected override Task CheckTableCasing(string tableName, string funnyCasing, Func setTableName) 14 | { 15 | TestOutput.WriteLine("Oracle has never been case-sensitive for grate. No need to introduce that now."); 16 | return Task.CompletedTask; 17 | } 18 | 19 | protected override string CountTableSql(string schemaName, string tableName) 20 | { 21 | return $@" 22 | SELECT COUNT(table_name) FROM user_tables 23 | WHERE 24 | lower(table_name) = '{tableName.ToLowerInvariant()}'"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/grate.postgresql/DependencyInjection/RegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | using grate.Configuration; 2 | using grate.DependencyInjection; 3 | using grate.Migration; 4 | using grate.PostgreSql.Migration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace grate.postgresql.DependencyInjection; 9 | 10 | public static class RegistrationExtensions 11 | { 12 | // ReSharper disable once InconsistentNaming 13 | public static IServiceCollection UsePostgreSQL(this IServiceCollection services) 14 | { 15 | services.TryAddTransient(); 16 | return services; 17 | } 18 | 19 | // ReSharper disable once InconsistentNaming 20 | public static IServiceCollection AddGrateWithPostgreSQL(this IServiceCollection services, GrateConfiguration? config = null) => 21 | services 22 | .AddGrate(config ?? GrateConfiguration.Default) 23 | .UsePostgreSQL(); 24 | } 25 | -------------------------------------------------------------------------------- /examples/k8s/initcontainer/sample-service/Controllers/GrateController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Data.SqlClient; 3 | using Dapper; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.Extensions.Configuration; 7 | using System; 8 | namespace Controllers; 9 | 10 | [Route("api/[controller]")] 11 | [ApiController] 12 | public class Grate : ControllerBase 13 | { 14 | [HttpGet] 15 | public async Task Hello([FromServices] IConfiguration configuration) 16 | { 17 | var connectionString = configuration["ConnectionStrings:DefaultConnection"] ?? throw new Exception("No connection string found in appsettings"); 18 | var dbConnection = new SqlConnection(connectionString); 19 | var query = "select id, name from grate_test"; 20 | var result = await dbConnection.QueryAsync<(int, string)>(query); 21 | return new OkObjectResult(result.Select(r => new { id = r.Item1, name = r.Item2 }).ToArray()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /unittests/MariaDB/Running_MigrationScripts/Failing_Scripts.cs: -------------------------------------------------------------------------------- 1 | using MariaDB.TestInfrastructure; 2 | using TestCommon.TestInfrastructure; 3 | 4 | namespace MariaDB.Running_MigrationScripts; 5 | 6 | [Collection(nameof(MariaDbGrateTestContext))] 7 | // ReSharper disable once InconsistentNaming 8 | public class Failing_Scripts(MariaDbGrateTestContext testContext, ITestOutputHelper testOutput) 9 | : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) 10 | { 11 | protected override string ExpectedStartOfErrorMessageForInvalidSql => 12 | """ 13 | Update ("up"): 14 | -------------------------------------------------------------------------------- 15 | 2_failing.sql: Unknown column 'TOP' in 'field list' 16 | """; 17 | 18 | 19 | protected override IDictionary ExpectedErrorDetails => new Dictionary 20 | { 21 | {"Server Error Code", 1054}, 22 | {"SqlState", "42S22"} 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/BatchSplitterReplacer.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using static System.Text.RegularExpressions.RegexOptions; 3 | 4 | namespace grate.Infrastructure; 5 | 6 | internal class BatchSplitterReplacer 7 | { 8 | private string Replacement { get; } 9 | private readonly Regex _regex; 10 | 11 | public BatchSplitterReplacer(ISyntax syntax) 12 | { 13 | var pattern = syntax.StatementSeparatorRegex; 14 | Replacement = StatementSplitter.BatchTerminatorReplacementString; 15 | 16 | _regex = new Regex(pattern, IgnoreCase | Multiline); 17 | } 18 | 19 | public string Replace(string text) => _regex.Replace(text, ReplaceBatchSeparator); 20 | 21 | private string ReplaceBatchSeparator(Match match) 22 | { 23 | var groups = match.Groups; 24 | var replacement = groups["BATCHSPLITTER"].Success ? Replacement : string.Empty; 25 | return groups["KEEP1"].Value + replacement + groups["KEEP2"].Value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/grate.mariadb/Infrastructure/MariaDbScriptFailed.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using grate.Configuration; 3 | using grate.Exceptions; 4 | using MySqlConnector; 5 | 6 | namespace grate.MariaDb.Infrastructure; 7 | 8 | public class MariaDbScriptFailed: ScriptFailed 9 | { 10 | public MariaDbScriptFailed(MigrationsFolder folder, string file, string? scriptText, Exception cause) 11 | : base(folder, file, scriptText, cause) 12 | { 13 | } 14 | 15 | protected override (int? line, int position) LineAndPosition => (0, 0); 16 | protected override string? ErrorSnippet => null; 17 | 18 | protected override int Position => this.DbException is MySqlException mySqlException 19 | ? mySqlException.Number 20 | : 0; 21 | 22 | protected override IDictionary GetDbScriptErrors() 23 | => InnerException!.Data 24 | .Cast() 25 | .ToDictionary(entry => entry.Key.ToString()!, entry => entry.Value); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /unittests/Docker/IncludeTests.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 14 | 15 | 18 | 19 | 20 | PreserveNewest 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/grate.mariadb/Bootstrapping/Sql/GrateStructure/up/00_03a_fix_scriptsrunerrors_table_casing.sql: -------------------------------------------------------------------------------- 1 | CREATE PROCEDURE create_{{SchemaName}}_fix_scriptsrunerrors_table_casing() 2 | BEGIN 3 | DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; 4 | IF EXISTS (SELECT 1 5 | FROM INFORMATION_SCHEMA.TABLES 6 | WHERE table_schema = DATABASE() 7 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{ScriptsRunErrorsTableLowerCase}}' -- exists in db 8 | ) 9 | THEN 10 | -- we need to make sure the target table is not existing, otherwise, mariadb will throw an error like table already exists 11 | IF NOT EXISTS (SELECT 1 12 | FROM INFORMATION_SCHEMA.COLUMNS 13 | WHERE table_schema = DATABASE() 14 | AND BINARY `table_name` = BINARY '{{SchemaName}}_{{ScriptsRunErrorsTable}}' 15 | ) 16 | THEN 17 | RENAME TABLE `{{SchemaName}}_{{ScriptsRunErrorsTableLowerCase}}` TO `{{SchemaName}}_{{ScriptsRunErrorsTable}}`; 18 | END IF; 19 | END IF; 20 | END; 21 | -------------------------------------------------------------------------------- /unittests/CommandLine/IncludeTests.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 14 | 15 | 18 | 19 | 20 | PreserveNewest 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/k8s/multitenancy/sample-service/Controllers/GrateController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Dapper; 5 | using grate.Configuration; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.Data.SqlClient; 8 | using Microsoft.Extensions.Configuration; 9 | using SampleService.Extension; 10 | namespace Controllers; 11 | 12 | [Route("api/[controller]")] 13 | [ApiController] 14 | public class Grate : ControllerBase 15 | { 16 | [HttpGet] 17 | public async Task Hello([FromServices] GrateConfiguration grateConfiguration, [FromQuery] string databaseName) 18 | { 19 | grateConfiguration.SwitchDatabase(databaseName); 20 | var dbConnection = new SqlConnection(grateConfiguration.ConnectionString); 21 | var query = "select id, name from grate_test"; 22 | var result = await dbConnection.QueryAsync<(int, string)>(query); 23 | return new OkObjectResult(result.Select(r => new { id = r.Item1, name = r.Item2 }).ToArray()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/grate.core/Configuration/GrateConfigurationBuilder.Factory.cs: -------------------------------------------------------------------------------- 1 | namespace grate.Configuration; 2 | 3 | public partial class GrateConfigurationBuilder 4 | { 5 | 6 | /// 7 | /// Create the grate configuration builder from an existing service collection and grate configuration. 8 | /// 9 | /// GrateConfiguration 10 | /// GrateConfigurationBuilder 11 | public static GrateConfigurationBuilder Create(GrateConfiguration grateConfiguration) 12 | { 13 | return new GrateConfigurationBuilder(grateConfiguration); 14 | } 15 | 16 | /// 17 | /// Create the default grate configuration builder with existing service collection. 18 | /// 19 | /// GrateConfigurationBuilder 20 | public static GrateConfigurationBuilder Create() 21 | { 22 | return new GrateConfigurationBuilder(GrateConfiguration.Default with { NonInteractive = true }); 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /unittests/CommandLine/CommandLine.Common/Startup_T.cs: -------------------------------------------------------------------------------- 1 | using CommandLine.Common.TestInfrastructure; 2 | using grate.Configuration; 3 | using grate.Migration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using TestCommon.TestInfrastructure; 7 | 8 | namespace CommandLine.Common; 9 | 10 | // ReSharper disable once UnusedType.Global 11 | public abstract class Startup< 12 | TTestContainerDatabase, 13 | TExternalDatabase, 14 | TGrateTestContext>: TestCommon.Startup 15 | where TTestContainerDatabase : ITestDatabase 16 | where TExternalDatabase : ITestDatabase 17 | where TGrateTestContext : IGrateTestContext 18 | { 19 | protected abstract DatabaseType DatabaseType { get; } 20 | 21 | protected override void ConfigureExtraServices(IServiceCollection services, HostBuilderContext context) 22 | { 23 | services.AddSingleton(new CommandLineGrateMigrator(DatabaseType)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/dotnet/sdk:8.0", 3 | "features": { 4 | "ghcr.io/devcontainers/features/docker-in-docker:2": {}, 5 | "ghcr.io/devcontainers/features/github-cli:1": { 6 | "version": "2" 7 | }, 8 | "ghcr.io/devcontainers/features/powershell:1": { 9 | "version": "latest" 10 | }, 11 | "ghcr.io/devcontainers/features/common-utils:2": {}, 12 | "ghcr.io/devcontainers/features/dotnet:2": { 13 | "version": "none", 14 | "dotnetRuntimeVersions": "7.0", 15 | "aspNetCoreRuntimeVersions": "7.0" 16 | } 17 | }, 18 | "customizations": { 19 | "vscode": { 20 | "extensions": [ 21 | "GitHub.copilot", 22 | "GitHub.vscode-github-actions", 23 | "ms-dotnettools.vscode-dotnet-runtime", 24 | "ms-dotnettools.csdevkit", 25 | "ms-dotnetools.csharp" 26 | ] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/grate.core/Infrastructure/TokenReplacer.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace grate.Infrastructure; 4 | 5 | internal static class TokenReplacer // When we have a second impl we'll add an interface :) 6 | { 7 | public static string ReplaceTokens(Dictionary tokens, string? textToReplace) 8 | { 9 | if (string.IsNullOrEmpty(textToReplace)) 10 | { 11 | return string.Empty; 12 | } 13 | 14 | 15 | //This regex is magic to me, but it worked in Roundhouse! 16 | var regex = new Regex("{{(?\\w+)}}"); 17 | 18 | string output = regex.Replace(textToReplace, m => 19 | { 20 | var key = m.Groups["key"].Value; 21 | if (!tokens.ContainsKey(key)) 22 | { 23 | return "{{" + key + "}}"; //leave unrecognised token alone 24 | } 25 | 26 | var value = tokens[key]; 27 | return value ?? string.Empty; 28 | }); 29 | 30 | return output; 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /test-infra/terraform/test-environment/aca-env-subnets.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_network_security_group" "aca-env" { 2 | name = "aca-env-nsg" 3 | location = data.azurerm_resource_group.grate-integration-tests.location 4 | resource_group_name = data.azurerm_resource_group.grate-integration-tests.name 5 | } 6 | 7 | resource "azurerm_virtual_network" "aca-env" { 8 | name = "aca-env-vnet" 9 | location = data.azurerm_resource_group.grate-integration-tests.location 10 | resource_group_name = data.azurerm_resource_group.grate-integration-tests.name 11 | address_space = ["10.1.0.0/16"] 12 | # dns_servers = ["10.0.0.4", "10.0.0.5"] 13 | } 14 | 15 | resource "azurerm_subnet" "aca-env" { 16 | name = "aca-env-infra-subnet" 17 | virtual_network_name = azurerm_virtual_network.aca-env.name 18 | resource_group_name = azurerm_virtual_network.aca-env.resource_group_name 19 | address_prefixes = [ "10.1.0.0/21" ] 20 | #security_group = azurerm_network_security_group.aca-env.id 21 | } -------------------------------------------------------------------------------- /docs/ConfigurationOptions/ResponseFiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Response (.rsp) Files" 3 | permalink: /response-files/ 4 | parent: Configuration options 5 | --- 6 | # Response (.rsp) Files 7 | 8 | As grate is built on the `System.CommandLine` libraries it has built in [support for Response (`.rsp`) files](https://github.com/dotnet/command-line-api/blob/main/docs/Features-overview.md#Response-files). These can be used to pass a standard set of command line arguments to the tool in lieu of a long command line. 9 | 10 | For example, if you created a `grate_settings.rsp` file with the following content 11 | ``` bash 12 | # Custom RSP for a local development drop/create migration 13 | -cs SomeConnectionString 14 | -f ./db 15 | --env DEV 16 | --drop 17 | --version 1.0 18 | --ut=my_token=myvalue 19 | ``` 20 | 21 | and ran it via `grate @./grate_settings.rsp` it would be the equivalent to the following command: 22 | ``` bash 23 | grate -cs SomeConnectionString -f ./db --env DEV --drop --version 1.0 --ut=my_token=myvalue 24 | ``` 25 | 26 | Note that the `@` before the file path is required. 27 | -------------------------------------------------------------------------------- /unittests/TestCommon/TestInfrastructure/RandomExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace TestCommon.TestInfrastructure; 2 | 3 | public static class RandomExtensions 4 | { 5 | // ReSharper disable once InconsistentNaming 6 | private static readonly char[] DefaultAllowedChars = "ABCDEFHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz".ToCharArray(); 7 | 8 | public static string GetString(this Random random, int length, string allowedChars) 9 | => GetString(random, length, allowedChars.ToCharArray()); 10 | 11 | public static string GetString(this Random random, int length, char[]? allowedChars = null) 12 | { 13 | allowedChars ??= DefaultAllowedChars; 14 | 15 | var bytes = new byte[length]; 16 | random.NextBytes(bytes); 17 | 18 | var allowedCharLength = (byte)allowedChars.Length; 19 | 20 | char[] chars = new char[length]; 21 | 22 | for (int i = 0; i < length; i++) 23 | { 24 | chars[i] = allowedChars[bytes[i] % allowedCharLength]; 25 | } 26 | 27 | return new string(chars); 28 | } 29 | 30 | } 31 | --------------------------------------------------------------------------------