├── .devcontainer ├── Dockerfile ├── devcontainer.json ├── postCreateCommand.sh ├── postStartCommand.sh ├── sqlserver.yml ├── tSQLtOfficialSigningKey.crt ├── tSQLtOfficialSigningKey.key └── tSQLtOfficialSigningKey.pfx ├── .github ├── CODEOWNERS └── workflows │ ├── aks_build_and_test.yml │ ├── aks_build_container_images.yml │ ├── aks_cicd_environment_setup.yml │ ├── aks_manage_cluster.yml │ └── build_and_test_on_spawn.yml ├── .gitignore ├── Build ├── ChangeSigningKey_ReadMe.txt ├── CommonFunctionsAndMethods.psm1 ├── License.txt ├── LocalBuild.ps1 ├── LocalValidate.ps1 ├── Readme.md ├── ReleaseNotes.txt ├── SQL │ ├── Add(tSQLt.Built)ToExampleDB.sql │ ├── ChangeDbAndExecuteStatement(tSQLt.Build).sql │ ├── CreateBuildDbBuildOrder.txt │ ├── CreateBuildDbStub.sql │ ├── CreateLogin(tSQLt.Build).sql │ ├── DisableExternalAccess.sql │ ├── Drop(master.tSQLt_testutil).sql │ ├── Drop(tSQLtAssemblyKey)(Pre2017).sql │ ├── EnableExternalAccess.sql │ ├── ExecuteAs(tSQLt.Build).sql │ ├── ExecuteAs(tSQLt.Build.SA).sql │ ├── ExecuteAsCleanup.sql │ ├── ExecuteResetValidationServer.sql │ ├── ForceDropTempProcedures.sql │ ├── GetFailedTestCount.sql │ ├── GetFriendlySQLServerVersion.template.sql │ ├── GetSQLServerVersion.sql │ ├── GrantBuildPermissions.sql │ ├── Install(master.tSQLt_testutil).sql │ ├── Install(tSQLtAssemblyKey).sql │ ├── PrintVersionInfo.sql │ ├── SeparatorTemplate.sql │ └── UseTempDb.sql ├── SQLServerConnection.ps1 ├── reviewneeded │ ├── Import-PfxCert.ps1 │ ├── Install the tSQLt build.docx │ ├── NewRelease.doc │ └── Setup.bat ├── tSQLt_Build.ps1 ├── tSQLt_Build │ ├── ConcatenateFiles.ps1 │ ├── CreateAssemblyGenerator.ps1 │ ├── CreateDropClassStatement.ps1 │ ├── GetAssemblyInfo.ps1 │ └── PackagetSQLtSnippets.ps1 ├── tSQLt_BuildCLR.ps1 ├── tSQLt_BuildDacpac.ps1 ├── tSQLt_BuildPackage.ps1 ├── tSQLt_BuildTests.ps1 ├── tSQLt_Validate.ps1 ├── tSQLt_ValidateRunAll.ps1 ├── tSQLt_ValidateRunExampleTests.ps1 └── tSQLt_ValidateRuntSQLtTests.ps1 ├── CI ├── AKS │ ├── docker │ │ ├── Dockerfile.mssql2012 │ │ ├── Dockerfile.mssql2014 │ │ ├── Dockerfile.mssql2016 │ │ ├── Dockerfile.mssql2017 │ │ ├── Dockerfile.mssql2019 │ │ ├── README.md │ │ ├── changeSqlLogin.ps1 │ │ ├── start.ps1 │ │ └── sxs │ │ │ ├── Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~en-US~.cab │ │ │ ├── Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~en-US~.cab │ │ │ ├── microsoft-windows-internetexplorer-optional-package~31bf3856ad364e35~amd64~~.cab │ │ │ └── microsoft-windows-netfx3-ondemand-package~31bf3856ad364e35~amd64~~.cab │ ├── envSetup │ │ ├── buildAndPushImage.ps1 │ │ ├── createContainerBuildMachine.ps1 │ │ ├── manualPrep.ps1 │ │ ├── setup.ps1 │ │ ├── setupBuildMachine.ps1 │ │ └── testBuildMachine.ps1 │ └── mssql.deployment.windows-template.yml ├── Azure-DevOps │ ├── .editorconfig │ ├── AZ_MainPipeline.yml │ ├── AZ_NightlyCleanup.yml │ ├── AZ_TempTest.yml │ ├── ContributorWithAuthorizationDelete.json │ ├── CreateSQLContainer.ps1 │ ├── CreateSQLContainerAndIpAddressModule.bicep │ ├── CreateSQLContainerTemplate.bicep │ ├── CreateSQLVM.ps1 │ ├── CreateSQLVM_azcli.ps1 │ ├── CreateSqlVirtualMachineTemplate-2008R2.bicep │ ├── CreateSqlVirtualMachineTemplate.bicep │ └── GetSQLServerVersion.sql └── CI.ssmssqlproj ├── Examples ├── BuildOrder.txt ├── CreateDatabase.sql ├── Example_Screenshot.jpg ├── Examples.sqlproj ├── Examples.ssmssqlproj ├── Source.sql ├── TestCaseTemplate.sql ├── TestThatExamplesAreDeployed.sql └── Tests.sql ├── Experiments ├── AnnotationParser.sql ├── AssertEqualsTable_PerformanceQueries.sql ├── AsynchronousExecution.sql ├── CallParameters.sql ├── CaptureTestExecTimes.sql ├── CertificateTest.sql ├── CollationTests.sql ├── CreateSigningCertificate.ps1 ├── CreateXEventSession_SSP&Batch.sql ├── Debugging tSQLt.tdf ├── EXPERIMENTS.sql ├── Experiments.sqlproj ├── Experiments.ssmssqlproj ├── FunctionBinding.sql ├── GenerateLargeXMLResult.sql ├── GenerateTestsForResultsetFilterDataTypes.sql ├── GetDir.ps1 ├── IncludeTest1.ps1 ├── IncludeTest2.ps1 ├── InvokeSqlcmdTest.ps1 ├── LIKE4000.sql ├── MSSQL Defect Try-Catch Invalidates Transaction.sql ├── NameResolutionResearch.sql ├── ObjectType_to_ExtendedPropertyLevelType_mapping.xlsx ├── ParsingDisaster.sql ├── ReadXEventSession.sql ├── RunExternalAccessKeyExistsTests.sql ├── RunTestsManually.bat ├── SM query - read trace table.sql ├── SQLCmdTest.1.1.sql ├── SQLCmdTest.1.2.sql ├── SQLCmdTest.1.sql ├── SpProcPrototype.sql ├── TFS │ └── JUnit │ │ └── SourceDir │ │ ├── v10.0 │ │ └── BuildExtensions │ │ │ └── xslt │ │ │ └── junit_trx.xslt │ │ └── v9.0 │ │ └── BuildExtensions │ │ └── xslt │ │ └── junit_trx.xslt ├── TestingTransactionNames.sql ├── UnprepareServer.sql ├── WAITFOR_DELAY_Tests.sql ├── WaitForTester.sql ├── XMLExperiment.sql ├── sqlServerAlias.ps1 ├── sqlcmdErrorHandling.ps1 ├── tSQLtListObjects.sql └── tSQLtOfficialSigningKey.pfx ├── OtherFiles ├── Download at tSQLt.org.png └── Please download at tSQLt.org.txt ├── README.md ├── Snippets ├── ReadMe.txt ├── Snippets.ssmssqlproj ├── ida.sqlpromptsnippet ├── idf.sqlpromptsnippet ├── idl.sqlpromptsnippet ├── idp.sqlpromptsnippet ├── ids.sqlpromptsnippet ├── idt.sqlpromptsnippet ├── idtr.sqlpromptsnippet ├── idu.sqlpromptsnippet ├── idv.sqlpromptsnippet ├── snippets.sql ├── tab.sqlpromptsnippet ├── tac.sqlpromptsnippet ├── tal.sqlpromptsnippet ├── tat.sqlpromptsnippet ├── tca.sqlpromptsnippet ├── tce.sqlpromptsnippet ├── tco.sqlpromptsnippet ├── tct.sqlpromptsnippet ├── te.sqlpromptsnippet ├── tes.sqlpromptsnippet ├── tet.sqlpromptsnippet ├── tf.sqlpromptsnippet ├── tff.sqlpromptsnippet ├── tft.sqlpromptsnippet ├── tie.sqlpromptsnippet ├── tmt.sqlpromptsnippet ├── tnc.sqlpromptsnippet ├── tne.sqlpromptsnippet ├── tnt.sqlpromptsnippet ├── toe.sqlpromptsnippet ├── tpc.sqlpromptsnippet ├── trf.sqlpromptsnippet ├── tro.sqlpromptsnippet ├── tso.sqlpromptsnippet ├── tsp.sqlpromptsnippet ├── txe.sqlpromptsnippet ├── txn.sqlpromptsnippet └── txp.sqlpromptsnippet ├── Source ├── ApplyConstraint_Methods.sql ├── BuildOrder.txt ├── ExecutePrepareServer.sql ├── InWork.sql ├── PrepareServerBuildOrder.txt ├── ResetValidationServerBuildOrder1.txt ├── ResetValidationServerBuildOrder2.txt ├── Run_Methods.sql ├── SetClrEnabled.sql ├── Source.sqlproj ├── tSQLt.(at)tSQLt_MaxSqlMajorVersion.sfn.sql ├── tSQLt.(at)tSQLt_MinSqlMajorVersion.sfn.sql ├── tSQLt.(at)tSQLt_NoTransaction.sfn.sql ├── tSQLt.(at)tSQLt_RunOnlyOnHostPlatform.sfn.sql ├── tSQLt.(at)tSQLt_SkipTest.sfn.sql ├── tSQLt.ApplyTrigger.ssp.sql ├── tSQLt.AssertEmptyTable.ssp.sql ├── tSQLt.AssertEqualsString.ssp.sql ├── tSQLt.AssertEqualsTable.ssp.sql ├── tSQLt.AssertEqualsTableSchema.ssp.sql ├── tSQLt.AssertLike.ssp.sql ├── tSQLt.AssertNotEquals.ssp.sql ├── tSQLt.AssertObjectDoesNotExist.ssp.sql ├── tSQLt.AssertObjectExists.ssp.sql ├── tSQLt.AssertStringIn.ssp.sql ├── tSQLt.AssertStringTable.udt.sql ├── tSQLt.CaptureOutputLog.tbl.sql ├── tSQLt.DropClass.ssp.sql ├── tSQLt.EnableExternalAccess.ssp.sql ├── tSQLt.ExpectException.ssp.sql ├── tSQLt.ExpectNoException.ssp.sql ├── tSQLt.Fail.ssp.sql ├── tSQLt.FakeFunction.ssp.sql ├── tSQLt.FakeTable.ssp.sql ├── tSQLt.FriendlySQLServerVersion.sfn.sql ├── tSQLt.Info.sfn.sql ├── tSQLt.InstallAssemblyKey.ssp.sql ├── tSQLt.InstallExternalAccessKey.ssp.sql ├── tSQLt.LogCapturedOutput.ssp.sql ├── tSQLt.NewTestClass.ssp.sql ├── tSQLt.PrepareServer.ssp.sql ├── tSQLt.Private_AssertNoSideEffects.ssp.sql ├── tSQLt.Private_AssertNoSideEffects_GenerateCommand.sfn.sql ├── tSQLt.Private_CleanTestResult.ssp.sql ├── tSQLt.Private_CleanUp.ssp.sql ├── tSQLt.Private_CleanUpCmdHandler.ssp.sql ├── tSQLt.Private_CompareTables.ssp.sql ├── tSQLt.Private_CompareTablesFailIfUnequalRowsExists.ssp.sql ├── tSQLt.Private_Configurations.tbl.sql ├── tSQLt.Private_CreateFakeFunction.ssp.sql ├── tSQLt.Private_CreateFakeFunctionStatement.sfn.sql ├── tSQLt.Private_CreateFakeOfTable.ssp.sql ├── tSQLt.Private_CreateFakeTableStatement.sfn.sql ├── tSQLt.Private_CreateProcedureSpy.ssp.sql ├── tSQLt.Private_CreateResultTableForCompareTables.ssp.sql ├── tSQLt.Private_DisallowOverwritingNonTestSchema.ssp.sql ├── tSQLt.Private_EnableCLR.ssp.sql ├── tSQLt.Private_GenerateCreateProcedureSpyStatement.ssp.sql ├── tSQLt.Private_GetAssemblyKeyBytes.mdl.sql ├── tSQLt.Private_GetCommaSeparatedColumnList.sfn.sql ├── tSQLt.Private_GetConfiguration.sfn.sql ├── tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql ├── tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql ├── tSQLt.Private_GetDropItemCmd.sfn.sql ├── tSQLt.Private_GetForeignKeyDefinition.sfn.sql ├── tSQLt.Private_GetFormattedErrorInfo.sfn.sql ├── tSQLt.Private_GetFullTypeName.sfn.sql ├── tSQLt.Private_GetIdentityDefinition.sfn.sql ├── tSQLt.Private_GetSQLProductMajorVersion.ssp.sql ├── tSQLt.Private_GetUniqueConstraintDefinition.sfn.sql ├── tSQLt.Private_HandleMessageAndResult.sfn.sql ├── tSQLt.Private_HostPlatform.stub.sql ├── tSQLt.Private_HostPlatform.svw.sql ├── tSQLt.Private_Init.ssp.sql ├── tSQLt.Private_InstallationInfo.sfn.sql ├── tSQLt.Private_InstallationInfo.stub.sql ├── tSQLt.Private_ListTestAnnotations.sfn.sql ├── tSQLt.Private_Lock.tbl.sql ├── tSQLt.Private_MarkObjectBeforeRename.ssp.sql ├── tSQLt.Private_MarkSchemaAsTestClass.ssp.sql ├── tSQLt.Private_MarktSQLtTempObject.ssp.sql ├── tSQLt.Private_NewTestClassList.tbl.sql ├── tSQLt.Private_NoTransactionHandleTable.ssp.sql ├── tSQLt.Private_NoTransactionHandleTables.ssp.sql ├── tSQLt.Private_NoTransactionTableAction.view.sql ├── tSQLt.Private_PrepareFakeFunctionOutputTable.ssp.sql ├── tSQLt.Private_ProcessTestAnnotations.ssp.sql ├── tSQLt.Private_QuoteClassNameForNewTestClass.sfn.sql ├── tSQLt.Private_RemoveSchemaBinding.ssp.sql ├── tSQLt.Private_RemoveSchemaBoundReferences.ssp.sql ├── tSQLt.Private_RenameObject.ssp.sql ├── tSQLt.Private_RenameObjectToUniqueName.ssp.sql ├── tSQLt.Private_RenameObjectToUniqueNameUsingObjectId.ssp.sql ├── tSQLt.Private_RenamedObjectLog.tbl.sql ├── tSQLt.Private_ResetNewTestClassList.ssp.sql ├── tSQLt.Private_Results.view.sql ├── tSQLt.Private_ScriptIndex.sfn.sql ├── tSQLt.Private_Seize.tbl.sql ├── tSQLt.Private_SetConfiguration.ssp.sql ├── tSQLt.Private_SkipTestAnnotationHelper.ssp.sql ├── tSQLt.Private_SplitSqlVersion.sfn.sql ├── tSQLt.Private_SqlVariantFormatter.sfn.sql ├── tSQLt.Private_SqlVersion.sfn.sql ├── tSQLt.Private_SysIndexes.svw.sql ├── tSQLt.Private_SysTypes.svw.sql ├── tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql ├── tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql ├── tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql ├── tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql ├── tSQLt.Private_TableToTextColumntoStringList.sfn.sql ├── tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql ├── tSQLt.Private_UndoSingleTestDouble.ssp.sql ├── tSQLt.Private_ValidateFakeTableParameters.ssp.sql ├── tSQLt.Private_ValidateObjectsCompatibleWithFakeFunction.ssp.sql ├── tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure.ssp.sql ├── tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported.ssp.sql ├── tSQLt.RemoveAssemblyKey.ssp.sql ├── tSQLt.RemoveExternalAccessKey.ssp.sql ├── tSQLt.RemoveObject.ssp.sql ├── tSQLt.RemoveObjectIfExists.ssp.sql ├── tSQLt.RenameClass.ssp.sql ├── tSQLt.Reset.ssp.sql ├── tSQLt.SetSummaryError.ssp.sql ├── tSQLt.SetVerbose.ssp.sql ├── tSQLt.SpyProcedure.ssp.sql ├── tSQLt.StubRecord.ssp.sql ├── tSQLt.TableToText.ssp.sql ├── tSQLt.TempDropStatement.mdl.sql ├── tSQLt.TestClass.user.sql ├── tSQLt.TestClasses.view.sql ├── tSQLt.Tests.view.sql ├── tSQLt.UndoTestDoubles.ssp.sql ├── tSQLt.Uninstall.ssp.sql ├── tSQLt._Footer.sql ├── tSQLt._Header.sql ├── tSQLt.class.sql ├── tSQLt.schema.sql ├── tSQLtCLR.mdl.sql ├── tSQLtCLR_CreateProcs.sql ├── tSQLtDropBuildOrder.txt └── testoutput.sql ├── TestUtil ├── BuildOrder.txt ├── GetUnsignedEmptyBytes.mdl.sql ├── TestUtil.sqlproj ├── tSQLtTestUtilCLR.mdl.sql ├── tSQLtTestUtilCLR_CreateItems.sql └── tSQLt_testutil.class.sql ├── TestUtilTests ├── TestUtilTests.sqlproj ├── tSQLt_testutil_test.class.sql └── tSQLt_testutil_test_SA.class.sql ├── Tests.EXTERNAL_ACCESS ├── Run_Methods_Tests_EA.class.sql ├── Tests.EXTERNAL_ACCESS.sqlproj └── tSQLtclr_test.class.sql ├── Tests.EXTERNAL_ACCESS_KEY_EXISTS ├── EnableExternalAccessTests.class.sql ├── Private_InitTests_EAKE.class.sql └── Tests.EXTERNAL_ACCESS_KEY_EXISTS.sqlproj ├── Tests.SA ├── InstallAssemblyKeyTests.class.sql ├── InstallExternalAccessKeyTests.class.sql ├── PrepareServerTests.class.sql ├── Private_EnableCLRTests.class.sql ├── RemoveAssemblyKeyTests.class.sql ├── RemoveExternalAccessKeyTests.class.sql ├── Tests.SA.sqlproj └── _ExploratoryTests_SA.class.sql ├── Tests ├── AnnotationHostPlatformTests.class.sql ├── AnnotationNoTransactionTests.class.sql ├── AnnotationSkipTestTests.class.sql ├── AnnotationSqlServerVersionTests.class.sql ├── AnnotationsTests.class.sql ├── ApplyConstraintTests.class.sql ├── ApplyTriggerTests.class.sql ├── AssertEmptyTableTests.class.sql ├── AssertEqualsStringTests.class.sql ├── AssertEqualsTableSchemaTests.class.sql ├── AssertEqualsTableTests.class.sql ├── AssertEqualsTests.class.sql ├── AssertLikeTests.class.sql ├── AssertNotEqualsTests.class.sql ├── AssertObjectDoesNotExistTests.class.sql ├── AssertObjectExistsTests.class.sql ├── AssertResultSetsHaveSameMetaDataTests.class.sql ├── AssertStringInTests.class.sql ├── BootStrapTest.sql ├── DropClassTests.class.sql ├── ExpectExceptionTests.class.sql ├── ExpectNoExceptionTests.class.sql ├── FailTests.class.sql ├── FakeFunctionTests.class.sql ├── FakeTableTests.class.sql ├── FriendlySQLServerVersionTests.class.sql ├── InfoTests.class.sql ├── NameAndIdResolution_test.class.sql ├── NewTestClassTests.class.sql ├── Private_AssertNoSideEffectsTests.class.sql ├── Private_CleanUpCmdHandlerTests.class.sql ├── Private_CleanUpTests.class.sql ├── Private_CreateFakeFunctionStatementTests.class.sql ├── Private_GetAnnotationListTests.class.sql ├── Private_GetFormattedErrorInfoTests.class.sql ├── Private_GetFullTypeNameTests.class.sql ├── Private_GetSQLProductMajorVersionTests.class.sql ├── Private_HandleMessageAndResultTests.class.sql ├── Private_InitTests.class.sql ├── Private_InstallationInfoTests.class.sql ├── Private_MarktSQLtTempObjectTests.class.sql ├── Private_NoTransactionHandleTableTests.class.sql ├── Private_NoTransactionHandleTablesTests.class.sql ├── Private_NoTransactionTableActionTests.class.sql ├── Private_ProcessTestAnnotationsTests.class.sql ├── Private_RemoveSchemaBindingTests.class.sql ├── Private_RemoveSchemaBoundReferencesTests.class.sql ├── Private_RenameObjectToUniqueNameTests.class.sql ├── Private_ResetNewTestClassListTests.class.sql ├── Private_ResultsTests.class.sql ├── Private_ScriptIndexTests.class.sql ├── Private_SeizeTests.class.sql ├── Private_SplitSqlVersionTests.class.sql ├── Private_SqlVariantFormatterTests.class.sql ├── RemoveObjectIfExistsTests.class.sql ├── RemoveObjectTests.class.sql ├── RenameClassTests.class.sql ├── ResetTests.class.sql ├── ResultSetFilterTests.class.sql ├── Run_Methods_Tests.class.sql ├── SetSummaryErrorTests.class.sql ├── SpyProcedureTests.class.sql ├── StubRecordTests.class.sql ├── TableToTextTests.class.sql ├── TestClassesTest.class.sql ├── Tests.sqlproj ├── UndoTestDoublesTests.class.sql ├── UninstallTests.class.sql ├── _ExploratoryTests.class.sql ├── tSQLt.AssertNotEquals.ssp.sql ├── tSQLt_test.class.sql └── tSQLtclr_test.class.sql ├── UpgradeLog.XML ├── docs ├── CNAME └── index.md ├── tSQLt.code-workspace ├── tSQLt.ssmssln └── tSQLtCLR ├── Build.ps1 ├── OfficialSigningKey ├── CreateBase64KeyFile.ps1 ├── InstallSigningKey.bat └── tSQLtOfficialSigningKey.pfx ├── UnsignedEmpty ├── Properties │ └── XXXX.AssemblyInfo.cs.XXXX ├── UnsignedEmpty.csproj └── XXXX.UnsignedEmpty.csproj.XXXX ├── XXXX.tSQLtCLR.sln.XXXX ├── tSQLtAssemblyKey ├── Properties │ └── XXXX.AssemblyInfo.cs.XXXX ├── XXXX.tSQLtAssemblyKey.csproj.XXXX ├── empty.cs └── tSQLtAssemblyKey.csproj ├── tSQLtCLR.sln ├── tSQLtCLR ├── Annotations.cs ├── CommandExecutor.cs ├── CommandExecutorException.cs ├── InvalidResultSetException.cs ├── MetaDataEqualityAsserter.cs ├── OutputCaptor.cs ├── PostBuild.bat ├── ResultSetFilter.cs ├── StoredProcedures.cs ├── StringExtensions.cs ├── TestDatabaseFacade.cs ├── XXXXX.XXXX ├── XXXXX.user.XXXX ├── tSQLtCLR.csproj └── tSQLtPrivate.cs └── tSQLtTestUtilCLR ├── ClrFunctions.cs ├── ClrStoredProcedures.cs ├── DataTypeByteOrdered.cs ├── DataTypeNoEqual.cs ├── DataTypeWithEqual.cs ├── Properties └── XXX.AssemblyInfo.cs.XXXX ├── XXXX.app.config.XXXX ├── XXXX.tSQLtTestUtilCLR.csproj.XXXX └── tSQLtTestUtilCLR.csproj /.devcontainer/postCreateCommand.sh: -------------------------------------------------------------------------------- 1 | cd "$(dirname "$0")" 2 | 3 | docker --version 4 | docker-compose -f sqlserver.yml up -d --force-recreate 5 | 6 | cd "$TSQLTCERTPATH" 7 | openssl req -x509 -newkey rsa:4096 -keyout tSQLtOfficialSigningKey.key -out tSQLtOfficialSigningKey.crt -days 365 -nodes -subj "/CN=yourdomain.com" 8 | openssl pkcs12 -export -out tSQLtOfficialSigningKey.pfx -inkey tSQLtOfficialSigningKey.key -in tSQLtOfficialSigningKey.crt -passout pass:"$TSQLTCERTPASSWORD" 9 | 10 | 11 | # pwsh -File ../tSQLt/PrepareServer.ps1 -------------------------------------------------------------------------------- /.devcontainer/postStartCommand.sh: -------------------------------------------------------------------------------- 1 | cd "$(dirname "$0")" 2 | 3 | docker --version 4 | docker-compose -f sqlserver.yml up -d -------------------------------------------------------------------------------- /.devcontainer/sqlserver.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | sql_server: 4 | image: mcr.microsoft.com/mssql/server:2022-latest 5 | ports: 6 | - "1433:1433" 7 | environment: 8 | ACCEPT_EULA: 'Y' 9 | MSSQL_SA_PASSWORD: 'P@ssw0rd' 10 | -------------------------------------------------------------------------------- /.devcontainer/tSQLtOfficialSigningKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/.devcontainer/tSQLtOfficialSigningKey.pfx -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | # @global-owner1 and @global-owner2 will be requested for 4 | # review when someone opens a pull request. 5 | * @tsqlt-org/maintainers 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Build/output 2 | /Build/temp 3 | /tSQLtCLR/tSQLtCLR/bin 4 | /tSQLtCLR/tSQLtCLR/obj 5 | /tSQLtCLR/tSQLtTestUtilCLR/bin 6 | /tSQLtCLR/tSQLtTestUtilCLR/obj 7 | *.ssms_suo 8 | /tSQLtCLR/tSQLtCLR.suo 9 | /tSQLtCLR/UnsignedEmpty/obj 10 | /tSQLtCLR/UnsignedEmpty/bin 11 | /tSQLtCLR/tSQLtAssemblyKey/bin 12 | /tSQLtCLR/tSQLtAssemblyKey/obj 13 | /tSQLtCLR/tSQLtCLR.v12.suo 14 | *.dtbcache 15 | *.suo 16 | /tSQLtCLR/builderr.txt 17 | /tSQLtCLR/buildlog.txt 18 | /tSQLtCLR/.vs/tSQLtCLR/v15/Server/sqlite3/db.lock 19 | /tSQLtCLR/.vs/tSQLtCLR/v15/Server/sqlite3/storage.ide 20 | /tSQLtCLR/.vs/tSQLtCLR/v15/Server/sqlite3/storage.ide-shm 21 | /tSQLtCLR/.vs/tSQLtCLR/v15/Server/sqlite3/storage.ide-wal 22 | /tSQLtCLR/.vs/tSQLtCLR/v16/Server/sqlite3 23 | /Build_Artifact 24 | /tSQLtCLR/OfficialSigningKey/tSQLtOfficialSigningKey.b64.txt 25 | .DS_Store 26 | /Build_Output 27 | /tSQLtCLR/OfficialSigningKey/KeyInfo.txt 28 | /tSQLtCLR/OfficialSigningKey/KeyInfoC.txt 29 | 30 | .vscode/settings.json 31 | -------------------------------------------------------------------------------- /Build/ChangeSigningKey_ReadMe.txt: -------------------------------------------------------------------------------- 1 | To get the new SigningKey accepted by the BuildAgent, follow these steps: 2 | 3 | 4 | 1) Run the failing build configuration and note the required key container 5 | a) run the configuration 6 | b) open the log and find the error: 7 | error MSB3325: Cannot import the following key file: SigningKey.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_FFAB74CD53FE74BA 8 | c) the key container name is at the end of the message 9 | 2) make sure the agent account is not in the "Deny log on locally" group policy 10 | a) Startmenu 11 | b) type gpedit.msc 12 | c) Computer Configuration/Windows Settings/Security Settings/Local Policies/User Rights Assignment 13 | d) check "Allow log on locally" and "Deny log on locally" 14 | (Adding an account to "Deny log on locally" prevents it from showing up on the winfows logo screen. Handy for service accounts.) 15 | 3) Run the Visual Studio Cmd Prompt from the service account 16 | a) https://msdn.microsoft.com/en-us/library/ms229859(v=vs.110).aspx 17 | 4) load the key with the sn tool 18 | a) CD to the path that contains the SigningKey.pfx (tSQLt/tSQLtCLR/tSQLtCLR) 19 | b) run this: sn -i SigningKey.pfx VS_KEY_FFAB74CD53FE74BA 20 | (using the key container name from the error message above) 21 | c) provide the key password when prompted 22 | 5) Add the account back to the "Deny log on locally" group policy -------------------------------------------------------------------------------- /Build/Readme.md: -------------------------------------------------------------------------------- 1 | # Building tSQLt 2 | 3 | To build tSQLt on your local machine, clode the repository in a local folder: 4 | 5 | `git clone https://` 6 | 7 | Open that folder in Visual Studio Code, aka VSC (Open Source, download from [https://code.visualstudio.com/download](https://code.visualstudio.com/download).) 8 | 9 | You also need Docker Dektop (Free for non-commercial use, Download from [https://www.docker.com/products/docker-desktop/](https://www.docker.com/products/docker-desktop/).) This might work with other container platforms, too. 10 | 11 | Once ready, type `>Dev Containers: Open Folder in Container...` into the top bar in VSC and hit Enter. 12 | 13 | This starts up your development container, that includes all the software needed to build tSQLt. -------------------------------------------------------------------------------- /Build/SQL/Add(tSQLt.Built)ToExampleDB.sql: -------------------------------------------------------------------------------- 1 | GO 2 | CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build]; 3 | GO 4 | ALTER ROLE db_owner ADD MEMBER [tSQLt.Build]; 5 | GO -------------------------------------------------------------------------------- /Build/SQL/ChangeDbAndExecuteStatement(tSQLt.Build).sql: -------------------------------------------------------------------------------- 1 | 2 | GO 3 | :OUT NUL: 4 | GO 5 | USE [$(DbName)]; 6 | GO 7 | :OUT STDOUT 8 | GO 9 | $(ExecuteStatement) 10 | GO 11 | -------------------------------------------------------------------------------- /Build/SQL/CreateBuildDbBuildOrder.txt: -------------------------------------------------------------------------------- 1 | ForceDropTempProcedures.sql 2 | CreateBuildDbStub.sql -------------------------------------------------------------------------------- /Build/SQL/CreateBuildDbStub.sql: -------------------------------------------------------------------------------- 1 | GO 2 | EXEC #ForceDropLogin [$(NewDbName)]; 3 | EXEC #ForceDropDatabase [$(NewDbName)]; 4 | GO 5 | CREATE DATABASE [$(NewDbName)] COLLATE SQL_Latin1_General_CP1_CS_AS WITH TRUSTWORTHY OFF; 6 | -- COLLATE SQL_Latin1_General_CP1_CS_AS 7 | GO 8 | CREATE LOGIN [$(NewDbName)] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B4 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; 9 | GO 10 | ALTER AUTHORIZATION ON DATABASE::[$(NewDbName)] TO [$(NewDbName)]; 11 | GO 12 | EXEC [$(NewDbName)].sys.sp_executesql N'CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build]; ALTER ROLE db_owner ADD MEMBER [tSQLt.Build];',N''; -------------------------------------------------------------------------------- /Build/SQL/CreateLogin(tSQLt.Build).sql: -------------------------------------------------------------------------------- 1 | GO 2 | SET NOCOUNT ON; 3 | GO 4 | USE master; 5 | GO 6 | EXEC #ForceDropLogin 'tSQLt.Build'; 7 | GO 8 | EXEC #ForceDropLogin 'tSQLt.Build.SA'; 9 | GO 10 | CREATE LOGIN [tSQLt.Build] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B0 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; 11 | GO 12 | CREATE LOGIN [tSQLt.Build.SA] WITH PASSWORD = 0x010095EBA5D9A28749DF6ABFD4F5AAFBCE8BD839E0E35D6273B2 HASHED, CHECK_POLICY = OFF, DEFAULT_DATABASE = tempdb; 13 | GO 14 | EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build.SA', @rolename = N'sysadmin' 15 | EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt.Build', @rolename = N'dbcreator' 16 | GO 17 | EXEC master.sys.sp_executesql N'IF USER_ID(''tSQLt.Build'') IS NOT NULL DROP USER [tSQLt.Build];'; 18 | EXEC master.sys.sp_executesql N'CREATE USER [tSQLt.Build] FROM LOGIN [tSQLt.Build];'; 19 | GO 20 | -------------------------------------------------------------------------------- /Build/SQL/DisableExternalAccess.sql: -------------------------------------------------------------------------------- 1 | IF(EXISTS(SELECT 1 FROM tSQLt.Info() WHERE HostPlatform NOT IN ('Linux'))) 2 | BEGIN 3 | EXEC tSQLt.EnableExternalAccess @try = 0, @enable=0; 4 | END; 5 | -------------------------------------------------------------------------------- /Build/SQL/Drop(master.tSQLt_testutil).sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('master.tSQLt_testutil.tSQLtTestUtil_DropExternalAccessKey') IS NOT NULL EXEC master.sys.sp_executesql N'DROP PROCEDURE tSQLt_testutil.tSQLtTestUtil_DropExternalAccessKey;'; 2 | IF OBJECT_ID('master.tSQLt_testutil.tSQLtTestUtil_UnsafeAssemblyAndExternalAccessRevoke') IS NOT NULL EXEC master.sys.sp_executesql N'DROP PROCEDURE tSQLt_testutil.tSQLtTestUtil_UnsafeAssemblyAndExternalAccessRevoke;'; 3 | EXEC master.sys.sp_executesql N'IF SCHEMA_ID(''tSQLt_testutil'') IS NOT NULL DROP SCHEMA tSQLt_testutil;'; 4 | EXEC master.sys.sp_executesql N'IF SUSER_ID(''tSQLt_testutil'') IS NOT NULL DROP LOGIN tSQLt_testutil;'; 5 | EXEC master.sys.sp_executesql N'IF CERT_ID(''tSQLt_testutil'') IS NOT NULL DROP CERTIFICATE tSQLt_testutil;'; 6 | -------------------------------------------------------------------------------- /Build/SQL/Drop(tSQLtAssemblyKey)(Pre2017).sql: -------------------------------------------------------------------------------- 1 | DECLARE @cmd NVARCHAR(MAX); 2 | 3 | IF(CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(MAX)),4) AS INT)<14) 4 | BEGIN 5 | PRINT '-------Dropping tSQLtAssemblyKey---------------'; 6 | SET @cmd = N'IF SUSER_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP LOGIN tSQLtAssemblyKey;'; 7 | EXEC master.sys.sp_executesql @cmd; 8 | SET @cmd = N'IF ASYMKEY_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP ASYMMETRIC KEY tSQLtAssemblyKey;'; 9 | EXEC master.sys.sp_executesql @cmd; 10 | END; 11 | ELSE 12 | BEGIN 13 | PRINT '-------Dropping of tSQLtAssemblyKey skipped---------------'; 14 | END; 15 | -------------------------------------------------------------------------------- /Build/SQL/EnableExternalAccess.sql: -------------------------------------------------------------------------------- 1 | IF(EXISTS(SELECT 1 FROM tSQLt.Info() WHERE HostPlatform NOT IN ('Linux'))) 2 | BEGIN 3 | EXEC tSQLt.EnableExternalAccess @try = 0, @enable=1; 4 | END; 5 | -------------------------------------------------------------------------------- /Build/SQL/ExecuteAs(tSQLt.Build).sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | EXECUTE AS LOGIN = 'tSQLt.Build'; 17 | GO 18 | -------------------------------------------------------------------------------- /Build/SQL/ExecuteAs(tSQLt.Build.SA).sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | EXECUTE AS LOGIN = 'tSQLt.Build.SA'; 17 | GO 18 | -------------------------------------------------------------------------------- /Build/SQL/ExecuteAsCleanup.sql: -------------------------------------------------------------------------------- 1 | GO 2 | DECLARE @Counter INT = 0; 3 | DECLARE @MaxAttempts INT = 10; 4 | DECLARE @PreviousUser NVARCHAR(128) = SYSTEM_USER; 5 | 6 | WHILE ORIGINAL_LOGIN() <> SYSTEM_USER AND @Counter < @MaxAttempts 7 | BEGIN 8 | SET @Counter=@Counter+1; 9 | REVERT; 10 | SELECT @Counter=0,@PreviousUser=SYSTEM_USER WHERE @PreviousUser<>SYSTEM_USER; 11 | PRINT SYSTEM_USER 12 | END 13 | 14 | IF @Counter >= @MaxAttempts 15 | BEGIN 16 | RAISERROR('WARNING: Impersonation could not be reverted after %d attempts.', 0, 1, @MaxAttempts) WITH NOWAIT; 17 | END 18 | GO -------------------------------------------------------------------------------- /Build/SQL/ExecuteResetValidationServer.sql: -------------------------------------------------------------------------------- 1 | GO 2 | EXEC #RemoveAssemblyKey; 3 | GO 4 | EXEC master.sys.sp_configure @configname='show advanced options', @configvalue = 1; 5 | GO 6 | RECONFIGURE; 7 | GO 8 | IF(CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(MAX)),4) AS INT)>=14) EXEC master.sys.sp_configure @configname='clr strict security', @configvalue = 1; 9 | EXEC master.sys.sp_configure @configname='clr enabled', @configvalue = 0; 10 | GO 11 | RECONFIGURE; 12 | GO 13 | -------------------------------------------------------------------------------- /Build/SQL/GetFailedTestCount.sql: -------------------------------------------------------------------------------- 1 | :EXIT(SELECT COUNT(*) FROM tSQLt.TestResult WHERE Result != 'Success') 2 | 3 | -------------------------------------------------------------------------------- /Build/SQL/GetFriendlySQLServerVersion.template.sql: -------------------------------------------------------------------------------- 1 | DECLARE @ProductVersion NVARCHAR(128) = CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128)); 2 | DECLARE @FriendlyVersion NVARCHAR(128) = (SELECT FriendlyVersion 3 | FROM 4 | ( 5 | /*snip1content*/ 6 | FROM 7 | ( 8 | /*snip2content*/ 9 | )SSV 10 | )X 11 | ); 12 | SELECT @FriendlyVersion FriendlyVersion; -------------------------------------------------------------------------------- /Build/SQL/GetSQLServerVersion.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | CASE PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(MAX)),4) 3 | WHEN 10 THEN 4 | CASE PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(MAX)),3) 5 | WHEN 0 THEN '2008' ELSE '2008R2' 6 | END 7 | WHEN 11 THEN '2012' 8 | WHEN 12 THEN '2014' 9 | WHEN 13 THEN '2016' 10 | WHEN 14 THEN '2017' 11 | WHEN 15 THEN '2019' 12 | ELSE 'Unknown' 13 | END SQLVersion; -------------------------------------------------------------------------------- /Build/SQL/GrantBuildPermissions.sql: -------------------------------------------------------------------------------- 1 | USE master; 2 | GO 3 | EXECUTE AS LOGIN='SA'; 4 | GO 5 | CREATE LOGIN FROM WINDOWS WITH DEFAULT_DATABASE=[tempdb], DEFAULT_LANGUAGE=[us_english] 6 | GO 7 | GRANT IMPERSONATE ON LOGIN::[tSQLt.Build] TO ; 8 | GRANT IMPERSONATE ON LOGIN::[tSQLt.Build.SA] TO ; 9 | GO 10 | -------------------------------------------------------------------------------- /Build/SQL/Install(master.tSQLt_testutil).sql: -------------------------------------------------------------------------------- 1 | EXEC master.sys.sp_executesql N'IF SCHEMA_ID(''tSQLt_testutil'') IS NULL EXEC(''CREATE SCHEMA tSQLt_testutil;'');'; 2 | EXEC master.sys.sp_executesql N'CREATE PROCEDURE tSQLt_testutil.tSQLtTestUtil_UnsafeAssemblyAndExternalAccessRevoke AS REVOKE EXTERNAL ACCESS ASSEMBLY,UNSAFE ASSEMBLY TO [tSQLtAssemblyKey];'; 3 | EXEC master.sys.sp_executesql N'CREATE CERTIFICATE tSQLt_testutil ENCRYPTION BY PASSWORD = ''CE4E37C2-A9B6-409D-94C3-F051FB09D957DA704F07-2F5D-4C4A-8497-A9A10C6E51F4'' WITH SUBJECT=''tSQLt_testutil'';'; 4 | CREATE LOGIN tSQLt_testutil FROM CERTIFICATE tSQLt_testutil; 5 | EXEC sys.sp_addsrvrolemember @loginame = N'tSQLt_testutil', @rolename = N'sysadmin'; 6 | EXEC master.sys.sp_executesql N'ADD SIGNATURE TO tSQLt_testutil.tSQLtTestUtil_UnsafeAssemblyAndExternalAccessRevoke BY CERTIFICATE tSQLt_testutil WITH PASSWORD = ''CE4E37C2-A9B6-409D-94C3-F051FB09D957DA704F07-2F5D-4C4A-8497-A9A10C6E51F4'';'; 7 | EXEC master.sys.sp_executesql N'GRANT EXECUTE ON OBJECT::tSQLt_testutil.tSQLtTestUtil_UnsafeAssemblyAndExternalAccessRevoke TO [tSQLt.Build];'; 8 | EXEC master.sys.sp_executesql N'ALTER CERTIFICATE tSQLt_testutil REMOVE PRIVATE KEY;'; 9 | -------------------------------------------------------------------------------- /Build/SQL/Install(tSQLtAssemblyKey).sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.InstallAssemblyKey; 2 | -------------------------------------------------------------------------------- /Build/SQL/PrintVersionInfo.sql: -------------------------------------------------------------------------------- 1 | DECLARE @txt NVARCHAR(MAX); 2 | IF(OBJECT_ID('tempdb..#VersionInfoTable')IS NOT NULL)DROP TABLE #VersionInfoTable; 3 | SELECT Version, ClrVersion, ClrSigningKey INTO #VersionInfoTable FROM tSQLt.Info(); 4 | EXEC tSQLt.TableToText @txt = @txt OUTPUT, @TableName = N'#VersionInfoTable'; 5 | 6 | RAISERROR('+-----------------------------------------------------------------------------------------------------+',0,1)WITH NOWAIT; 7 | RAISERROR('| tSQLt Info: |',0,1)WITH NOWAIT; 8 | RAISERROR('+-----------------------------------------------------------------------------------------------------+',0,1)WITH NOWAIT; 9 | RAISERROR('',0,1)WITH NOWAIT; 10 | RAISERROR(@txt,0,1)WITH NOWAIT; 11 | RAISERROR('',0,1)WITH NOWAIT; 12 | RAISERROR('+-----------------------------------------------------------------------------------------------------+',0,1)WITH NOWAIT; 13 | RAISERROR('| SQL Server Info: |',0,1)WITH NOWAIT; 14 | RAISERROR('+-----------------------------------------------------------------------------------------------------+',0,1)WITH NOWAIT; 15 | RAISERROR('',0,1)WITH NOWAIT; 16 | RAISERROR('%s',0,1,@@VERSION)WITH NOWAIT; 17 | RAISERROR('-------------------------------------------------------------------------------------------------------',0,1)WITH NOWAIT; 18 | -------------------------------------------------------------------------------- /Build/SQL/SeparatorTemplate.sql: -------------------------------------------------------------------------------- 1 | 2 | GO 3 | --> /*--FILENAME--*/ 4 | GO 5 | -------------------------------------------------------------------------------- /Build/SQL/UseTempDb.sql: -------------------------------------------------------------------------------- 1 | GO 2 | USE tempdb; 3 | GO 4 | -------------------------------------------------------------------------------- /Build/reviewneeded/Import-PfxCert.ps1: -------------------------------------------------------------------------------- 1 | param($PfxFilePath, $Password) 2 | 3 | $absolutePfxFilePath = Resolve-Path -Path $PfxFilePath 4 | Write-Output "Importing store certificate '$absolutePfxFilePath'..." 5 | 6 | Add-Type -AssemblyName System.Security 7 | $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 8 | $cert.Import($absolutePfxFilePath, $Password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet) 9 | $store = new-object system.security.cryptography.X509Certificates.X509Store -argumentlist "MY", CurrentUser 10 | $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::"ReadWrite") 11 | $store.Add($cert) 12 | $store.Close() 13 | 14 | #Source: http://blog.danskingdom.com/creating-a-pfx-certificate-and-applying-it-on-the-build-server-at-build-time/ 15 | -------------------------------------------------------------------------------- /Build/reviewneeded/Install the tSQLt build.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Build/reviewneeded/Install the tSQLt build.docx -------------------------------------------------------------------------------- /Build/reviewneeded/NewRelease.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Build/reviewneeded/NewRelease.doc -------------------------------------------------------------------------------- /Build/reviewneeded/Setup.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | IF "%~1"=="" GOTO :Usage 3 | 4 | CD /d %~p0 5 | REM sqlcmd -S %1 -E -I -d master -i "ExecuteAsSA.sql" "tSQLtKey.sql" "Create(tSQLtKey).sql" "CreateLogin(tSQLt.Build).sql" -V11 6 | sqlcmd -S %1 -E -I -d master -i "CreateLogin(tSQLt.Build).sql" -V11 7 | GOTO :EOF 8 | 9 | :Usage 10 | ECHO Usage %~nx0 ServerAndInstanceName 11 | -------------------------------------------------------------------------------- /Build/tSQLt_Build/GetAssemblyInfo.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] 3 | [string]$dllPath, 4 | [Parameter(Mandatory=$true, ParameterSetName="Version")] 5 | [switch]$v, 6 | [Parameter(Mandatory=$true, ParameterSetName="Key")] 7 | [switch]$k, 8 | [Parameter(Mandatory=$true, ParameterSetName="Token")] 9 | [switch]$t 10 | ) 11 | 12 | function Get-AssemblyInfo { 13 | param( 14 | [string]$dllPath, 15 | [switch]$v, 16 | [switch]$k, 17 | [switch]$t 18 | ) 19 | 20 | try { 21 | $assemblyName = [System.Reflection.AssemblyName]::GetAssemblyName($dllPath) 22 | 23 | if($v) { 24 | return $assemblyName.Version.ToString() 25 | } 26 | elseif($k){ 27 | $publicKey = $assemblyName.GetPublicKey() 28 | if ($null -eq $publicKey -or $publicKey.Length -eq 0) { 29 | return "" 30 | } else { 31 | return [BitConverter]::ToString($publicKey) -replace '-' 32 | } 33 | } 34 | elseif($t){ 35 | $publicKeyToken = $assemblyName.GetPublicKeyToken() 36 | if ($null -eq $publicKeyToken -or $publicKeyToken.Length -eq 0) { 37 | return "" 38 | } else { 39 | return [BitConverter]::ToString($publicKeyToken) -replace '-' 40 | } 41 | } 42 | } catch { 43 | Write-Error "Error processing assembly: $_" 44 | exit 1 45 | } 46 | } 47 | 48 | (Get-AssemblyInfo -dllPath $dllPath -v:$v -k:$k -t:$t) 49 | 50 | -------------------------------------------------------------------------------- /Build/tSQLt_Build/PackagetSQLtSnippets.ps1: -------------------------------------------------------------------------------- 1 | using module "../CommonFunctionsAndMethods.psm1"; 2 | 3 | $__=$__ 4 | $invocationDir = $PSScriptRoot 5 | Push-Location -Path $invocationDir 6 | try{ 7 | $snippetsPath = Join-Path $invocationDir '../../Snippets' | Resolve-Path; 8 | $outputPath = Join-Path $invocationDir '../output/tSQLtBuild' |Resolve-Path; 9 | $tempPath = Join-Path $invocationDir '../temp/tSQLtBuild/SQLPromptSnippets'; 10 | Remove-DirectoryQuietly -Path $tempPath; 11 | $__ = New-Item -ItemType "directory" -Path $tempPath; 12 | 13 | 14 | $fileList = Get-ChildItem -path (Join-Path $snippetsPath '*') -include "*.sqlpromptsnippet","ReadMe.txt" 15 | $fileList | Copy-Item -Destination $tempPath 16 | 17 | $compress = @{ 18 | CompressionLevel = "Optimal" 19 | DestinationPath = (Join-Path $outputPath "tSQLtSnippets(SQLPrompt).zip") 20 | } 21 | Get-ChildItem -Path (Join-Path $tempPath "*") | Compress-Archive @compress 22 | } 23 | finally{ 24 | Pop-Location 25 | } -------------------------------------------------------------------------------- /Build/tSQLt_BuildCLR.ps1: -------------------------------------------------------------------------------- 1 | using module "./CommonFunctionsAndMethods.psm1"; 2 | param( 3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $pfxFilePath , 4 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][securestring] $pfxPassword 5 | ) 6 | Push-Location -Path $PSScriptRoot 7 | Write-Verbose((Get-Location).Path) 8 | try{ 9 | $OutputPath = "./output/tSQLtCLR/"; 10 | $TempPath = "./temp/tSQLtCLR/"; 11 | 12 | <# Clean #> 13 | Remove-DirectoryQuietly -Path $TempPath; 14 | Remove-DirectoryQuietly -Path $OutputPath; 15 | Get-ChildItem -Path ("../tSQLtCLR/") -Recurse -Include bin, obj|Foreach-Object{Remove-DirectoryQuietly -Path $_} 16 | 17 | <# Init directories, capturing the return values in a variable so that they don't print. #> 18 | $__=$__; 19 | $__ = New-Item -ItemType "directory" -Path $TempPath; 20 | $__ = New-Item -ItemType "directory" -Path $OutputPath; 21 | 22 | ../tSQLtCLR/Build.ps1 -pfxFilePath $pfxFilePath -pfxPassword $pfxPassword 23 | 24 | Get-ChildItem -Path ("../tSQLtCLR/*/bin") -Recurse -Include *.dll | Copy-Item -Destination $TempPath; 25 | 26 | $compress = @{ 27 | CompressionLevel = "Optimal" 28 | DestinationPath = $OutputPath + "/tSQLtCLR.zip" 29 | } 30 | Get-ChildItem -Path $TempPath | Compress-Archive @compress 31 | } 32 | finally{ 33 | Pop-Location 34 | } -------------------------------------------------------------------------------- /CI/AKS/docker/README.md: -------------------------------------------------------------------------------- 1 | # containerbuild 2 | 3 | 1. `docker build -f /Dockerfile .` 4 | 1. You can also change directories and run `docker build -f Dockerfile ..` 5 | 1. `docker container create -p HOSTPORT:1433 IMAGENAME` 6 | 1. `docker container start CONTAINERNAME` 7 | 1. `docker container exec 93d676bf0088 sqlcmd -E -S ".,1433" -Q "SELECT @@VERSION"` 8 | 1. `sqlcmd -U sa -P "W3lc0mE002" -S ".,41433" -Q "SELECT @@VERSION"` 9 | 10 | Changing the sa password. 11 | `$cmd = "Invoke-SqlCmd -Query `"`"ALTER LOGIN sa WITH PASSWORD='test123451'`"`""` 12 | `docker container exec CONTAINERNAMEorID powershell $cmd` 13 | `sqlcmd -Q "SELECT SUSER_NAME() U,SYSDATETIME() T,@@VERSION V;" -S ".,41417" -U "sa" -P "test123451"` -------------------------------------------------------------------------------- /CI/AKS/docker/changeSqlLogin.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$True)][string] $sa_password 3 | ) 4 | 5 | if($null -ne $sa_password -And $sa_password -ne "") { 6 | Write-Verbose "Changing SA login credentials" 7 | $sqlcmdChangePassword = "ALTER LOGIN sa with password='"+$sa_password+"' ,CHECK_POLICY=OFF,CHECK_EXPIRATION=OFF" 8 | echo "command: " $sqlcmdChangePassword 9 | & sqlcmd -Q $sqlcmdChangePassword 10 | $sqlcmdEnable = "ALTER LOGIN sa ENABLE" 11 | & sqlcmd -Q $sqlcmdEnable 12 | } -------------------------------------------------------------------------------- /CI/AKS/docker/start.ps1: -------------------------------------------------------------------------------- 1 | # The script starts the SQL Server Service 2 | 3 | param( 4 | [Parameter(Mandatory=$false)] 5 | [string]$ACCEPT_EULA, 6 | 7 | [Parameter(Mandatory=$false)] 8 | [string]$sqlsrvrlogin 9 | ) 10 | 11 | Write-Host "Beginning of start.ps1" 12 | 13 | if($ACCEPT_EULA -ne "Y" -And $ACCEPT_EULA -ne "y") 14 | { 15 | Write-Verbose "ERROR: You must accept the End User License Agreement before this container can start." 16 | Write-Verbose "Set the environment variable ACCEPT_EULA to 'Y' if you accept the agreement." 17 | 18 | exit 1 19 | } 20 | 21 | # start the service 22 | Write-Verbose "Starting SQL Server" 23 | start-service MSSQLSERVER 24 | Write-Verbose "Started SQL Server." 25 | 26 | # create the sql server login 27 | Write-Verbose "Create login for sqlsrvrlogin account." 28 | 29 | $createLogin="CREATE LOGIN [" + $env:USERDOMAIN + "\"+ $sqlsrvrlogin +"] FROM WINDOWS" 30 | Write-Verbose "Create login command: $createLogin" 31 | & sqlcmd -j -m-1 -Q $createLogin 32 | 33 | Write-Verbose "Providing sysadmin permissions to sqlsrvrlogin account." 34 | 35 | $enableSysAdminPermissions="sp_addsrvRolemember [" + $env:USERDOMAIN + "\"+ $sqlsrvrlogin +"], 'sysadmin'" 36 | Write-Verbose "Enable sys admin permissions command: $enableSysAdminPermissions" 37 | & sqlcmd -j -m-1 -Q $enableSysAdminPermissions 38 | 39 | $lastCheck = (Get-Date).AddSeconds(-2) 40 | while ($true) 41 | { 42 | Get-EventLog -LogName Application -Source "MSSQL*" -After $lastCheck | Select-Object TimeGenerated, EntryType, Message 43 | $lastCheck = Get-Date 44 | Start-Sleep -Seconds 2 45 | } 46 | Write-Error "Should not get here, ever." -------------------------------------------------------------------------------- /CI/AKS/docker/sxs/Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~en-US~.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/CI/AKS/docker/sxs/Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~en-US~.cab -------------------------------------------------------------------------------- /CI/AKS/docker/sxs/Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~en-US~.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/CI/AKS/docker/sxs/Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~en-US~.cab -------------------------------------------------------------------------------- /CI/AKS/docker/sxs/microsoft-windows-internetexplorer-optional-package~31bf3856ad364e35~amd64~~.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/CI/AKS/docker/sxs/microsoft-windows-internetexplorer-optional-package~31bf3856ad364e35~amd64~~.cab -------------------------------------------------------------------------------- /CI/AKS/docker/sxs/microsoft-windows-netfx3-ondemand-package~31bf3856ad364e35~amd64~~.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/CI/AKS/docker/sxs/microsoft-windows-netfx3-ondemand-package~31bf3856ad364e35~amd64~~.cab -------------------------------------------------------------------------------- /CI/AKS/envSetup/buildAndPushImage.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$mssqlVersion, 3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$acrURL, # eg. crn1234567890.azurecr.io 4 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$azSpCrBase64, 5 | $debugOnString="false" 6 | ); 7 | 8 | $debugOn = ($debugOnString -eq "true"); 9 | if ($debugOn) { 10 | $DebugPreference = "Continue"; 11 | } 12 | 13 | $decodedCreds = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("$azSpCrBase64")); 14 | $creds = (ConvertFrom-Json -InputObject $decodedCreds) ; 15 | 16 | Set-Location -Path ~\sourceRepo\docker; 17 | 18 | docker login $acrURL --username $creds.clientId --password $creds.clientSecret 19 | 20 | docker build . --file Dockerfile.$mssqlVersion --isolation=process -t $acrURL/mssql:$mssqlVersion 21 | 22 | docker push $acrURL/mssql:$mssqlVersion 23 | -------------------------------------------------------------------------------- /CI/AKS/envSetup/setupBuildMachine.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$repoURL, 3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$commitId, 4 | $debugOnString="false" 5 | ); 6 | 7 | $debugOn = ($debugOnString -eq "true"); 8 | if ($debugOn) { 9 | $DebugPreference = "Continue"; 10 | } 11 | 12 | Set-ExecutionPolicy Bypass -Scope Process -Force; 13 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; 14 | iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) ; 15 | choco feature disable --name showDownloadProgress ; 16 | 17 | choco install git --force --force-dependencies -y; 18 | 19 | # Let's check stuff out in our home directory 20 | Set-Location -Path ~ 21 | 22 | & 'C:\Program Files\Git\cmd\git.exe' clone $repoURL sourceRepo ; 23 | Set-Location -Path sourceRepo ; 24 | & 'C:\Program Files\Git\cmd\git.exe' checkout $commitId ; 25 | 26 | Get-ChildItem -Recurse -Path ./sourceRepo ; 27 | -------------------------------------------------------------------------------- /CI/AKS/envSetup/testBuildMachine.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$repoURL, 3 | $debugOnString="false" 4 | ); 5 | 6 | $debugOn = ($debugOnString -eq "true"); 7 | if ($debugOn) { 8 | $DebugPreference = "Continue"; 9 | } 10 | 11 | Write-Output "Got here."; 12 | -------------------------------------------------------------------------------- /CI/AKS/mssql.deployment.windows-template.yml: -------------------------------------------------------------------------------- 1 | # Documentation 2 | # - https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/ 3 | # - https://kubernetes.io/docs/tasks/inject-data-application/define-interdependent-environment-variables/ 4 | # - 5 | apiVersion: apps/v1 6 | kind: Deployment 7 | metadata: 8 | name: matrix.mssqlversion-deployment 9 | labels: 10 | app: matrix.mssqlversion-db 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: matrix.mssqlversion-db 16 | template: 17 | metadata: 18 | labels: 19 | app: matrix.mssqlversion-db 20 | spec: 21 | nodeSelector: 22 | agentpool: akswin 23 | containers: 24 | - name: matrix.mssqlversion-db 25 | image: containerRegistryName/mssql:matrix.mssqlversion 26 | ports: 27 | - containerPort: 80 28 | name: other 29 | protocol: TCP 30 | - containerPort: 1433 31 | name: mssql 32 | protocol: TCP 33 | imagePullSecrets: 34 | - name: acr-secret 35 | 36 | -------------------------------------------------------------------------------- /CI/Azure-DevOps/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | insert_final_newline = true 5 | 6 | -------------------------------------------------------------------------------- /CI/Azure-DevOps/AZ_TempTest.yml: -------------------------------------------------------------------------------- 1 | name: $(Date:yyyyMMdd)$(Rev:.r)($(Build.BuildId)) 2 | 3 | trigger: none 4 | 5 | pr: none 6 | 7 | pool: 8 | vmImage: 'windows-latest' 9 | 10 | parameters: 11 | - name: SQLCMDPath 12 | type: string 13 | default: 'C:\Program Files\Microsoft SQL Server\110\Tools\Binn' 14 | - name: RequestingBuildId 15 | type: string 16 | default: 'NULL' 17 | - name: VMMatrix 18 | type: object 19 | default: [{"name":"S3",'SQLVersionEdition':'2016'},{"name":"S4",'SQLVersionEdition':'2017'},{"name":"S5",'SQLVersionEdition':'2019'}] 20 | 21 | 22 | 23 | variables: 24 | - name: NamePreFix 25 | value: 'tSQLtCI_DevTestLab_' 26 | - name: ArtifactBranchName 27 | value: tSQLt$(Build.SourceVersion) 28 | 29 | stages: 30 | - stage: Find_SQLCMD 31 | dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel 32 | jobs: 33 | - job: 34 | steps: 35 | 36 | - task: PowerShell@2 37 | name: Find_SQLCMD 38 | inputs: 39 | targetType: 'inline' 40 | script: | 41 | $x = get-ChildItem -path C:\program* -include sqlcmd.exe -recurse -ErrorAction Ignore 42 | $x|%{$_.FullName} 43 | 44 | - stage: Find_SqlPackage 45 | dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel 46 | jobs: 47 | - job: 48 | steps: 49 | 50 | - task: PowerShell@2 51 | name: Find_SqlPackage 52 | inputs: 53 | targetType: 'inline' 54 | script: | 55 | $x = get-ChildItem -path C:\program* -include sqlpackage.exe -recurse -ErrorAction Ignore 56 | $x|%{$_.FullName} 57 | -------------------------------------------------------------------------------- /CI/Azure-DevOps/ContributorWithAuthorizationDelete.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "ContributorWithAuthorizationDelete", 3 | "Id": null, 4 | "IsCustom": true, 5 | "Description": "Lets you manage everything except access to resources.", 6 | "Actions": [ 7 | "*" 8 | ], 9 | "NotActions": [ 10 | "Microsoft.Authorization/*/Write", 11 | "Microsoft.Authorization/elevateAccess/Action", 12 | "Microsoft.Blueprint/blueprintAssignments/write", 13 | "Microsoft.Blueprint/blueprintAssignments/delete" 14 | ], 15 | "DataActions": [], 16 | "NotDataActions": [], 17 | "AssignableScopes": [ 18 | "/subscriptions/58c04a99-5b92-410c-9e41-10262f68ca80" 19 | ] 20 | } -------------------------------------------------------------------------------- /CI/Azure-DevOps/CreateSQLContainerAndIpAddressModule.bicep: -------------------------------------------------------------------------------- 1 | param location string = resourceGroup().location 2 | param containerName string 3 | param sqlServerImage string 4 | param cpu int 5 | param memory int 6 | @secure() 7 | param saPassword string 8 | 9 | var containerGroupName = '${containerName}-group' 10 | var sqlPort = 1433 11 | 12 | resource containerGroup 'Microsoft.ContainerInstance/containerGroups@2021-10-01' = { 13 | name: containerGroupName 14 | location: location 15 | properties: { 16 | containers: [ 17 | { 18 | name: containerName 19 | properties: { 20 | image: sqlServerImage 21 | resources: { 22 | requests: { 23 | cpu: cpu 24 | memoryInGB: memory 25 | } 26 | } 27 | environmentVariables: [ 28 | { 29 | name: 'ACCEPT_EULA' 30 | value: 'Y' 31 | } 32 | { 33 | name: 'MSSQL_SA_PASSWORD' 34 | secureValue: saPassword 35 | } 36 | ] 37 | ports: [ 38 | { 39 | port: sqlPort 40 | } 41 | ] 42 | } 43 | } 44 | ] 45 | osType: 'Linux' 46 | ipAddress: { 47 | type: 'Public' 48 | ports: [ 49 | { 50 | protocol: 'tcp' 51 | port: sqlPort 52 | } 53 | ] 54 | } 55 | } 56 | } 57 | 58 | output ipAddress string = containerGroup.properties.ipAddress.ip 59 | output Port int = containerGroup.properties.ipAddress.ports[0].port 60 | -------------------------------------------------------------------------------- /CI/Azure-DevOps/CreateSQLContainerTemplate.bicep: -------------------------------------------------------------------------------- 1 | targetScope='subscription' 2 | 3 | param location string = 'eastus2' 4 | param newResourceGroupName string = 'sqlserver-container-test-rg' 5 | param containerName string = 'sqlserver2022' 6 | param sqlServerImage string = 'mcr.microsoft.com/mssql/server:2022-latest' 7 | @secure() 8 | param saPassword string 9 | param cpu int = 4 10 | param memory int = 8 11 | 12 | 13 | resource newResourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { 14 | name: newResourceGroupName 15 | location: location 16 | tags: { 17 | Department: 'tSQLtCI' 18 | Ephemeral: 'True' 19 | } 20 | } 21 | 22 | 23 | module containers './CreateSQLContainerAndIpAddressModule.bicep' = { 24 | name: 'deployContainers' 25 | scope: newResourceGroup 26 | params: { 27 | location: location 28 | containerName: containerName 29 | sqlServerImage: sqlServerImage 30 | cpu:cpu 31 | memory:memory 32 | saPassword: saPassword 33 | } 34 | } 35 | 36 | output ipAddress string = containers.outputs.ipAddress 37 | output Port int = containers.outputs.Port 38 | -------------------------------------------------------------------------------- /CI/Azure-DevOps/GetSQLServerVersion.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | SUSER_NAME() LoginName, 3 | SYSDATETIME() [TimeStamp], 4 | @@VERSION [VersionDetail], 5 | SERVERPROPERTY('ProductVersion') AS ProductVersion, 6 | SERVERPROPERTY('ProductLevel') AS ProductLevel, 7 | CASE (SELECT PARSENAME(XX,4)+'.'+PARSENAME(XX,3) FROM (SELECT (CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(MAX)))XX)X) 8 | WHEN '9.0' THEN '2005' 9 | WHEN '10.0' THEN '2008' 10 | WHEN '10.50' THEN '2008R2' 11 | WHEN '11.0' THEN '2012' 12 | WHEN '12.0' THEN '2014' 13 | WHEN '13.0' THEN '2016' 14 | WHEN '14.0' THEN '2017' 15 | WHEN '15.0' THEN '2019' 16 | WHEN '16.0' THEN '2022' 17 | ELSE 'Unknown' 18 | END SQLVersion, 19 | SERVERPROPERTY('Collation') AS ServerCollation -------------------------------------------------------------------------------- /CI/CI.ssmssqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Examples/BuildOrder.txt: -------------------------------------------------------------------------------- 1 | CreateDatabase.sql 2 | ../Build/temp/tSQLtBuild/tSQLt.class.sql 3 | Source.sql 4 | Tests.sql 5 | -------------------------------------------------------------------------------- /Examples/CreateDatabase.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | USE tempdb; 17 | 18 | IF(db_id('tSQLt_Example') IS NOT NULL) 19 | EXEC(' 20 | ALTER DATABASE tSQLt_Example SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; 21 | USE tSQLt_Example; 22 | ALTER DATABASE tSQLt_Example SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 23 | USE tempdb; 24 | DROP DATABASE tSQLt_Example; 25 | '); 26 | 27 | CREATE DATABASE tSQLt_Example WITH TRUSTWORTHY OFF; 28 | GO 29 | USE tSQLt_Example; 30 | GO 31 | 32 | 33 | ------------------------------------------------------------------------------------ 34 | CREATE SCHEMA Accelerator; 35 | GO 36 | 37 | IF OBJECT_ID('Accelerator.Particle') IS NOT NULL DROP TABLE Accelerator.Particle; 38 | GO 39 | CREATE TABLE Accelerator.Particle( 40 | Id INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Point_Id PRIMARY KEY, 41 | X DECIMAL(10,2) NOT NULL, 42 | Y DECIMAL(10,2) NOT NULL, 43 | Value NVARCHAR(MAX) NOT NULL, 44 | ColorId INT NOT NULL 45 | ); 46 | GO 47 | 48 | IF OBJECT_ID('Accelerator.Color') IS NOT NULL DROP TABLE Accelerator.Color; 49 | GO 50 | CREATE TABLE Accelerator.Color( 51 | Id INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Color_Id PRIMARY KEY, 52 | ColorName NVARCHAR(MAX) NOT NULL 53 | ); 54 | GO -------------------------------------------------------------------------------- /Examples/Example_Screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Examples/Example_Screenshot.jpg -------------------------------------------------------------------------------- /Examples/Examples.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Examples 6 | {D2F3BB37-831A-4D07-89CC-4B9E1C9E9C07} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Examples/TestCaseTemplate.sql: -------------------------------------------------------------------------------- 1 | -- Comments here are associated with the test. 2 | -- For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/ 3 | CREATE PROCEDURE [].[] 4 | AS 5 | BEGIN 6 | --Assemble 7 | -- This section is for code that sets up the environment. It often 8 | -- contains calls to methods such as tSQLt.FakeTable and tSQLt.SpyProcedure 9 | -- along with INSERTs of relevant data. 10 | -- For more information, see http://tsqlt.org/user-guide/isolating-dependencies/ 11 | 12 | --Act 13 | -- Execute the code under test like a stored procedure, function or view 14 | -- and capture the results in variables or tables. 15 | 16 | --Assert 17 | -- Compare the expected and actual values, or call tSQLt.Fail in an IF statement. 18 | -- Example Asserts: tSQLt.AssertEquals, tSQLt.AssertEqualsString, tSQLt.AssertEqualsTable 19 | -- For a complete list, see: http://tsqlt.org/user-guide/assertions/ 20 | EXEC tSQLt.Fail 'TODO:Implement this test.' 21 | 22 | END; 23 | -------------------------------------------------------------------------------- /Experiments/AnnotationParser.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('dbo.rotiueortiuo') IS NOT NULL DROP PROCEDURE dbo.rotiueortiuo; 2 | GO 3 | 4 | GO 5 | /* create proc dbo.rotiueortiuo on 20200722 6 | /* Annotations/**/ 7 | RETURN 8 | --*//* 9 | RETURN 10 | --[@tSQLt:sdfsdfsd]() 11 | RETURN 12 | */ 13 | CREATE/*23423 14 | /*sdfkljh*//**/ 15 | -sdfkljh*/PROCEDURE 16 | 17 | dbo.rotiueortiuo 18 | AS 19 | RETURN 1; 20 | GO 21 | DECLARE @D NVARCHAR(MAX) = (SELECT definition FROM sys.sql_modules AS SM WHERE SM.object_id = OBJECT_ID('dbo.rotiueortiuo')); 22 | 23 | 24 | SELECT 25 | * 26 | FROM( 27 | SELECT 28 | LTRIM(RTRIM(CASE WHEN LEFT(Z.S,1) = NCHAR(10) THEN SUBSTRING(Z.S,2,LEN(Z.S)-1) ELSE Z.S END)) SS 29 | FROM( 30 | SELECT 31 | SUBSTRING(Y.X,Y.no,LEAD(Y.no)OVER(ORDER BY Y.no)-Y.no-1) S 32 | FROM( 33 | SELECT 34 | * 35 | FROM (VALUES(LEFT(@D,CHARINDEX('CREATE',@D))))X(X) 36 | CROSS APPLY tSQLt.F_Num(LEN(X.X)+2) AS FN WHERE SUBSTRING(NCHAR(13)+X.X+NCHAR(13),FN.no,1)=NCHAR(13) 37 | )Y 38 | )Z 39 | )ZZ 40 | WHERE ZZ.SS LIKE '%--[[]@tSQLt:%](%)%' 41 | -- SELECT FN.no,CHAR(no),CAST(CHAR(no) AS BINARY(1)) FROM tSQLt.F_Num(255) AS FN 42 | 43 | SELECT 44 | *, 45 | SUBSTRING('/**/'+X.X+'/**/',FN.no,LEAD(FN.no)OVER(ORDER BY FN.no)-FN.no) 46 | FROM (VALUES(@D))X(X) 47 | CROSS APPLY tSQLt.F_Num(LEN(X.X)+2) AS FN WHERE SUBSTRING('/**/'+X.X+'/**/',FN.no,2)IN('/*','*/','--',CHAR(13)+CHAR(10)) 48 | -------------------------------------------------------------------------------- /Experiments/CallParameters.sql: -------------------------------------------------------------------------------- 1 | 2 | EXEC('PRINT ''$(parameter1)'';') 3 | 4 | 5 | 6 | 7 | GO 8 | CREATE PROCEDURE #somethingrather 9 | AS 10 | BEGIN 11 | RETURN; 12 | END; 13 | GO 14 | SELECT * FROM sys.procedures 15 | SELECT * FROM tempdb.sys.procedures AS P 16 | GO 17 | IF OBJECT_ID('tempdb..#PrepareServer') IS NOT NULL DROP PROCEDURE tempdb..#PrepareServer; 18 | EXEC(' 19 | CREATE PROCEDURE tempdb..#PrepareServer 20 | AS 21 | BEGIN 22 | SELECT DB_NAME(); 23 | END; 24 | '); 25 | SELECT * FROM tempdb.sys.procedures AS P 26 | EXEC tempdb..#PrepareServer; 27 | GO 28 | EXEC(' 29 | CREATE TABLE #SuchATable(id INT) 30 | '); 31 | SELECT * FROM tempdb.sys.tables AS P 32 | GO 33 | CREATE PROCEDURE #ScopeTest 34 | AS 35 | BEGIN 36 | EXEC('CREATE PROC #Inner1 AS BEGIN RETURN END;'); 37 | EXEC #Inner1; 38 | END; 39 | GO 40 | EXEC #ScopeTest 41 | 42 | GO 43 | ------------------------------------------------------------ 44 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 45 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 46 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 47 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 48 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 49 | IF OBJECT_ID('') IS NOT NULL DROP PROCEDURE ; 50 | GO 51 | CREATE PROCEDURE #... 52 | GO 53 | CREATE FUNCTION #xxx 54 | RETURNS TABLE 55 | AS 56 | RETURN 57 | SELECT 'abcd' xxx 58 | GO 59 | -------------------------------------------------------------------------------- /Experiments/CertificateTest.sql: -------------------------------------------------------------------------------- 1 | IF(CERT_ID('tSQLtSigningKey') IS NOT NULL) DROP CERTIFICATE tSQLtSigningKey; 2 | GO 3 | CREATE CERTIFICATE tSQLtSigningKey 4 | ENCRYPTION BY PASSWORD = 'password' 5 | WITH SUBJECT = 'CN=tSQLt.org, title=tSQLt_OfficialSigningKey', 6 | EXPIRY_DATE = '2020-12-01T00:00:00.000' 7 | GO 8 | BACKUP CERTIFICATE tSQLtSigningKey TO FILE ='C:\Data\git\tSQLt\tSQLt\tSQLtCLR\OfficialSigningKey\tSQLtSigningKey.cer' 9 | WITH PRIVATE KEY(FILE='C:\Data\git\tSQLt\tSQLt\tSQLtCLR\OfficialSigningKey\tSQLtSigningKey.pkf', DECRYPTION BY PASSWORD = 'password', ENCRYPTION BY PASSWORD = 'password'); 10 | -------------------------------------------------------------------------------- /Experiments/CollationTests.sql: -------------------------------------------------------------------------------- 1 | /*-- 2 | RELEVANT LINKS 3 | https://www.red-gate.com/simple-talk/databases/sql-server/t-sql-programming-sql-server/questions-sql-server-collations-shy-ask/ 4 | https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql?view=sql-server-ver15 5 | --*/ 6 | 7 | SELECT DATABASEPROPERTYEX('tempdb','Collation') [tempdb collation], 8 | DATABASEPROPERTYEX(DB_NAME(),'Collation') [database collation] 9 | GO 10 | 11 | DROP TABLE IF EXISTS dbo.atable; 12 | DROP TABLE IF EXISTS tempdb..#Actual; 13 | SELECT 14 | 'Hello World!' COLLATE SQL_Polish_CP1250_CI_AS c1, 15 | 'Hello World!' COLLATE SQL_Latin1_General_CP437_BIN c2, 16 | 'Hello World!' COLLATE Albanian_BIN2 c3 17 | INTO dbo.atable 18 | SELECT * INTO #Actual FROM dbo.atable 19 | 20 | SELECT 'dbo.atable' [table],* FROM sys.columns WHERE object_id = OBJECT_ID('dbo.atable') 21 | 22 | SELECT '#Actual',* FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb..#Actual'); 23 | 24 | GO 25 | 26 | DROP TABLE IF EXISTS tempdb..#E; 27 | CREATE TABLE #E( 28 | C1 NVARCHAR(MAX) COLLATE DATABASE_DEFAULT, 29 | C2 NVARCHAR(MAX) 30 | ); 31 | 32 | SELECT '#E',* FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb..#E'); 33 | GO 34 | SELECT * 35 | FROM #E E1 36 | JOIN #E E2 37 | ON E2.C2 = E1.C1 -------------------------------------------------------------------------------- /Experiments/CreateSigningCertificate.ps1: -------------------------------------------------------------------------------- 1 | # $cert = New-SelfSignedCertificate -Type Custom -KeySpec Signature ` 2 | # -Subject "CN=P2SRootCert" -KeyExportPolicy Exportable ` 3 | # -HashAlgorithm sha256 -KeyLength 2048 ` 4 | # -CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign 5 | 6 | New-SelfSignedCertificate -Type Custom -DnsName P2SChildCert -KeySpec Signature ` 7 | -Subject "CN=tSQLtOfficialSigningKey" -KeyExportPolicy Exportable ` 8 | -HashAlgorithm sha256 -KeyLength 2048 ` 9 | -CertStoreLocation "Cert:\CurrentUser\My" ` 10 | -Signer $cert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2") -------------------------------------------------------------------------------- /Experiments/CreateXEventSession_SSP&Batch.sql: -------------------------------------------------------------------------------- 1 | IF(EXISTS(SELECT * FROM sys.server_event_sessions WHERE name = 'MyXEventSession')) 2 | BEGIN 3 | DROP EVENT SESSION [MyXEventSession] ON SERVER; 4 | END; 5 | CREATE EVENT SESSION [MyXEventSession] ON SERVER 6 | ADD EVENT sqlserver.rpc_completed ( 7 | ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) 8 | WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') 9 | ), 10 | ADD EVENT sqlserver.rpc_starting ( 11 | ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) 12 | WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') 13 | ), 14 | ADD EVENT sqlserver.sql_batch_completed ( 15 | ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) 16 | WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') 17 | ), 18 | ADD EVENT sqlserver.sql_batch_starting ( 19 | ACTION(sqlserver.sql_text, sqlserver.database_id, sqlserver.username) 20 | WHERE (sqlserver.database_name=N'tSQLt_ValidateBuild') 21 | ) 22 | ADD TARGET package0.ring_buffer(SET max_memory=4096) -- Storing data in a ring buffer 23 | WITH (MAX_MEMORY=4096 KB, EVENT_RETENTION_MODE=NO_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=ON, STARTUP_STATE=OFF) 24 | GO 25 | ALTER EVENT SESSION [MyXEventSession] ON SERVER STATE = START; -------------------------------------------------------------------------------- /Experiments/Debugging tSQLt.tdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Experiments/Debugging tSQLt.tdf -------------------------------------------------------------------------------- /Experiments/Experiments.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Experiments 6 | {67F0113D-7E17-41F4-961D-FA1E88969F9C} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Experiments/GenerateLargeXMLResult.sql: -------------------------------------------------------------------------------- 1 | 2 | SELECT (SELECT * FROM sys.all_objects CROSS JOIN (SELECT TOP(1) ROW_NUMBER()OVER(ORDER BY (SELECT 1)) n FROM sys.all_objects) n FOR XML PATH(''),TYPE,ROOT('GH')) 3 | 4 | -------------------------------------------------------------------------------- /Experiments/GetDir.ps1: -------------------------------------------------------------------------------- 1 | $scriptpath = $MyInvocation.MyCommand.Path 2 | $dir = Split-Path $scriptpath 3 | $scriptpath 4 | $dir -------------------------------------------------------------------------------- /Experiments/IncludeTest1.ps1: -------------------------------------------------------------------------------- 1 | $xxx=123 2 | -------------------------------------------------------------------------------- /Experiments/IncludeTest2.ps1: -------------------------------------------------------------------------------- 1 | .((Split-Path $MyInvocation.MyCommand.Path)+"/includeTest1.ps1") 2 | $xxx 3 | -------------------------------------------------------------------------------- /Experiments/InvokeSqlcmdTest.ps1: -------------------------------------------------------------------------------- 1 | 2 | Param( 3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, 4 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Username, 5 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $anotherString 6 | ); 7 | 8 | $SqlCmdVariables = "DatabaseName=master", "ColumnName=name"; 9 | $Results = (Invoke-Sqlcmd -ServerInstance $ServerName -Username $Username -Password $anotherString -Query "SET STATISTICS XML ON; SELECT `$(ColumnName) FROM sys.databases WHERE [name] = '`$(DataBaseName)';" -Variable $SqlCmdVariables -MaxCharLength 10MB); 10 | $Plan = [xml]$Results[$Results.GetUpperBound(0)].Item(0); 11 | # $Plan.Save("C:\temp\test.sqlplan"); 12 | $Plan; 13 | 14 | -------------------------------------------------------------------------------- /Experiments/LIKE4000.sql: -------------------------------------------------------------------------------- 1 | SELECT * 2 | INTO #td 3 | FROM ( 4 | VALUES( 5 | N'before+before+before+before+before+before+'+REPLICATE(CAST('12345' AS NVARCHAR(MAX)),4000)+N'+after+after+after+after+after+after', 6 | '%'+REPLICATE(CAST('12345' AS NVARCHAR(MAX)),800)+'%' 7 | ))X(s,p); 8 | GO 9 | RAISERROR('direct select',0,1)WITH NOWAIT; 10 | 11 | SELECT * 12 | FROM (VALUES('direct'))AS L(loc) 13 | LEFT OUTER JOIN #td td 14 | ON td.s LIKE td.p; 15 | GO 16 | CREATE PROCEDURE #tttt 17 | @s NVARCHAR(MAX), 18 | @p NVARCHAR(4000) 19 | AS 20 | SELECT * 21 | FROM (VALUES('proc'))AS L(loc) 22 | LEFT OUTER JOIN 23 | (VALUES(@s)) AS X(s) 24 | ON s LIKE @p; 25 | GO 26 | RAISERROR('procedure call',0,1)WITH NOWAIT; 27 | 28 | DECLARE @s NVARCHAR(MAX); 29 | DECLARE @p NVARCHAR(MAX); 30 | SELECT @s = s, @p = p FROM #td; 31 | 32 | EXEC #tttt @s, @p; 33 | 34 | GO 35 | 36 | DROP PROC #tttt 37 | DROP TABLE #td -------------------------------------------------------------------------------- /Experiments/MSSQL Defect Try-Catch Invalidates Transaction.sql: -------------------------------------------------------------------------------- 1 | PRINT 'No TRY...CATCH:'; 2 | EXEC ('BEGIN TRAN'); 3 | SELECT XACT_STATE() AS [XACT_STATE()],@@TRANCOUNT AS [@@TRANCOUNT]; 4 | GO 5 | IF(XACT_STATE()<>0)ROLLBACK; 6 | GO 7 | 8 | 9 | 10 | GO 11 | PRINT 'In TRY...CATCH:'; 12 | BEGIN TRY 13 | EXEC ('BEGIN TRAN'); 14 | END TRY 15 | BEGIN CATCH 16 | END CATCH; 17 | SELECT XACT_STATE() AS [XACT_STATE()],@@TRANCOUNT AS [@@TRANCOUNT]; 18 | GO 19 | IF(XACT_STATE()<>0)ROLLBACK; 20 | GO 21 | -------------------------------------------------------------------------------- /Experiments/ObjectType_to_ExtendedPropertyLevelType_mapping.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Experiments/ObjectType_to_ExtendedPropertyLevelType_mapping.xlsx -------------------------------------------------------------------------------- /Experiments/ParsingDisaster.sql: -------------------------------------------------------------------------------- 1 | --execute, then comment out the line below and execute again 2 | SELECT 1 AS [A 3 | GO 4 | SELECT 0 AS [X] 5 | 6 | --/* <-- execute, then delete '--' and execute again 7 | /*Comment*/ 8 | SELECT 2 9 | ,2.2 10 | --*/SELECT 3 /* 11 | --*/,3.2,' 12 | SELECT 4 13 | ,4.2 14 | --' /* 15 | --*/SELECT 5 /* 16 | --*/,5.2 /* 17 | --*/ 18 | SELECT 6 19 | -------------------------------------------------------------------------------- /Experiments/ReadXEventSession.sql: -------------------------------------------------------------------------------- 1 | DECLARE @xml_output xml; 2 | 3 | -- Get the XML data from the ring buffer 4 | SELECT @xml_output = CAST(xet.target_data AS xml) 5 | FROM sys.dm_xe_session_targets AS xet 6 | JOIN sys.dm_xe_sessions AS xe 7 | ON (xe.address = xet.event_session_address) 8 | WHERE xe.name = N'MyXEventSession' -- Replace with your session name 9 | AND xet.target_name = N'ring_buffer'; 10 | -- SELECT @xml_output 11 | -- Parse and display the relevant information 12 | SELECT 13 | event_data.value('(@timestamp)[1]', 'datetime2') AS EventTime, 14 | event_data.value('(data[@name="duration"]/value)[1]', 'int') AS Duration, 15 | event_data.value('(action[@name="sql_text"]/value)[1]', 'nvarchar(max)') AS SqlText, 16 | event_data.query('.') xx 17 | FROM @xml_output.nodes('RingBufferTarget/event') AS XEventData(event_data) 18 | ORDER BY EventTime; 19 | -------------------------------------------------------------------------------- /Experiments/RunExternalAccessKeyExistsTests.sql: -------------------------------------------------------------------------------- 1 | USE tSQLt_dev; 2 | GO 3 | DECLARE @cmd NVARCHAR(MAX); 4 | 5 | IF(CAST(SERVERPROPERTY('ProductMajorVersion') AS INT)<14) 6 | BEGIN 7 | PRINT '-------Dropping tSQLtAssemblyKey---------------'; 8 | SET @cmd = N'IF SUSER_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP LOGIN tSQLtAssemblyKey;'; 9 | EXEC master.sys.sp_executesql @cmd; 10 | SET @cmd = N'IF ASYMKEY_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP ASYMMETRIC KEY tSQLtAssemblyKey;'; 11 | EXEC master.sys.sp_executesql @cmd; 12 | END; 13 | ELSE 14 | BEGIN 15 | PRINT '-------Dropping of tSQLtAssemblyKey skipped---------------'; 16 | END; 17 | GO 18 | EXEC tSQLt.InstallAssemblyKey; 19 | GO 20 | EXECUTE AS LOGIN='tSQLt.Build.SA' 21 | GO 22 | EXEC tSQLt.Run 'EnableExternalAccessTests'; 23 | GO 24 | REVERT 25 | GO 26 | -------------------------------------------------------------------------------- /Experiments/SM query - read trace table.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | R.EventSequence, 3 | TE.name, 4 | TSV.subclass_name, 5 | R.ObjectName, 6 | R.LineNumber, 7 | R.TransactionID, 8 | R.XactSequence, 9 | ISNULL(REPLICATE(' ',(R.NestLevel-1)),'')+CAST(R.TextData AS NVARCHAR(MAX)) AS TextData, 10 | R.Error, 11 | R.Severity, 12 | R.NestLevel, 13 | R.RowNumber, 14 | R.EventClass, 15 | R.EventSubClass, 16 | R.ApplicationName, 17 | R.ClientProcessID, 18 | R.DatabaseID, 19 | R.DatabaseName, 20 | R.GroupID, 21 | R.HostName, 22 | R.IsSystem, 23 | R.LoginName, 24 | R.LoginSid, 25 | R.NTDomainName, 26 | R.NTUserName, 27 | R.RequestID, 28 | R.SPID, 29 | R.ServerName, 30 | R.SessionLoginName, 31 | R.StartTime, 32 | R.Success, 33 | R.GUID, 34 | R.BinaryData, 35 | R.Duration, 36 | R.EndTime, 37 | R.IntegerData, 38 | R.CPU, 39 | R.IntegerData2, 40 | R.Offset, 41 | R.Reads, 42 | R.RowCounts, 43 | R.Writes, 44 | R.State, 45 | R.ObjectID, 46 | R.ObjectType, 47 | R.SourceDatabaseID, 48 | R.IndexID, 49 | R.Type, 50 | R.Mode, 51 | R.OwnerID, 52 | R.ObjectID2, 53 | R.BigintData1 54 | FROM dbo.run4 R 55 | LEFT JOIN sys.trace_events AS TE 56 | ON R.EventClass = TE.trace_event_id 57 | LEFT JOIN sys.trace_subclass_values AS TSV 58 | ON TSV.trace_event_id = TE.trace_event_id 59 | AND R.EventSubClass = TSV.subclass_value 60 | WHERE ISNULL(R.ObjectName,'???') NOT IN ('Private_Print','sp_rename', 'sp_validname','GetTestResultFormatter','sp_addextendedproperty','sp_updateextendedproperty') 61 | ORDER BY R.EventSequence -------------------------------------------------------------------------------- /Experiments/SQLCmdTest.1.1.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('dbo.testproc') IS NOT NULL DROP PROCEDURE dbo.testproc; 2 | -------------------------------------------------------------------------------- /Experiments/SQLCmdTest.1.2.sql: -------------------------------------------------------------------------------- 1 | CREATE PROC dbo.testproc 2 | AS 3 | BEGIN 4 | RETURN 5 | END; -------------------------------------------------------------------------------- /Experiments/SQLCmdTest.1.sql: -------------------------------------------------------------------------------- 1 | :r C:\Data\git\tSQLt\tSQLt\Experiments\SQLCmdTest.1.1.sql 2 | 3 | :r C:\Data\git\tSQLt\tSQLt\Experiments\SQLCmdTest.1.2.sql 4 | 5 | GO 6 | 7 | :r C:\Data\git\tSQLt\tSQLt\Experiments\SQLCmdTest.1.1.sql 8 | GO 9 | :!! echo something 10 | :r C:\Data\git\tSQLt\tSQLt\Experiments\SQLCmdTest.1.2.sql 11 | -------------------------------------------------------------------------------- /Experiments/SpProcPrototype.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | GO 17 | 18 | create table #tst (pn sysname,cc int, cmd varchar(max)) 19 | go 20 | insert into #tst select 'tstp',2,'print $$cc$$'; 21 | 22 | go 23 | declare @cmd nvarchar(max); 24 | update #tst 25 | set cc=cc+1, 26 | @cmd = replace(cmd,'$$cc$$',cast(cc+1 as varchar(max))) 27 | where pn='tstp' 28 | exec(@cmd) 29 | go 3 30 | drop table #tst -------------------------------------------------------------------------------- /Experiments/TestingTransactionNames.sql: -------------------------------------------------------------------------------- 1 | IF(XACT_STATE()<>0)ROLLBACK 2 | GO 3 | DROP TABLE IF EXISTS #Actual 4 | GO 5 | DECLARE @TranName NVARCHAR(32) = NULL; 6 | SELECT 1,@@TRANCOUNT 7 | SELECT 1 X,@@TRANCOUNT TC INTO #Actual 8 | BEGIN TRAN; 9 | SELECT 2,@@TRANCOUNT 10 | INSERT INTO #Actual VALUES(2,@@TRANCOUNT); 11 | SAVE TRAN @TranName; 12 | SELECT 3,@@TRANCOUNT 13 | SELECT * FROM sys.dm_tran_current_transaction AS DTCT JOIN sys.dm_tran_session_transactions 14 | AS DTAT ON DTAT.transaction_id = DTCT.transaction_id 15 | INSERT INTO #Actual VALUES(3,@@TRANCOUNT); 16 | SELECT * FROM #Actual AS A 17 | ROLLBACK TRAN @TranName; 18 | SELECT 4,@@TRANCOUNT 19 | INSERT INTO #Actual VALUES(4,@@TRANCOUNT); 20 | COMMIT; 21 | SELECT * FROM #Actual AS A 22 | -------------------------------------------------------------------------------- /Experiments/UnprepareServer.sql: -------------------------------------------------------------------------------- 1 | GO 2 | EXEC tSQLt.RemoveAssemblyKey; 3 | GO 4 | EXEC sp_configure @configname='clr enabled', @configvalue=0; 5 | GO 6 | RECONFIGURE 7 | GO 8 | EXEC sp_configure @configname='show adv', @configvalue=1; 9 | GO 10 | RECONFIGURE 11 | GO 12 | EXEC sp_configure @configname='clr stri', @configvalue=1; 13 | GO 14 | RECONFIGURE 15 | GO 16 | EXEC sp_configure @configname='show adv', @configvalue=0; 17 | GO 18 | RECONFIGURE 19 | GO 20 | SELECT * FROM master.sys.configurations AS C WHERE name LIKE '%clr%' 21 | SELECT * FROM master.sys.server_principals AS SP WHERE SP.name LIKE '%tSQLt%'; 22 | SELECT * FROM master.sys.asymmetric_keys AS AK WHERE AK.name LIKE '%tSQLt%'; 23 | SELECT * FROM master.sys.trusted_assemblies AS TA --WHERE SP.name LIKE '%tSQLt%'; 24 | SELECT * FROM master.sys.assemblies AS AK WHERE AK.name LIKE '%tSQLt%'; 25 | SELECT name,AK.is_trustworthy_on FROM master.sys.databases AS AK WHERE AK.name LIKE '%tSQLt%'; 26 | SELECT * FROM sys.server_permissions AS SP WHERE SP.grantee_principal_id = (SELECT SP2.principal_id FROM sys.server_principals AS SP2 WHERE SP2.name = 'tSQLtAssemblyKey'); 27 | --||-- 28 | --^^--Needs manual review for now 29 | --||-- 30 | -------------------------------------------------------------------------------- /Experiments/XMLExperiment.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | GO 17 | create table #tst (pn sysname,cc int, cmd varchar(max)) 18 | go 19 | insert into #tst select 'tstp',2,'print $$cc$$'; 20 | 21 | go 22 | declare @cmd nvarchar(max); 23 | update #tst 24 | set cc=cc+1, 25 | @cmd = replace(cmd,'$$cc$$',cast(cc+1 as varchar(max))) 26 | where pn='tstp' 27 | exec(@cmd) 28 | 29 | -- select @cmd as cmd 30 | --for xml raw 31 | 32 | --this is the problem: 33 | set @cmd=@cmd+char(0) 34 | 35 | 36 | select @cmd as cmd,cast(@cmd as varbinary(max)) as cmd2,null as cmd3 37 | for xml path('') 38 | 39 | declare @x xml = ( 40 | select @cmd as cmd,cast(@cmd as varbinary(max)) as cmd2,null as cmd3 41 | for xml path('')) 42 | select a.value('cmd[1]', 'varchar(max)') cmd,CAST(a.value('cmd2[1]', 'varBINARY(max)') as NVARCHAR(MAX)) cmd2 43 | from @x.nodes('.') n(a) 44 | 45 | go 3 46 | drop table #tst -------------------------------------------------------------------------------- /Experiments/sqlServerAlias.ps1: -------------------------------------------------------------------------------- 1 | # List existing aliases 2 | Get-WmiObject -Namespace 'root\Microsoft\SqlServer\ComputerManagement15' -Class 'SqlServerAlias' | 3 | Format-Table -Property 'AliasName', 'ServerName', 'ProtocolName', 'ConnectionString' 4 | 5 | # Delete existing aliases 6 | $alias = Get-WmiObject -namespace 'root\Microsoft\SqlServer\ComputerManagement15' -class 'SqlServerAlias' -filter "AliasName='Dev_tSQLt'" 7 | $alias.Delete() 8 | 9 | # Example script to create an alias 10 | $alias = ([wmiclass] '\\.\root\Microsoft\SqlServer\ComputerManagement15:SqlServerAlias').CreateInstance() 11 | $alias.AliasName = 'Dev_tSQLt' 12 | $alias.ConnectionString = '41433' #connection specific parameters depending on the protocol 13 | $alias.ProtocolName = 'tcp' 14 | $alias.ServerName = '810D79BF7E9C' 15 | $alias.Put() | Out-Null; -------------------------------------------------------------------------------- /Experiments/sqlcmdErrorHandling.ps1: -------------------------------------------------------------------------------- 1 | 2 | Param( 3 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $ServerName, 4 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $Login, 5 | [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string] $SqlCmdPath 6 | ); 7 | 8 | 9 | $sqlFileForTesting = @" 10 | RAISERROR('an error',15,2); 11 | GO 12 | RAISERROR('no error 1',0,1)WITH NOWAIT; 13 | GO 14 | RAISERROR('no error 2',0,1)WITH NOWAIT; 15 | GO 16 | "@; 17 | 18 | Set-Content "sqlFileForTesting.sql" $sqlFileForTesting; 19 | 20 | #$CallSqlCmd = '&"'+$SqlCmdPath+'\sqlcmd.exe" -S "'+$ServerName+'" '+$Login+' -I -b -Q "RAISERROR (''an error!'',15,3)"'; 21 | $CallSqlCmd = '&"'+$SqlCmdPath+'\sqlcmd.exe" -S "'+$ServerName+'" '+$Login+' -I -b -i "sqlFileForTesting.sql"'; 22 | $CallSqlCmd; 23 | $CallSqlCmd = $CallSqlCmd + ';if($LASTEXITCODE -ne 0){throw "error during execution";}' 24 | Invoke-Expression $CallSqlCmd; 25 | 26 | -------------------------------------------------------------------------------- /Experiments/tSQLtListObjects.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | O.type_desc, 3 | QUOTENAME(S.name)+'.'+QUOTENAME(O.name) AS name, 4 | PP.parameters, 5 | CC.columns 6 | FROM sys.objects AS O 7 | JOIN sys.schemas AS S 8 | ON S.schema_id = O.schema_id 9 | CROSS APPLY 10 | ( 11 | SELECT SUBSTRING 12 | ( 13 | ( 14 | SELECT ','+CHAR(13)+CHAR(10)+CASE WHEN P.parameter_id = 0 THEN '{RETURN}' ELSE P.name END+' '+ISNULL(PGFTN.TypeName,'') 15 | FROM sys.parameters AS P 16 | OUTER APPLY tSQLt.Private_GetFullTypeName(P.user_type_id,P.max_length,P.precision,P.scale,NULL) AS PGFTN 17 | WHERE P.object_id = O.object_id 18 | ORDER BY P.parameter_id 19 | FOR XML PATH(''),TYPE 20 | ).value('.','VARCHAR(MAX)'), 21 | 4, 22 | -1-POWER(-2,31) 23 | ) parameters 24 | )PP 25 | CROSS APPLY 26 | ( 27 | SELECT SUBSTRING 28 | ( 29 | ( 30 | SELECT ','+CHAR(13)+CHAR(10)+C.name+' '+ISNULL(PGFTN.TypeName,'') 31 | FROM sys.columns AS C 32 | OUTER APPLY tSQLt.Private_GetFullTypeName(C.user_type_id,C.max_length,C.precision,C.scale,C.collation_name) AS PGFTN 33 | WHERE C.object_id = O.object_id 34 | ORDER BY C.column_id 35 | FOR XML PATH(''),TYPE 36 | ).value('.','VARCHAR(MAX)'), 37 | 4, 38 | -1-POWER(-2,31) 39 | ) columns 40 | )CC 41 | WHERE O.is_ms_shipped = 0 42 | AND S.name = 'tSQLt' 43 | AND O.type IN('TT','FN','IF','U','FS','V','P','TF','PC','FT') 44 | ORDER BY CASE WHEN O.name LIKE 'Private[_]%' THEN 1 ELSE 0 END,O.type_desc,name 45 | 46 | 47 | SELECT SCHEMA_NAME(T.schema_id),* FROM sys.types AS T 48 | --SELECT * FROM sys.columns AS C 49 | 50 | --SELECT type,O.type_desc,COUNT(1) FROM sys.objects AS O GROUP BY O.type ,O.type_desc 51 | 52 | --SELECT -1-POWER(-2,31) 53 | 54 | --SELECT CAST(', ' AS VARBINARY(MAX)) 55 | -------------------------------------------------------------------------------- /Experiments/tSQLtOfficialSigningKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Experiments/tSQLtOfficialSigningKey.pfx -------------------------------------------------------------------------------- /OtherFiles/Download at tSQLt.org.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/OtherFiles/Download at tSQLt.org.png -------------------------------------------------------------------------------- /OtherFiles/Please download at tSQLt.org.txt: -------------------------------------------------------------------------------- 1 | Starting August 2015, all tSQLt downloads will be available directly at tSQLt.org 2 | Please go there for the latest version. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tSQLt 2 | 3 | Download the latest version at [tSQLt.org](http://tsqlt.org/downloads/). 4 | 5 | tSQLt is a unit testing framework for Microsoft SQL Server. 6 | It is compatible with SQL Server 2005 (service pack 2 required) and above on all editions. 7 | 8 | tSQLt allows you to implement unit tests in T-SQL. This is important as you do not have to switch between various tools to create your code and your unit tests. tSQLt also provides the following features to make it easier to create and manage unit tests: 9 | 10 | * Tests are automatically run within transactions – this keeps tests independent and reduces any cleanup work you need 11 | * Tests can be grouped together within a schema – allowing you to organize your tests and use common setup methods 12 | * Output can be generated in plain text or XML – making it easier to integrate with a continuous integration tool 13 | 14 | tSQLt is licensed under Apache 2.0 (https://github.com/tSQLt-org/tSQLt/blob/master/Build/License.txt) 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/ReadMe.txt: -------------------------------------------------------------------------------- 1 | This zip file contains a set of SQL Prompt snippets for use with Red Gate SQL Prompt. 2 | 3 | Red Gate SQL Prompt is not part of tSQLt and not required to use tSQLt. 4 | You can get it here:http://www.red-gate.com/products/sql-development/sql-prompt/ 5 | 6 | To install the tSQLt snippets, unzip this zip file into the SQL Prompt Snippet Directory. 7 | This directory is usually located in "AppData\Local\Red Gate\SQL Prompt 6\Snippets" 8 | under your local user directory. -------------------------------------------------------------------------------- /Snippets/ida.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/ida.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idf.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idf.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idl.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idl.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idp.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idp.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/ids.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/ids.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idt.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idt.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idtr.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idtr.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idu.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idu.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/idv.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/idv.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tab.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tab.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tac.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tac.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tal.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tal.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tat.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tat.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tca.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tca.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tce.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tce.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tco.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tco.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tct.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tct.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/te.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/te.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tes.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tes.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tet.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tet.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tf.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tf.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tff.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tff.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tft.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tft.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tie.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tie.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tmt.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tmt.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tnc.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tnc.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tne.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tne.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tnt.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tnt.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/toe.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/toe.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tpc.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tpc.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/trf.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/trf.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tro.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tro.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tso.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tso.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/tsp.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/tsp.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/txe.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/txe.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/txn.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/txn.sqlpromptsnippet -------------------------------------------------------------------------------- /Snippets/txp.sqlpromptsnippet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Snippets/txp.sqlpromptsnippet -------------------------------------------------------------------------------- /Source/ExecutePrepareServer.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.PrepareServer; 2 | -------------------------------------------------------------------------------- /Source/InWork.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/Source/InWork.sql -------------------------------------------------------------------------------- /Source/PrepareServerBuildOrder.txt: -------------------------------------------------------------------------------- 1 | ../Build/temp/tSQLtBuild/tSQLt.Private_GetAssemblyKeyBytes.sql 2 | tSQLt.Private_EnableCLR.ssp.sql 3 | tSQLt.Private_GetSQLProductMajorVersion.ssp.sql 4 | tSQLt.RemoveAssemblyKey.ssp.sql 5 | tSQLt.InstallAssemblyKey.ssp.sql 6 | tSQLt.PrepareServer.ssp.sql 7 | ExecutePrepareServer.sql 8 | -------------------------------------------------------------------------------- /Source/ResetValidationServerBuildOrder1.txt: -------------------------------------------------------------------------------- 1 | ../Build/temp/tSQLtTests/Source/tSQLt.Private_GetAssemblyKeyBytes.sql 2 | tSQLt.Private_GetSQLProductMajorVersion.ssp.sql 3 | tSQLt.RemoveAssemblyKey.ssp.sql 4 | ../Build/SQL/ExecuteResetValidationServer.sql 5 | -------------------------------------------------------------------------------- /Source/ResetValidationServerBuildOrder2.txt: -------------------------------------------------------------------------------- 1 | ../Build/temp/tSQLtTests/ResetValidationServer.tmp.sql 2 | ../Build/SQL/ForceDropTempProcedures.sql 3 | ../Build/SQL/CreateLogin(tSQLt.Build).sql -------------------------------------------------------------------------------- /Source/SetClrEnabled.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 tSQLt 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | EXEC sp_configure 'clr enabled', 1; 17 | RECONFIGURE; 18 | GO 19 | --DECLARE @cmd NVARCHAR(MAX); 20 | --SET @cmd='ALTER DATABASE ' + QUOTENAME(DB_NAME()) + ' SET TRUSTWORTHY ON;'; 21 | --EXEC(@cmd); 22 | GO 23 | -------------------------------------------------------------------------------- /Source/Source.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source 6 | {57B28F7E-3312-4E55-A6FA-75019BDACA5B} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Source/tSQLt.(at)tSQLt_MaxSqlMajorVersion.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.[@tSQLt:MaxSqlMajorVersion]') IS NOT NULL DROP FUNCTION tSQLt.[@tSQLt:MaxSqlMajorVersion]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.[@tSQLt:MaxSqlMajorVersion](@MaxVersion INT) 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT AF.* 10 | FROM (SELECT PSSV.Major FROM tSQLt.Private_SqlVersion() AS PSV CROSS APPLY tSQLt.Private_SplitSqlVersion(PSV.ProductVersion) AS PSSV) AV 11 | CROSS APPLY tSQLt.[@tSQLt:SkipTest]('Maximum allowed version is '+ 12 | CAST(@MaxVersion AS NVARCHAR(MAX))+ 13 | ', but current version is '+ 14 | CAST(AV.Major AS NVARCHAR(MAX))+'.' 15 | ) AS AF 16 | WHERE @MaxVersion < AV.Major 17 | GO 18 | ---Build- 19 | GO 20 | 21 | -------------------------------------------------------------------------------- /Source/tSQLt.(at)tSQLt_MinSqlMajorVersion.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.[@tSQLt:MinSqlMajorVersion]') IS NOT NULL DROP FUNCTION tSQLt.[@tSQLt:MinSqlMajorVersion]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.[@tSQLt:MinSqlMajorVersion](@MinVersion INT) 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT AF.* 10 | FROM 11 | ( 12 | SELECT PSSV.Major 13 | FROM tSQLt.Private_SqlVersion() AS PSV 14 | CROSS APPLY tSQLt.Private_SplitSqlVersion(PSV.ProductVersion) AS PSSV 15 | ) AV 16 | CROSS APPLY tSQLt.[@tSQLt:SkipTest]('Minimum required version is '+ 17 | CAST(@MinVersion AS NVARCHAR(MAX))+ 18 | ', but current version is '+ 19 | CAST(AV.Major AS NVARCHAR(MAX))+'.' 20 | ) AS AF 21 | WHERE @MinVersion > AV.Major 22 | GO 23 | ---Build- 24 | GO 25 | 26 | -------------------------------------------------------------------------------- /Source/tSQLt.(at)tSQLt_NoTransaction.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.[@tSQLt:NoTransaction]') IS NOT NULL DROP FUNCTION tSQLt.[@tSQLt:NoTransaction]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.[@tSQLt:NoTransaction](@CleanUpProcedureName NVARCHAR(MAX) = NULL) 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT 10 | CASE 11 | WHEN (X.QuotedName IS NULL) 12 | THEN 'INSERT INTO #NoTransaction VALUES(NULL);' 13 | ELSE 'IF(NOT EXISTS (SELECT 1 FROM sys.procedures WHERE object_id = OBJECT_ID('+X.QuotedName+'))) BEGIN RAISERROR(''Test CleanUp Procedure %s does not exist or is not a procedure.'',16,10,'+X.QuotedName+'); END;INSERT INTO #NoTransaction VALUES('+X.QuotedName+');' 14 | END AS AnnotationCmd 15 | FROM (VALUES(''''+REPLACE(@CleanUpProcedureName,'''','''''')+''''))X(QuotedName); 16 | GO 17 | ---Build- 18 | GO 19 | -------------------------------------------------------------------------------- /Source/tSQLt.(at)tSQLt_RunOnlyOnHostPlatform.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.[@tSQLt:RunOnlyOnHostPlatform]') IS NOT NULL DROP FUNCTION tSQLt.[@tSQLt:RunOnlyOnHostPlatform]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.[@tSQLt:RunOnlyOnHostPlatform](@HostPlatform NVARCHAR(MAX)) 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT SkipTestFunction.* 10 | FROM (SELECT I.HostPlatform FROM tSQLt.Info() AS I WHERE I.HostPlatform <> @HostPlatform) AV 11 | CROSS APPLY tSQLt.[@tSQLt:SkipTest]('HostPlatform is required to be '''+ 12 | @HostPlatform + 13 | ''', but is '''+ 14 | AV.HostPlatform + 15 | '''.' 16 | ) AS SkipTestFunction; 17 | GO 18 | ---Build- 19 | GO 20 | 21 | -------------------------------------------------------------------------------- /Source/tSQLt.(at)tSQLt_SkipTest.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.[@tSQLt:SkipTest]') IS NOT NULL DROP FUNCTION tSQLt.[@tSQLt:SkipTest]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.[@tSQLt:SkipTest](@SkipReason NVARCHAR(MAX)) 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT 'EXEC tSQLt.Private_SkipTestAnnotationHelper @SkipReason = '''+ 10 | ISNULL(NULLIF(REPLACE(@SkipReason,'''',''''''),''),'')+ 11 | ''';' AS AnnotationCmd; 12 | GO 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /Source/tSQLt.ApplyTrigger.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.ApplyTrigger') IS NOT NULL DROP PROCEDURE tSQLt.ApplyTrigger; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.ApplyTrigger 5 | @TableName NVARCHAR(MAX), 6 | @TriggerName NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | DECLARE @OrgTableObjectId INT; 10 | DECLARE @NewNameOfOriginalTrigger NVARCHAR(MAX); 11 | 12 | SELECT @OrgTableObjectId = OrgTableObjectId FROM tSQLt.Private_GetOriginalTableInfo(OBJECT_ID(@TableName)) orgTbl 13 | IF(@OrgTableObjectId IS NULL) 14 | BEGIN 15 | RAISERROR('%s does not exist or was not faked by tSQLt.FakeTable.', 16, 10, @TableName); 16 | END; 17 | 18 | DECLARE @FullTriggerName NVARCHAR(MAX); 19 | DECLARE @TriggerObjectId INT; 20 | SELECT @FullTriggerName = QUOTENAME(SCHEMA_NAME(schema_id))+'.'+QUOTENAME(name), @TriggerObjectId = object_id 21 | FROM sys.objects WHERE PARSENAME(@TriggerName,1) = name AND parent_object_id = @OrgTableObjectId; 22 | 23 | DECLARE @TriggerCode NVARCHAR(MAX); 24 | SELECT @TriggerCode = m.definition 25 | FROM sys.sql_modules m 26 | WHERE m.object_id = @TriggerObjectId; 27 | 28 | IF (@TriggerCode IS NULL) 29 | BEGIN 30 | RAISERROR('%s is not a trigger on %s', 16, 10, @TriggerName, @TableName); 31 | END; 32 | 33 | EXEC tSQLt.RemoveObject @ObjectName = @FullTriggerName, @NewName = @NewNameOfOriginalTrigger OUTPUT; 34 | 35 | EXEC(@TriggerCode); 36 | 37 | EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @FullTriggerName, @ObjectType = N'TRIGGER', @NewNameOfOriginalObject = @NewNameOfOriginalTrigger; 38 | END; 39 | ---Build- 40 | GO 41 | 42 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertEmptyTable.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertEmptyTable') IS NOT NULL DROP PROCEDURE tSQLt.AssertEmptyTable; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.AssertEmptyTable 5 | @TableName NVARCHAR(MAX), 6 | @Message NVARCHAR(MAX) = '' 7 | AS 8 | BEGIN 9 | EXEC tSQLt.AssertObjectExists @TableName; 10 | 11 | DECLARE @FullName NVARCHAR(MAX); 12 | IF(OBJECT_ID(@TableName) IS NULL AND OBJECT_ID('tempdb..'+@TableName) IS NOT NULL) 13 | BEGIN 14 | SET @FullName = CASE WHEN LEFT(@TableName,1) = '[' THEN @TableName ELSE QUOTENAME(@TableName)END; 15 | END; 16 | ELSE 17 | BEGIN 18 | SET @FullName = tSQLt.Private_GetQuotedFullName(OBJECT_ID(@TableName)); 19 | END; 20 | 21 | DECLARE @cmd NVARCHAR(MAX); 22 | DECLARE @exists INT; 23 | SET @cmd = 'SELECT @exists = CASE WHEN EXISTS(SELECT 1 FROM '+@FullName+') THEN 1 ELSE 0 END;' 24 | EXEC sp_executesql @cmd,N'@exists INT OUTPUT', @exists OUTPUT; 25 | 26 | IF(@exists = 1) 27 | BEGIN 28 | DECLARE @TableToText NVARCHAR(MAX); 29 | EXEC tSQLt.TableToText @TableName = @FullName,@txt = @TableToText OUTPUT; 30 | DECLARE @Msg NVARCHAR(MAX); 31 | SET @Msg = @FullName + ' was not empty:' + CHAR(13) + CHAR(10)+ @TableToText; 32 | EXEC tSQLt.Fail @Message,@Msg; 33 | END 34 | END -------------------------------------------------------------------------------- /Source/tSQLt.AssertEqualsString.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertEqualsString') IS NOT NULL DROP PROCEDURE tSQLt.AssertEqualsString; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.AssertEqualsString 6 | @Expected NVARCHAR(MAX), 7 | @Actual NVARCHAR(MAX), 8 | @Message NVARCHAR(MAX) = '' 9 | AS 10 | BEGIN 11 | IF ((@Expected = @Actual) OR (@Actual IS NULL AND @Expected IS NULL)) 12 | RETURN 0; 13 | 14 | DECLARE @Msg NVARCHAR(MAX); 15 | SELECT @Msg = CHAR(13)+CHAR(10)+ 16 | 'Expected: ' + ISNULL('<'+@Expected+'>', 'NULL') + 17 | CHAR(13)+CHAR(10)+ 18 | 'but was : ' + ISNULL('<'+@Actual+'>', 'NULL'); 19 | EXEC tSQLt.Fail @Message, @Msg; 20 | END; 21 | GO 22 | ---Build- 23 | GO -------------------------------------------------------------------------------- /Source/tSQLt.AssertLike.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('[tSQLt].[AssertLike]') IS NOT NULL DROP PROCEDURE [tSQLt].[AssertLike]; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE [tSQLt].[AssertLike] 6 | @ExpectedPattern NVARCHAR(MAX), 7 | @Actual NVARCHAR(MAX), 8 | @Message NVARCHAR(MAX) = '' 9 | AS 10 | BEGIN 11 | IF (LEN(@ExpectedPattern) > 4000) 12 | BEGIN 13 | RAISERROR ('@ExpectedPattern may not exceed 4000 characters.', 16, 10); 14 | END; 15 | 16 | IF ((@Actual LIKE @ExpectedPattern) OR (@Actual IS NULL AND @ExpectedPattern IS NULL)) 17 | BEGIN 18 | RETURN 0; 19 | END 20 | 21 | DECLARE @Msg NVARCHAR(MAX); 22 | SELECT @Msg = CHAR(13) + CHAR(10) + 'Expected: <' + ISNULL(@ExpectedPattern, 'NULL') + '>' + 23 | CHAR(13) + CHAR(10) + ' but was: <' + ISNULL(@Actual, 'NULL') + '>'; 24 | EXEC tSQLt.Fail @Message, @Msg; 25 | END; 26 | GO 27 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertNotEquals.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertNotEquals') IS NOT NULL DROP PROCEDURE tSQLt.AssertNotEquals; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.AssertNotEquals 5 | @Expected SQL_VARIANT, 6 | @Actual SQL_VARIANT, 7 | @Message NVARCHAR(MAX) = '' 8 | AS 9 | BEGIN 10 | IF (@Expected = @Actual) 11 | OR (@Expected IS NULL AND @Actual IS NULL) 12 | BEGIN 13 | DECLARE @Msg NVARCHAR(MAX); 14 | SET @Msg = 'Expected actual value to not ' + 15 | COALESCE('equal <' + tSQLt.Private_SqlVariantFormatter(@Expected)+'>', 'be NULL') + 16 | '.'; 17 | EXEC tSQLt.Fail @Message,@Msg; 18 | END; 19 | RETURN 0; 20 | END; 21 | ---Build- 22 | GO 23 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertObjectDoesNotExist.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertObjectDoesNotExist') IS NOT NULL DROP PROCEDURE tSQLt.AssertObjectDoesNotExist; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.AssertObjectDoesNotExist 5 | @ObjectName NVARCHAR(MAX), 6 | @Message NVARCHAR(MAX) = '' 7 | AS 8 | BEGIN 9 | DECLARE @Msg NVARCHAR(MAX); 10 | IF OBJECT_ID(@ObjectName) IS NOT NULL 11 | OR(@ObjectName LIKE '#%' AND OBJECT_ID('tempdb..'+@ObjectName) IS NOT NULL) 12 | BEGIN 13 | SELECT @Msg = '''' + @ObjectName + ''' does exist!'; 14 | EXEC tSQLt.Fail @Message,@Msg; 15 | END; 16 | END; 17 | ---Build- 18 | GO 19 | 20 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertObjectExists.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertObjectExists') IS NOT NULL DROP PROCEDURE tSQLt.AssertObjectExists; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.AssertObjectExists 5 | @ObjectName NVARCHAR(MAX), 6 | @Message NVARCHAR(MAX) = '' 7 | AS 8 | BEGIN 9 | DECLARE @Msg NVARCHAR(MAX); 10 | IF(@ObjectName LIKE '#%') 11 | BEGIN 12 | IF OBJECT_ID('tempdb..'+@ObjectName) IS NULL 13 | BEGIN 14 | SELECT @Msg = '''' + COALESCE(@ObjectName, 'NULL') + ''' does not exist'; 15 | EXEC tSQLt.Fail @Message, @Msg; 16 | RETURN 1; 17 | END; 18 | END 19 | ELSE 20 | BEGIN 21 | IF OBJECT_ID(@ObjectName) IS NULL 22 | BEGIN 23 | SELECT @Msg = '''' + COALESCE(@ObjectName, 'NULL') + ''' does not exist'; 24 | EXEC tSQLt.Fail @Message, @Msg; 25 | RETURN 1; 26 | END; 27 | END; 28 | RETURN 0; 29 | END; 30 | ---Build- 31 | GO 32 | 33 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertStringIn.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertStringIn') IS NOT NULL DROP PROCEDURE tSQLt.AssertStringIn; 2 | GO 3 | ---Build+ 4 | GO 5 | IF NOT(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(MAX)) LIKE '9.%') 6 | BEGIN 7 | EXEC(' 8 | CREATE PROCEDURE tSQLt.AssertStringIn 9 | @Expected tSQLt.AssertStringTable READONLY, 10 | @Actual NVARCHAR(MAX), 11 | @Message NVARCHAR(MAX) = '''' 12 | AS 13 | BEGIN 14 | IF(NOT EXISTS(SELECT 1 FROM @Expected WHERE value = @Actual)) 15 | BEGIN 16 | DECLARE @ExpectedMessage NVARCHAR(MAX); 17 | SELECT value INTO #ExpectedSet FROM @Expected; 18 | EXEC tSQLt.TableToText @TableName = ''#ExpectedSet'', @OrderBy = ''value'',@txt = @ExpectedMessage OUTPUT; 19 | SET @ExpectedMessage = ISNULL(''<''+@Actual+''>'',''NULL'')+CHAR(13)+CHAR(10)+''is not in''+CHAR(13)+CHAR(10)+@ExpectedMessage; 20 | EXEC tSQLt.Fail @Message, @ExpectedMessage; 21 | END; 22 | END; 23 | '); 24 | END; 25 | GO 26 | ---Build- 27 | GO 28 | 29 | 30 | -------------------------------------------------------------------------------- /Source/tSQLt.AssertStringTable.udt.sql: -------------------------------------------------------------------------------- 1 | IF TYPE_ID('tSQLt.AssertStringTable') IS NOT NULL DROP TYPE tSQLt.AssertStringTable; 2 | GO 3 | ---Build+ 4 | GO 5 | IF NOT(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(MAX)) LIKE '9.%') 6 | BEGIN 7 | EXEC('CREATE TYPE tSQLt.AssertStringTable AS TABLE(value NVARCHAR(MAX));'); 8 | END; 9 | GO 10 | ---Build- 11 | GO 12 | -------------------------------------------------------------------------------- /Source/tSQLt.CaptureOutputLog.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.CaptureOutputLog') IS NOT NULL DROP TABLE tSQLt.CaptureOutputLog; 2 | ---Build+ 3 | CREATE TABLE tSQLt.CaptureOutputLog ( 4 | Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, 5 | OutputText NVARCHAR(MAX) 6 | ); 7 | ---Build- 8 | -------------------------------------------------------------------------------- /Source/tSQLt.EnableExternalAccess.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.EnableExternalAccess') IS NOT NULL DROP PROCEDURE tSQLt.EnableExternalAccess; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.EnableExternalAccess 6 | @try BIT = 0, 7 | @enable BIT = 1 8 | AS 9 | BEGIN 10 | IF((SELECT HostPlatform FROM tSQLt.Info()) = 'Linux') 11 | BEGIN 12 | IF(@try = 0) 13 | BEGIN 14 | RAISERROR('tSQLt.EnableExternalAccess is not supported on Linux.',16,10); 15 | END; 16 | RETURN -1; 17 | END; 18 | BEGIN TRY 19 | IF @enable = 1 20 | BEGIN 21 | EXEC('ALTER ASSEMBLY tSQLtCLR WITH PERMISSION_SET = EXTERNAL_ACCESS;'); 22 | END 23 | ELSE 24 | BEGIN 25 | EXEC('ALTER ASSEMBLY tSQLtCLR WITH PERMISSION_SET = SAFE;'); 26 | END 27 | END TRY 28 | BEGIN CATCH 29 | IF(@try = 0) 30 | BEGIN 31 | DECLARE @Message NVARCHAR(4000); 32 | SET @Message = 'The attempt to ' + 33 | CASE WHEN @enable = 1 THEN 'enable' ELSE 'disable' END + 34 | ' tSQLt features requiring EXTERNAL_ACCESS failed' + 35 | ': '+ERROR_MESSAGE(); 36 | RAISERROR(@Message,16,10); 37 | END; 38 | RETURN -1; 39 | END CATCH; 40 | RETURN 0; 41 | END; 42 | GO 43 | ---Build- 44 | GO 45 | -------------------------------------------------------------------------------- /Source/tSQLt.ExpectException.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.ExpectException') IS NOT NULL DROP PROCEDURE tSQLt.ExpectException; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.ExpectException 5 | @ExpectedMessage NVARCHAR(MAX) = NULL, 6 | @ExpectedSeverity INT = NULL, 7 | @ExpectedState INT = NULL, 8 | @Message NVARCHAR(MAX) = NULL, 9 | @ExpectedMessagePattern NVARCHAR(MAX) = NULL, 10 | @ExpectedErrorNumber INT = NULL 11 | AS 12 | BEGIN 13 | IF(EXISTS(SELECT 1 FROM #ExpectException WHERE ExpectException = 1)) 14 | BEGIN 15 | DELETE #ExpectException; 16 | RAISERROR('Each test can only contain one call to tSQLt.ExpectException.',16,10); 17 | END; 18 | 19 | INSERT INTO #ExpectException(ExpectException, ExpectedMessage, ExpectedSeverity, ExpectedState, ExpectedMessagePattern, ExpectedErrorNumber, FailMessage) 20 | VALUES(1, @ExpectedMessage, @ExpectedSeverity, @ExpectedState, @ExpectedMessagePattern, @ExpectedErrorNumber, @Message); 21 | END; 22 | ---Build- 23 | GO 24 | -------------------------------------------------------------------------------- /Source/tSQLt.ExpectNoException.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.ExpectNoException') IS NOT NULL DROP PROCEDURE tSQLt.ExpectNoException; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.ExpectNoException 5 | @Message NVARCHAR(MAX) = NULL 6 | AS 7 | BEGIN 8 | IF(EXISTS(SELECT 1 FROM #ExpectException WHERE ExpectException = 0)) 9 | BEGIN 10 | DELETE #ExpectException; 11 | RAISERROR('Each test can only contain one call to tSQLt.ExpectNoException.',16,10); 12 | END; 13 | IF(EXISTS(SELECT 1 FROM #ExpectException WHERE ExpectException = 1)) 14 | BEGIN 15 | DELETE #ExpectException; 16 | RAISERROR('tSQLt.ExpectNoException cannot follow tSQLt.ExpectException inside a single test.',16,10); 17 | END; 18 | 19 | INSERT INTO #ExpectException(ExpectException, FailMessage) 20 | VALUES(0, @Message); 21 | END; 22 | ---Build- 23 | GO 24 | -------------------------------------------------------------------------------- /Source/tSQLt.FakeFunction.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.FakeFunction') IS NOT NULL DROP PROCEDURE tSQLt.FakeFunction; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.FakeFunction 6 | @FunctionName NVARCHAR(MAX), 7 | @FakeFunctionName NVARCHAR(MAX) = NULL, 8 | @FakeDataSource NVARCHAR(MAX) = NULL 9 | 10 | AS 11 | BEGIN 12 | DECLARE @FunctionObjectId INT; 13 | DECLARE @FakeFunctionObjectId INT; 14 | DECLARE @IsScalarFunction BIT; 15 | DECLARE @NewNameOfOriginalFunction NVARCHAR(MAX); 16 | 17 | EXEC tSQLt.Private_ValidateObjectsCompatibleWithFakeFunction 18 | @FunctionName = @FunctionName, 19 | @FakeFunctionName = @FakeFunctionName, 20 | @FakeDataSource = @FakeDataSource, 21 | @FunctionObjectId = @FunctionObjectId OUT, 22 | @FakeFunctionObjectId = @FakeFunctionObjectId OUT, 23 | @IsScalarFunction = @IsScalarFunction OUT; 24 | 25 | EXEC tSQLt.RemoveObject 26 | @ObjectName = @FunctionName, 27 | @NewName = @NewNameOfOriginalFunction OUTPUT; 28 | 29 | EXEC tSQLt.Private_CreateFakeFunction 30 | @FunctionName = @FunctionName, 31 | @FakeFunctionName = @FakeFunctionName, 32 | @FakeDataSource = @FakeDataSource, 33 | @FunctionObjectId = @FunctionObjectId, 34 | @FakeFunctionObjectId = @FakeFunctionObjectId, 35 | @IsScalarFunction = @IsScalarFunction; 36 | 37 | EXEC tSQLt.Private_MarktSQLtTempObject 38 | @ObjectName = @FunctionName, 39 | @ObjectType = N'FUNCTION', 40 | @NewNameOfOriginalObject = @NewNameOfOriginalFunction; 41 | 42 | END; 43 | GO 44 | -------------------------------------------------------------------------------- /Source/tSQLt.FriendlySQLServerVersion.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.FriendlySQLServerVersion') IS NOT NULL DROP FUNCTION tSQLt.FriendlySQLServerVersion; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.FriendlySQLServerVersion(@ProductVersion NVARCHAR(128)) 6 | /* Important: Do not rename the @ProductVersion parameter! */ 7 | RETURNS TABLE 8 | AS 9 | RETURN 10 | /* Important: Do not rename the @ProductVersion parameter! */ 11 | /*StartSnip*/ 12 | SELECT 13 | @ProductVersion ProductVersion, 14 | CASE 15 | WHEN SSV.Major = '16' THEN '2022' 16 | WHEN SSV.Major = '15' THEN '2019' 17 | WHEN SSV.Major = '14' THEN '2017' 18 | WHEN SSV.Major = '13' THEN '2016' 19 | WHEN SSV.Major = '12' THEN '2014' 20 | WHEN SSV.Major = '11' THEN '2012' 21 | WHEN SSV.Major = '10' AND SSV.Minor IN ('50','5') THEN '2008R2' 22 | WHEN SSV.Major = '10' AND SSV.Minor IN ('00','0') THEN '2008' 23 | END FriendlyVersion 24 | /*EndSnip*/ 25 | /* Important: Do not rename the @ProductVersion parameter! */ 26 | FROM tSQLt.Private_SplitSqlVersion(@ProductVersion) AS SSV; 27 | GO 28 | ---Build- 29 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Info.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Info') IS NOT NULL DROP FUNCTION tSQLt.Info; 2 | -- This will not work if executed outside of the build! 3 | GO 4 | ---Build+ 5 | GO 6 | CREATE FUNCTION tSQLt.Info() 7 | RETURNS TABLE 8 | AS 9 | RETURN 10 | SELECT Version = '$LATEST-BUILD-NUMBER$', 11 | ClrVersion = (SELECT tSQLt.Private::Info()), 12 | ClrSigningKey = (SELECT tSQLt.Private::SigningKey()), 13 | InstalledOnSqlVersion = (SELECT SqlVersion FROM tSQLt.Private_InstallationInfo()), 14 | V.SqlVersion, 15 | V.SqlBuild, 16 | V.SqlEdition, 17 | V.HostPlatform 18 | FROM 19 | ( 20 | SELECT CAST(PSSV.Major+'.'+PSSV.Minor AS NUMERIC(10,2)) AS SqlVersion, 21 | CAST(PSSV.Build+'.'+PSSV.Revision AS NUMERIC(10,2)) AS SqlBuild, 22 | PSV.Edition AS SqlEdition, 23 | PHP.host_platform AS HostPlatform 24 | FROM tSQLt.Private_SqlVersion() AS PSV 25 | CROSS APPLY tSQLt.Private_SplitSqlVersion(PSV.ProductVersion) AS PSSV 26 | CROSS JOIN tSQLt.Private_HostPlatform AS PHP 27 | )V; 28 | GO 29 | ---Build- 30 | GO 31 | SELECT * FROM tSQLt.Info() AS I; 32 | -------------------------------------------------------------------------------- /Source/tSQLt.InstallExternalAccessKey.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.InstallExternalAccessKey') IS NOT NULL DROP PROCEDURE tSQLt.InstallExternalAccessKey; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.InstallExternalAccessKey 6 | AS 7 | BEGIN 8 | EXEC tSQLt.Private_Print @Message='tSQLt.InstallExternalAccessKey is deprecated. Please use tSQLt.InstallAssemblyKey instead.'; 9 | EXEC tSQLt.InstallAssemblyKey; 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | -------------------------------------------------------------------------------- /Source/tSQLt.LogCapturedOutput.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.LogCapturedOutput') IS NOT NULL DROP PROCEDURE tSQLt.LogCapturedOutput; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.LogCapturedOutput @text NVARCHAR(MAX) 5 | AS 6 | BEGIN 7 | INSERT INTO tSQLt.CaptureOutputLog (OutputText) VALUES (@text); 8 | END; 9 | ---Build- -------------------------------------------------------------------------------- /Source/tSQLt.NewTestClass.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.NewTestClass') IS NOT NULL DROP PROCEDURE tSQLt.NewTestClass; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.NewTestClass 5 | @ClassName NVARCHAR(MAX) 6 | AS 7 | BEGIN 8 | BEGIN TRY 9 | EXEC tSQLt.Private_DisallowOverwritingNonTestSchema @ClassName; 10 | 11 | EXEC tSQLt.DropClass @ClassName = @ClassName; 12 | 13 | DECLARE @QuotedClassName NVARCHAR(MAX); 14 | SELECT @QuotedClassName = tSQLt.Private_QuoteClassNameForNewTestClass(@ClassName); 15 | 16 | EXEC ('CREATE SCHEMA ' + @QuotedClassName); 17 | EXEC tSQLt.Private_MarkSchemaAsTestClass @QuotedClassName; 18 | END TRY 19 | BEGIN CATCH 20 | DECLARE @ErrMsg NVARCHAR(MAX);SET @ErrMsg = ERROR_MESSAGE() + ' (Error originated in ' + ERROR_PROCEDURE() + ')'; 21 | DECLARE @ErrSvr INT;SET @ErrSvr = ERROR_SEVERITY(); 22 | 23 | RAISERROR(@ErrMsg, @ErrSvr, 10); 24 | END CATCH; 25 | END; 26 | ---Build- 27 | GO 28 | -------------------------------------------------------------------------------- /Source/tSQLt.PrepareServer.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.PrepareServer') IS NOT NULL DROP PROCEDURE tSQLt.PrepareServer; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.PrepareServer 6 | AS 7 | BEGIN 8 | EXEC tSQLt.Private_EnableCLR; 9 | EXEC tSQLt.InstallAssemblyKey; 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_AssertNoSideEffects.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_AssertNoSideEffects') IS NOT NULL DROP PROCEDURE tSQLt.Private_AssertNoSideEffects; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_AssertNoSideEffects 6 | @BeforeExecutionObjectSnapshotTableName NVARCHAR(MAX), 7 | @AfterExecutionObjectSnapshotTableName NVARCHAR(MAX), 8 | @TestResult NVARCHAR(MAX) OUTPUT, 9 | @TestMsg NVARCHAR(MAX) OUTPUT 10 | AS 11 | BEGIN 12 | DECLARE @Command NVARCHAR(MAX) = (SELECT Command FROM tSQLt.Private_AssertNoSideEffects_GenerateCommand(@BeforeExecutionObjectSnapshotTableName, @AfterExecutionObjectSnapshotTableName)); 13 | EXEC tSQLt.Private_CleanUpCmdHandler @CleanUpCmd=@Command, @TestResult=@TestResult OUT, @TestMsg=@TestMsg OUT; 14 | END; 15 | GO 16 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_AssertNoSideEffects_GenerateCommand.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_AssertNoSideEffects_GenerateCommand') IS NOT NULL DROP FUNCTION tSQLt.Private_AssertNoSideEffects_GenerateCommand; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_AssertNoSideEffects_GenerateCommand( 6 | @BeforeExecutionObjectSnapshotTableName NVARCHAR(MAX), 7 | @AfterExecutionObjectSnapshotTableName NVARCHAR(MAX) 8 | ) 9 | RETURNS TABLE 10 | AS 11 | RETURN 12 | SELECT ' 13 | SELECT * INTO #ObjectDiscrepancies 14 | FROM( 15 | (SELECT ''Deleted'' [Status], B.* FROM '+@BeforeExecutionObjectSnapshotTableName+' AS B EXCEPT SELECT ''Deleted'' [Status],* FROM '+@AfterExecutionObjectSnapshotTableName+' AS A) 16 | UNION ALL 17 | (SELECT ''Added'' [Status], A.* FROM '+@AfterExecutionObjectSnapshotTableName+' AS A EXCEPT SELECT ''Added'' [Status], * FROM '+@BeforeExecutionObjectSnapshotTableName+' AS B) 18 | )D; 19 | IF(EXISTS(SELECT 1 FROM #ObjectDiscrepancies)) 20 | BEGIN 21 | DECLARE @TableToText NVARCHAR(MAX); 22 | EXEC tSQLt.TableToText @TableName = ''#ObjectDiscrepancies'' ,@txt = @TableToText OUTPUT, @OrderBy = ''[Status] ASC, SchemaName ASC, ObjectName ASC''; 23 | RAISERROR(''After the test executed, there were unexpected or missing objects in the database: %s'',16,10,@TableToText); 24 | END;' Command; 25 | GO 26 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CleanTestResult.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CleanTestResult') IS NOT NULL DROP PROCEDURE tSQLt.Private_CleanTestResult; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_CleanTestResult 6 | AS 7 | BEGIN 8 | DELETE FROM tSQLt.TestResult; 9 | END; 10 | GO 11 | ---Build- 12 | GO 13 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CleanUp.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CleanUp') IS NOT NULL DROP PROCEDURE tSQLt.Private_CleanUp; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_CleanUp 6 | @FullTestName NVARCHAR(MAX), 7 | @Result NVARCHAR(MAX) OUTPUT, 8 | @ErrorMsg NVARCHAR(MAX) OUTPUT 9 | AS 10 | BEGIN 11 | 12 | EXEC tSQLt.Private_CleanUpCmdHandler 13 | @CleanUpCmd = 'EXEC tSQLt.Private_NoTransactionHandleTables @Action=''Reset'';', 14 | @TestResult = @Result OUT, 15 | @TestMsg = @ErrorMsg OUT, 16 | @ResultInCaseOfError = 'FATAL'; 17 | 18 | EXEC tSQLt.Private_CleanUpCmdHandler 19 | @CleanUpCmd = 'EXEC tSQLt.UndoTestDoubles @Force = 0;', 20 | @TestResult = @Result OUT, 21 | @TestMsg = @ErrorMsg OUT, 22 | @ResultInCaseOfError = 'Abort'; 23 | 24 | END; 25 | GO 26 | ---Build- 27 | GO 28 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CleanUpCmdHandler.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CleanUpCmdHandler') IS NOT NULL DROP PROCEDURE tSQLt.Private_CleanUpCmdHandler; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_CleanUpCmdHandler 5 | @CleanUpCmd NVARCHAR(MAX), 6 | @TestResult NVARCHAR(MAX) OUTPUT, 7 | @TestMsg NVARCHAR(MAX) OUTPUT, 8 | @ResultInCaseOfError NVARCHAR(MAX) = 'Error' 9 | AS 10 | BEGIN 11 | BEGIN TRY 12 | EXEC(@CleanUpCmd); 13 | END TRY 14 | BEGIN CATCH 15 | DECLARE @NewMsg NVARCHAR(MAX) = 'Error during clean up: (' + (SELECT FormattedError FROM tSQLt.Private_GetFormattedErrorInfo()) + ')'; 16 | SELECT @TestMsg = Message, @TestResult = Result FROM tSQLt.Private_HandleMessageAndResult(@TestMsg /*PrevMsg*/, @TestResult /*PrevResult*/, @NewMsg /*NewMsg*/, @ResultInCaseOfError /*NewResult*/); 17 | END CATCH; 18 | END; 19 | GO 20 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CompareTablesFailIfUnequalRowsExists.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CompareTablesFailIfUnequalRowsExists') IS NOT NULL DROP PROCEDURE tSQLt.Private_CompareTablesFailIfUnequalRowsExists; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_CompareTablesFailIfUnequalRowsExists 6 | @UnequalRowsExist INT, 7 | @ResultTable NVARCHAR(MAX), 8 | @ResultColumn NVARCHAR(MAX), 9 | @ColumnList NVARCHAR(MAX), 10 | @FailMsg NVARCHAR(MAX) 11 | AS 12 | BEGIN 13 | IF @UnequalRowsExist > 0 14 | BEGIN 15 | DECLARE @TableToTextResult NVARCHAR(MAX); 16 | DECLARE @OutputColumnList NVARCHAR(MAX); 17 | SELECT @OutputColumnList = '[_m_],' + @ColumnList; 18 | EXEC tSQLt.TableToText @TableName = @ResultTable, @OrderBy = @ResultColumn, @PrintOnlyColumnNameAliasList = @OutputColumnList, @txt = @TableToTextResult OUTPUT; 19 | 20 | DECLARE @Message NVARCHAR(MAX); 21 | SELECT @Message = @FailMsg + CHAR(13) + CHAR(10); 22 | 23 | EXEC tSQLt.Fail @Message, @TableToTextResult; 24 | END; 25 | END 26 | GO 27 | ---Build- 28 | GO 29 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_Configurations.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_Configurations') IS NOT NULL DROP TABLE tSQLt.Private_Configurations; 2 | ---Build+ 3 | CREATE TABLE tSQLt.Private_Configurations ( 4 | Name NVARCHAR(100) PRIMARY KEY CLUSTERED, 5 | Value SQL_VARIANT 6 | ); 7 | ---Build- 8 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CreateFakeOfTable.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CreateFakeOfTable') IS NOT NULL DROP PROCEDURE tSQLt.Private_CreateFakeOfTable; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_CreateFakeOfTable 5 | @SchemaName NVARCHAR(MAX), 6 | @TableName NVARCHAR(MAX), 7 | @OrigTableObjectId INT, 8 | @Identity BIT, 9 | @ComputedColumns BIT, 10 | @Defaults BIT 11 | AS 12 | BEGIN 13 | DECLARE @cmd NVARCHAR(MAX) = 14 | (SELECT CreateTableStatement 15 | FROM tSQLt.Private_CreateFakeTableStatement(@OrigTableObjectId, @SchemaName+'.'+@TableName,@Identity,@ComputedColumns,@Defaults,0)); 16 | EXEC (@cmd); 17 | END; 18 | ---Build- 19 | GO 20 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CreateFakeTableStatement.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CreateFakeTableStatement') IS NOT NULL DROP FUNCTION tSQLt.Private_CreateFakeTableStatement; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_CreateFakeTableStatement( 6 | @OriginalTableObjectId INT, 7 | @FullFakeTableName NVARCHAR(MAX), 8 | @Identity BIT, 9 | @ComputedColumns BIT, 10 | @Defaults BIT, 11 | @PreserveNOTNULL BIT 12 | ) 13 | RETURNS TABLE 14 | AS 15 | RETURN 16 | SELECT 17 | 'CREATE TABLE ' + @FullFakeTableName + '(' + STUFF(Cols,1,1,'') + ')' CreateTableStatement, 18 | 'CREATE TYPE ' + @FullFakeTableName + ' AS TABLE(' + STUFF(Cols,1,1,'') + ')' CreateTableTypeStatement 19 | FROM 20 | ( 21 | SELECT 22 | ( 23 | SELECT 24 | ',' + 25 | QUOTENAME(name) + 26 | cc.ColumnDefinition + 27 | dc.DefaultDefinition + 28 | id.IdentityDefinition + 29 | CASE WHEN cc.IsComputedColumn = 1 OR id.IsIdentityColumn = 1 30 | THEN '' 31 | ELSE CASE WHEN @PreserveNOTNULL = 1 AND c.is_nullable = 0 THEN ' NOT NULL' ELSE ' NULL' END 32 | END 33 | FROM sys.columns c 34 | CROSS APPLY tSQLt.Private_GetDataTypeOrComputedColumnDefinition(c.user_type_id, c.max_length, c.precision, c.scale, c.collation_name, c.object_id, c.column_id, @ComputedColumns) cc 35 | CROSS APPLY tSQLt.Private_GetDefaultConstraintDefinition(c.object_id, c.column_id, @Defaults) AS dc 36 | CROSS APPLY tSQLt.Private_GetIdentityDefinition(c.object_id, c.column_id, @Identity) AS id 37 | WHERE object_id = @OriginalTableObjectId 38 | ORDER BY column_id 39 | FOR XML PATH(''), TYPE 40 | ).value('.', 'NVARCHAR(MAX)') 41 | ) AS X(Cols); 42 | GO 43 | ---Build- 44 | GO 45 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CreateProcedureSpy.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CreateProcedureSpy') IS NOT NULL DROP PROCEDURE tSQLt.Private_CreateProcedureSpy; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_CreateProcedureSpy 5 | @ProcedureObjectId INT, 6 | @OriginalProcedureName NVARCHAR(MAX), 7 | @LogTableName NVARCHAR(MAX), 8 | @CommandToExecute NVARCHAR(MAX) = NULL 9 | AS 10 | BEGIN 11 | 12 | RETURN; 13 | END; 14 | ---Build- 15 | GO 16 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_CreateResultTableForCompareTables.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CreateResultTableForCompareTables') IS NOT NULL DROP PROCEDURE tSQLt.Private_CreateResultTableForCompareTables; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_CreateResultTableForCompareTables 6 | @ResultTable NVARCHAR(MAX), 7 | @ResultColumn NVARCHAR(MAX), 8 | @BaseTable NVARCHAR(MAX) 9 | AS 10 | BEGIN 11 | DECLARE @Cmd NVARCHAR(MAX); 12 | SET @Cmd = ' 13 | SELECT TOP(0) ''>'' AS ' + @ResultColumn + ', Expected.* INTO ' + @ResultTable + ' 14 | FROM ' + @BaseTable + ' AS Expected RIGHT JOIN ' + @BaseTable + ' AS X ON 1=0; ' 15 | EXEC(@Cmd); 16 | EXEC tSQLt.Private_MarktSQLtTempObject @ObjectName = @ResultTable, @ObjectType = N'TABLE'; 17 | END 18 | GO 19 | ---Build- 20 | GO 21 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_DisallowOverwritingNonTestSchema.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_DisallowOverwritingNonTestSchema') IS NOT NULL DROP PROCEDURE tSQLt.Private_DisallowOverwritingNonTestSchema; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_DisallowOverwritingNonTestSchema 5 | @ClassName NVARCHAR(MAX) 6 | AS 7 | BEGIN 8 | IF SCHEMA_ID(@ClassName) IS NOT NULL AND tSQLt.Private_IsTestClass(@ClassName) = 0 9 | BEGIN 10 | RAISERROR('Attempted to execute tSQLt.NewTestClass on ''%s'' which is an existing schema but not a test class', 16, 10, @ClassName); 11 | END 12 | END; 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_EnableCLR.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_EnableCLR') IS NOT NULL DROP PROCEDURE tSQLt.Private_EnableCLR; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_EnableCLR 6 | AS 7 | BEGIN 8 | EXEC master.sys.sp_configure @configname='clr enabled', @configvalue = 1; 9 | RECONFIGURE; 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetAssemblyKeyBytes.mdl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetAssemblyKeyBytes') IS NOT NULL DROP PROCEDURE tSQLt.Private_GetAssemblyKeyBytes; 2 | GO 3 | 4 | ---Build+ 5 | GO 6 | CREATE PROCEDURE tSQLt.Private_GetAssemblyKeyBytes 7 | @AssemblyKeyBytes VARBINARY(MAX) = NULL OUTPUT, 8 | @AssemblyKeyThumbPrint VARBINARY(MAX) = NULL OUTPUT 9 | AS 10 | SELECT @AssemblyKeyBytes = 11 | 0x000000 12 | ,@AssemblyKeyThumbPrint = 0x000001 ; 13 | GO 14 | ---Build- 15 | GO 16 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetCommaSeparatedColumnList.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetCommaSeparatedColumnList') IS NOT NULL DROP FUNCTION tSQLt.Private_GetCommaSeparatedColumnList; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_GetCommaSeparatedColumnList (@Table NVARCHAR(MAX), @ExcludeColumn NVARCHAR(MAX)) 6 | RETURNS NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | RETURN STUFF(( 10 | SELECT ',' + CASE WHEN system_type_id = TYPE_ID('timestamp') THEN ';TIMESTAMP columns are unsupported!;' ELSE QUOTENAME(name) END 11 | FROM sys.columns 12 | WHERE object_id = OBJECT_ID(@Table) 13 | AND name <> @ExcludeColumn 14 | ORDER BY column_id 15 | FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)') 16 | ,1, 1, ''); 17 | 18 | END; 19 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetConfiguration.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetConfiguration') IS NOT NULL DROP FUNCTION tSQLt.Private_GetConfiguration; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_GetConfiguration( 6 | @Name NVARCHAR(100) 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT PC.Name, 12 | PC.Value 13 | FROM tSQLt.Private_Configurations AS PC 14 | WHERE PC.Name = @Name; 15 | GO 16 | ---Build- 17 | GO 18 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetDataTypeOrComputedColumnDefinition.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetDataTypeOrComputedColumnDefinition') IS NOT NULL DROP FUNCTION tSQLt.Private_GetDataTypeOrComputedColumnDefinition; 2 | ---Build+ 3 | GO 4 | CREATE FUNCTION tSQLt.Private_GetDataTypeOrComputedColumnDefinition(@UserTypeId INT, @MaxLength INT, @Precision INT, @Scale INT, @CollationName NVARCHAR(MAX), @ObjectId INT, @ColumnId INT, @ReturnDetails BIT) 5 | RETURNS TABLE 6 | AS 7 | RETURN SELECT 8 | COALESCE(cc.IsComputedColumn, 0) AS IsComputedColumn, 9 | COALESCE(cc.ComputedColumnDefinition, GFTN.TypeName) AS ColumnDefinition 10 | FROM (SELECT @UserTypeId, @MaxLength, @Precision, @Scale, @CollationName, @ObjectId, @ColumnId, @ReturnDetails) 11 | AS V(UserTypeId, MaxLength, Precision, Scale, CollationName, ObjectId, ColumnId, ReturnDetails) 12 | CROSS APPLY tSQLt.Private_GetFullTypeName(V.UserTypeId, V.MaxLength, V.Precision, V.Scale, V.CollationName) AS GFTN 13 | LEFT JOIN (SELECT 1 AS IsComputedColumn, 14 | ' AS '+ cci.definition + CASE WHEN cci.is_persisted = 1 THEN ' PERSISTED' ELSE '' END AS ComputedColumnDefinition, 15 | cci.object_id, 16 | cci.column_id 17 | FROM sys.computed_columns cci 18 | )cc 19 | ON cc.object_id = V.ObjectId 20 | AND cc.column_id = V.ColumnId 21 | AND V.ReturnDetails = 1; 22 | ---Build- 23 | GO 24 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetDefaultConstraintDefinition.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetDefaultConstraintDefinition') IS NOT NULL DROP FUNCTION tSQLt.Private_GetDefaultConstraintDefinition; 2 | ---Build+ 3 | GO 4 | CREATE FUNCTION tSQLt.Private_GetDefaultConstraintDefinition(@ObjectId INT, @ColumnId INT, @ReturnDetails BIT) 5 | RETURNS TABLE 6 | AS 7 | RETURN SELECT 8 | COALESCE(IsDefault, 0) AS IsDefault, 9 | COALESCE(DefaultDefinition, '') AS DefaultDefinition 10 | FROM (SELECT 1) X(X) 11 | LEFT JOIN (SELECT 1 AS IsDefault,' DEFAULT '+ definition AS DefaultDefinition,parent_object_id,parent_column_id 12 | FROM sys.default_constraints 13 | )dc 14 | ON dc.parent_object_id = @ObjectId 15 | AND dc.parent_column_id = @ColumnId 16 | AND @ReturnDetails = 1; 17 | ---Build- 18 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetFormattedErrorInfo.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetFormattedErrorInfo') IS NOT NULL DROP FUNCTION tSQLt.Private_GetFormattedErrorInfo; 2 | GO 3 | ---Build+ 4 | CREATE FUNCTION tSQLt.Private_GetFormattedErrorInfo() 5 | RETURNS TABLE 6 | AS 7 | RETURN 8 | SELECT 'Message: ' + ISNULL(ERROR_MESSAGE(),'') + ' | Procedure: ' + ISNULL(ERROR_PROCEDURE(),'') + ISNULL(' (' + CAST(ERROR_LINE() AS NVARCHAR(MAX)) + ')','') + ' | Severity, State: ' + ISNULL(CAST(ERROR_SEVERITY() AS NVARCHAR(MAX)),'') + ', ' + ISNULL(CAST(ERROR_STATE() AS NVARCHAR(MAX)), '') + ' | Number: ' + ISNULL(CAST(ERROR_NUMBER() AS NVARCHAR(MAX)), '') AS FormattedError; 9 | GO 10 | ---Build- 11 | GO 12 | BEGIN TRY 13 | SELECT CAST('A' AS INT); 14 | END TRY 15 | BEGIN CATCH 16 | SELECT FormattedError FROM tSQLt.Private_GetFormattedErrorInfo(); 17 | END CATCH -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetFullTypeName.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetFullTypeName') IS NOT NULL DROP FUNCTION tSQLt.Private_GetFullTypeName; 2 | ---Build+ 3 | GO 4 | CREATE FUNCTION tSQLt.Private_GetFullTypeName(@TypeId INT, @Length INT, @Precision INT, @Scale INT, @CollationName NVARCHAR(MAX)) 5 | RETURNS TABLE 6 | AS 7 | RETURN SELECT X.SchemaName + '.' + X.Name + X.Suffix + X.Collation AS TypeName, X.SchemaName, X.Name, X.Suffix, X.is_table_type AS IsTableType 8 | FROM( 9 | SELECT QUOTENAME(SCHEMA_NAME(T.schema_id)) SchemaName, QUOTENAME(T.name) Name, 10 | CASE WHEN T.max_length = -1 11 | THEN '' 12 | WHEN @Length = -1 13 | THEN '(MAX)' 14 | WHEN T.name LIKE 'n%char' 15 | THEN '(' + CAST(@Length / 2 AS NVARCHAR) + ')' 16 | WHEN T.name LIKE '%char' OR T.name LIKE '%binary' 17 | THEN '(' + CAST(@Length AS NVARCHAR) + ')' 18 | WHEN T.name IN ('decimal', 'numeric') 19 | THEN '(' + CAST(@Precision AS NVARCHAR) + ',' + CAST(@Scale AS NVARCHAR) + ')' 20 | WHEN T.name IN ('datetime2', 'datetimeoffset', 'time') 21 | THEN '(' + CAST(@Scale AS NVARCHAR) + ')' 22 | ELSE '' 23 | END Suffix, 24 | CASE WHEN @CollationName IS NULL OR T.is_user_defined = 1 THEN '' 25 | ELSE ' COLLATE ' + @CollationName 26 | END Collation, 27 | T.is_table_type 28 | FROM tSQLt.Private_SysTypes AS T WHERE T.user_type_id = @TypeId 29 | )X; 30 | ---Build- 31 | GO 32 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetIdentityDefinition.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetIdentityDefinition') IS NOT NULL DROP FUNCTION tSQLt.Private_GetIdentityDefinition; 2 | GO 3 | ---Build+ 4 | CREATE FUNCTION tSQLt.Private_GetIdentityDefinition(@ObjectId INT, @ColumnId INT, @ReturnDetails BIT) 5 | RETURNS TABLE 6 | AS 7 | RETURN SELECT 8 | COALESCE(IsIdentity, 0) AS IsIdentityColumn, 9 | COALESCE(IdentityDefinition, '') AS IdentityDefinition 10 | FROM (SELECT 1) X(X) 11 | LEFT JOIN (SELECT 1 AS IsIdentity, 12 | ' IDENTITY(' + CAST(seed_value AS NVARCHAR(MAX)) + ',' + CAST(increment_value AS NVARCHAR(MAX)) + ')' AS IdentityDefinition, 13 | object_id, 14 | column_id 15 | FROM sys.identity_columns 16 | ) AS id 17 | ON id.object_id = @ObjectId 18 | AND id.column_id = @ColumnId 19 | AND @ReturnDetails = 1; 20 | ---Build- 21 | GO 22 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_GetSQLProductMajorVersion.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_GetSQLProductMajorVersion') IS NOT NULL DROP PROCEDURE tSQLt.Private_GetSQLProductMajorVersion; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_GetSQLProductMajorVersion 6 | AS 7 | RETURN CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(MAX)),4) AS INT); 8 | GO 9 | ---Build- 10 | GO 11 | DECLARE @Version INT; 12 | EXEC @Version = tSQLt.Private_GetSQLProductMajorVersion; 13 | PRINT 'SQL Major Version: '+CAST(@Version as NVARCHAR(MAX)); 14 | 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_HandleMessageAndResult.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_HandleMessageAndResult') IS NOT NULL DROP FUNCTION tSQLt.Private_HandleMessageAndResult; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_HandleMessageAndResult ( 6 | @PrevMessage NVARCHAR(MAX), 7 | @PrevResult NVARCHAR(MAX), 8 | @NewMessage NVARCHAR(MAX), 9 | @NewResult NVARCHAR(MAX) 10 | ) 11 | RETURNS TABLE 12 | AS 13 | RETURN 14 | SELECT CASE WHEN ISNULL(@PrevMessage,'') NOT LIKE '%[^ '+CHAR(9)+']%' AND @PrevResult = 'Success' THEN '' 15 | ELSE CASE WHEN @PrevMessage NOT LIKE '%[^ '+CHAR(9)+']%' THEN '' ELSE ISNULL(@PrevMessage,'') END+' [Result: '+ 16 | CASE WHEN @PrevResult NOT LIKE '%[^ '+CHAR(9)+']%' THEN '' ELSE ISNULL(@PrevResult,'') END+'] || ' 17 | END+ 18 | CASE WHEN @NewMessage NOT LIKE '%[^ '+CHAR(9)+']%' THEN '' ELSE ISNULL(@NewMessage,'') END Message, 19 | (SELECT TOP(1) Result FROM tSQLt.Private_Results WHERE Result IN (@PrevResult, @NewResult) ORDER BY Severity DESC) Result; 20 | GO 21 | ---Build- 22 | GO 23 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_HostPlatform.stub.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_HostPlatform') IS NOT NULL DROP VIEW tSQLt.Private_HostPlatform; 2 | GO 3 | ---Build+ 4 | CREATE VIEW tSQLt.Private_HostPlatform AS SELECT CAST('Windows' AS NVARCHAR(256)) AS host_platform; 5 | ---Build- 6 | GO 7 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_HostPlatform.svw.sql: -------------------------------------------------------------------------------- 1 | GO 2 | ---Build+ 3 | IF((SELECT SqlVersion FROM tSQLt.Info())>=14) 4 | BEGIN 5 | EXEC('CREATE OR ALTER VIEW tSQLt.Private_HostPlatform AS SELECT host_platform FROM sys.dm_os_host_info;'); 6 | END; 7 | ---Build- 8 | GO 9 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_Init.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_Init') IS NOT NULL DROP PROCEDURE tSQLt.Private_Init; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_Init 6 | AS 7 | BEGIN 8 | EXEC tSQLt.Private_CleanTestResult; 9 | 10 | DECLARE @enable BIT; SET @enable = 1; 11 | DECLARE @version_match BIT;SET @version_match = 0; 12 | BEGIN TRY 13 | EXEC sys.sp_executesql N'SELECT @r = CASE WHEN I.Version = I.ClrVersion THEN 1 ELSE 0 END FROM tSQLt.Info() AS I;',N'@r BIT OUTPUT',@version_match OUT; 14 | END TRY 15 | BEGIN CATCH 16 | RAISERROR('Cannot access CLR. Assembly might be in an invalid state. Try running EXEC tSQLt.EnableExternalAccess @enable = 0; or reinstalling tSQLt.',16,10); 17 | RETURN; 18 | END CATCH; 19 | SELECT @version_match = CASE WHEN I.SqlVersion = I.InstalledOnSqlVersion THEN 1 ELSE 0 END FROM tSQLt.Info() AS I WHERE @version_match = 1; 20 | IF(@version_match = 0 OR EXISTS(SELECT 1 FROM tSQLt.Private_Seize)) 21 | BEGIN 22 | RAISERROR('tSQLt is in an invalid state. Please reinstall tSQLt.',16,10); 23 | RETURN; 24 | END; 25 | 26 | IF(NOT EXISTS(SELECT 1 FROM tSQLt.Info() WHERE SqlEdition = 'SQL Azure')) 27 | BEGIN 28 | EXEC tSQLt.EnableExternalAccess @enable = @enable, @try = 1; 29 | END; 30 | END; 31 | GO 32 | ---Build- 33 | GO 34 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_InstallationInfo.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_CreateInstallationInfo') IS NOT NULL DROP PROCEDURE tSQLt.Private_CreateInstallationInfo; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_CreateInstallationInfo 6 | -- Created as a stored procedure to make it testable. 7 | AS 8 | BEGIN 9 | DECLARE @cmd NVARCHAR(MAX); 10 | SELECT 11 | @cmd = 'ALTER FUNCTION tSQLt.Private_InstallationInfo() RETURNS TABLE AS RETURN SELECT CAST('+ 12 | CAST(I.SqlVersion AS NVARCHAR(MAX))+ 13 | ' AS NUMERIC(10,2)) AS SqlVersion;' 14 | FROM tSQLt.Info() AS I; 15 | 16 | EXEC(@cmd); 17 | END; 18 | GO 19 | EXEC tSQLt.Private_CreateInstallationInfo; 20 | GO 21 | ---Build- 22 | GO 23 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_InstallationInfo.stub.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_InstallationInfo') IS NOT NULL DROP FUNCTION tSQLt.Private_InstallationInfo; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_InstallationInfo() 6 | RETURNS TABLE 7 | AS 8 | RETURN SELECT CAST(NULL AS NUMERIC(10,2)) AS SqlVersion; 9 | GO 10 | ---Build- 11 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_ListTestAnnotations.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_ListTestAnnotations') IS NOT NULL DROP FUNCTION tSQLt.Private_ListTestAnnotations; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_ListTestAnnotations( 6 | @TestObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | GAL.AnnotationNo, 13 | REPLACE(GAL.Annotation,'''','''''') AS EscapedAnnotationString, 14 | 'tSQLt.'+GAL.Annotation AS Annotation 15 | FROM tSQLt.Private_GetAnnotationList(OBJECT_DEFINITION(@TestObjectId))AS GAL; 16 | GO 17 | ---Build- 18 | GO 19 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_Lock.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_Lock') IS NOT NULL DROP TABLE tSQLt.Private_Lock; 2 | GO 3 | --DECLARE @Lock INT = (SELECT COUNT(1) FROM tSQLt.Lock AS L WITH(TABLOCKX)); 4 | ---Build+ 5 | GO 6 | CREATE TABLE tSQLt.Private_Lock(X BIT CONSTRAINT [PK:tSQLt.Private_Lock] PRIMARY KEY CONSTRAINT [CHK:tSQLt.Private_Lock(X)] CHECK(X=13)); 7 | GO 8 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_MarkObjectBeforeRename.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_MarkObjectBeforeRename') IS NOT NULL DROP PROCEDURE tSQLt.Private_MarkObjectBeforeRename; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_MarkObjectBeforeRename 5 | @SchemaName NVARCHAR(MAX), 6 | @OriginalName NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | INSERT INTO tSQLt.Private_RenamedObjectLog (ObjectId, OriginalName) 10 | VALUES (OBJECT_ID(@SchemaName + '.' + @OriginalName), @OriginalName); 11 | END; 12 | ---Build- 13 | GO 14 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_MarkSchemaAsTestClass.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_MarkSchemaAsTestClass') IS NOT NULL DROP PROCEDURE tSQLt.Private_MarkSchemaAsTestClass; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_MarkSchemaAsTestClass 5 | @QuotedClassName NVARCHAR(MAX) 6 | AS 7 | BEGIN 8 | SET NOCOUNT ON; 9 | 10 | DECLARE @UnquotedClassName NVARCHAR(MAX); 11 | 12 | SELECT @UnquotedClassName = name 13 | FROM sys.schemas 14 | WHERE QUOTENAME(name) = @QuotedClassName; 15 | 16 | EXEC sp_addextendedproperty @name = N'tSQLt.TestClass', 17 | @value = 1, 18 | @level0type = 'SCHEMA', 19 | @level0name = @UnquotedClassName; 20 | 21 | INSERT INTO tSQLt.Private_NewTestClassList(ClassName) 22 | SELECT @UnquotedClassName 23 | WHERE NOT EXISTS 24 | ( 25 | SELECT * 26 | FROM tSQLt.Private_NewTestClassList AS NTC 27 | WITH(UPDLOCK,ROWLOCK,HOLDLOCK) 28 | WHERE NTC.ClassName = @UnquotedClassName 29 | ); 30 | END; 31 | ---Build- 32 | GO 33 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_NewTestClassList.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_NewTestClassList') IS NOT NULL DROP TABLE tSQLt.Private_NewTestClassList; 2 | ---Build+ 3 | CREATE TABLE tSQLt.Private_NewTestClassList ( 4 | ClassName NVARCHAR(450) PRIMARY KEY CLUSTERED 5 | ); 6 | ---Build- 7 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_NoTransactionHandleTables.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_NoTransactionHandleTables') IS NOT NULL DROP PROCEDURE tSQLt.Private_NoTransactionHandleTables; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_NoTransactionHandleTables 6 | @Action NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | DECLARE @cmd NVARCHAR(MAX) = ( 10 | SELECT 'EXEC tSQLt.Private_NoTransactionHandleTable @Action = '''+@Action+''', @FullTableName = '''+X.Name+''', @TableAction = '''+X.Action+''';' 11 | FROM tSQLt.Private_NoTransactionTableAction X 12 | WHERE X.Action <> 'Ignore' 13 | FOR XML PATH(''),TYPE 14 | ).value('.','NVARCHAR(MAX)'); 15 | EXEC(@cmd); 16 | END; 17 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_NoTransactionTableAction.view.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_NoTransactionTableAction') IS NOT NULL DROP VIEW tSQLt.Private_NoTransactionTableAction; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE VIEW tSQLt.Private_NoTransactionTableAction 6 | AS 7 | SELECT CAST(Name AS NVARCHAR(MAX)) Name, CAST(Action AS NVARCHAR(MAX)) Action 8 | FROM( 9 | VALUES('[tSQLt].[Private_NewTestClassList]','Hide'), 10 | ('[tSQLt].[Run_LastExecution]','Hide'), 11 | ('[tSQLt].[Private_Configurations]','Restore'), 12 | ('[tSQLt].[CaptureOutputLog]','Truncate'), 13 | ('[tSQLt].[Private_RenamedObjectLog]','Ignore'), 14 | ('[tSQLt].[Private_Seize]','Ignore'), 15 | ('[tSQLt].[Private_Seize_NoTruncate]','Ignore'), 16 | ('[tSQLt].[TestResult]','Restore') 17 | )X(Name, Action); 18 | GO 19 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_PrepareFakeFunctionOutputTable.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_PrepareFakeFunctionOutputTable') IS NOT NULL 2 | DROP PROCEDURE tSQLt.Private_PrepareFakeFunctionOutputTable; 3 | GO 4 | ---Build+ 5 | CREATE PROCEDURE tSQLt.Private_PrepareFakeFunctionOutputTable 6 | @FakeDataSource NVARCHAR(MAX), 7 | @OutputTable NVARCHAR(MAX) OUTPUT 8 | AS 9 | BEGIN 10 | SET @OutputTable = tSQLt.Private::CreateUniqueObjectName(); 11 | 12 | IF ( LOWER(LTRIM(@FakeDataSource)) LIKE 'select%' 13 | AND OBJECT_ID(@FakeDataSource) IS NULL 14 | ) 15 | BEGIN 16 | SET @FakeDataSource = N'('+ @FakeDataSource + N') a'; 17 | END; 18 | 19 | DECLARE @Cmd NVARCHAR(MAX) = N'SELECT * INTO ' + @OutputTable + N' FROM ' + @FakeDataSource; 20 | 21 | EXEC sp_executesql @Cmd; 22 | 23 | RETURN 0; 24 | END; 25 | ---Build- 26 | GO 27 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_QuoteClassNameForNewTestClass.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_QuoteClassNameForNewTestClass') IS NOT NULL DROP FUNCTION tSQLt.Private_QuoteClassNameForNewTestClass; 2 | GO 3 | ---Build+ 4 | CREATE FUNCTION tSQLt.Private_QuoteClassNameForNewTestClass(@ClassName NVARCHAR(MAX)) 5 | RETURNS NVARCHAR(MAX) 6 | AS 7 | BEGIN 8 | RETURN 9 | CASE WHEN @ClassName LIKE '[[]%]' THEN @ClassName 10 | ELSE QUOTENAME(@ClassName) 11 | END; 12 | END; 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RemoveSchemaBinding.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RemoveSchemaBinding') IS NOT NULL DROP PROCEDURE tSQLt.Private_RemoveSchemaBinding; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_RemoveSchemaBinding 6 | @object_id INT 7 | AS 8 | BEGIN 9 | DECLARE @cmd NVARCHAR(MAX); 10 | SELECT @cmd = tSQLt.[Private]::GetAlterStatementWithoutSchemaBinding(SM.definition) 11 | FROM sys.sql_modules AS SM 12 | WHERE SM.object_id = @object_id; 13 | EXEC(@cmd); 14 | END; 15 | GO 16 | ---Build- 17 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RemoveSchemaBoundReferences.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RemoveSchemaBoundReferences') IS NOT NULL DROP PROCEDURE tSQLt.Private_RemoveSchemaBoundReferences; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_RemoveSchemaBoundReferences 6 | @object_id INT 7 | AS 8 | BEGIN 9 | DECLARE @cmd NVARCHAR(MAX); 10 | SELECT @cmd = 11 | ( 12 | SELECT 13 | 'EXEC tSQLt.Private_RemoveSchemaBoundReferences @object_id = '+STR(SED.referencing_id)+';'+ 14 | 'EXEC tSQLt.Private_RemoveSchemaBinding @object_id = '+STR(SED.referencing_id)+';' 15 | FROM 16 | ( 17 | SELECT DISTINCT SEDI.referencing_id,SEDI.referenced_id 18 | FROM sys.sql_expression_dependencies AS SEDI 19 | WHERE SEDI.is_schema_bound_reference = 1 20 | ) AS SED 21 | WHERE SED.referenced_id = @object_id 22 | FOR XML PATH(''),TYPE 23 | ).value('.','NVARCHAR(MAX)'); 24 | EXEC(@cmd); 25 | END; 26 | GO 27 | ---Build- 28 | GO 29 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RenameObject.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RenameObject') IS NOT NULL DROP PROCEDURE tSQLt.Private_RenameObject; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_RenameObject 5 | @SchemaName NVARCHAR(MAX), 6 | @ObjectName NVARCHAR(MAX), 7 | @NewName NVARCHAR(MAX) 8 | AS 9 | BEGIN 10 | DECLARE @RenameCmd NVARCHAR(MAX); 11 | SET @RenameCmd = 'EXEC sp_rename ''' + 12 | REPLACE(@SchemaName + '.' + @ObjectName, '''', '''''') + ''', ''' + 13 | REPLACE(@NewName, '''', '''''') + ''',''OBJECT'';'; 14 | 15 | EXEC tSQLt.SuppressOutput @RenameCmd; 16 | END; 17 | ---Build- 18 | GO 19 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RenameObjectToUniqueName.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RenameObjectToUniqueName') IS NOT NULL DROP PROCEDURE tSQLt.Private_RenameObjectToUniqueName; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_RenameObjectToUniqueName 5 | @SchemaName NVARCHAR(MAX), 6 | @ObjectName NVARCHAR(MAX), 7 | @NewName NVARCHAR(MAX) = NULL OUTPUT 8 | AS 9 | BEGIN 10 | SET @NewName=ISNULL(@NewName, tSQLt.Private::CreateUniqueObjectName()); 11 | 12 | EXEC tSQLt.Private_MarkObjectBeforeRename @SchemaName, @ObjectName; 13 | 14 | EXEC tSQLt.Private_RenameObject @SchemaName, 15 | @ObjectName, 16 | @NewName; 17 | 18 | END; 19 | ---Build- 20 | GO 21 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RenameObjectToUniqueNameUsingObjectId.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RenameObjectToUniqueNameUsingObjectId') IS NOT NULL DROP PROCEDURE tSQLt.Private_RenameObjectToUniqueNameUsingObjectId; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_RenameObjectToUniqueNameUsingObjectId 5 | @ObjectId INT, 6 | @NewName NVARCHAR(MAX) = NULL OUTPUT 7 | AS 8 | BEGIN 9 | DECLARE @SchemaName NVARCHAR(MAX); 10 | DECLARE @ObjectName NVARCHAR(MAX); 11 | 12 | SELECT @SchemaName = QUOTENAME(OBJECT_SCHEMA_NAME(@ObjectId)), @ObjectName = QUOTENAME(OBJECT_NAME(@ObjectId)); 13 | 14 | EXEC tSQLt.Private_RenameObjectToUniqueName @SchemaName,@ObjectName, @NewName OUTPUT; 15 | END; 16 | ---Build- 17 | GO 18 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_RenamedObjectLog.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_RenamedObjectLog') IS NOT NULL DROP TABLE tSQLt.Private_RenamedObjectLog; 2 | GO 3 | ---Build+ 4 | CREATE TABLE tSQLt.Private_RenamedObjectLog ( 5 | Id INT IDENTITY(1,1) CONSTRAINT PK__Private_RenamedObjectLog__Id PRIMARY KEY CLUSTERED, 6 | ObjectId INT NOT NULL, 7 | OriginalName NVARCHAR(MAX) NOT NULL 8 | ); 9 | ---Build- 10 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_ResetNewTestClassList.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_ResetNewTestClassList') IS NOT NULL DROP PROCEDURE tSQLt.Private_ResetNewTestClassList; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_ResetNewTestClassList 6 | AS 7 | BEGIN 8 | SET NOCOUNT ON; 9 | DELETE FROM tSQLt.Private_NewTestClassList; 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_Results.view.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_Results') IS NOT NULL DROP VIEW tSQLt.Private_Results; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE VIEW tSQLt.Private_Results 6 | AS 7 | SELECT CAST(Severity AS INT) Severity,CAST(Result AS NVARCHAR(MAX)) Result 8 | FROM( 9 | VALUES(1, 'Success') 10 | , 11 | (2, 'Skipped'), 12 | (3, 'Failure'), 13 | (4, 'Error'), 14 | (5, 'Abort'), 15 | (6, 'FATAL') 16 | )X(Severity, Result); 17 | GO 18 | 19 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_Seize.tbl.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_Seize_NoTruncate') IS NOT NULL DROP TABLE tSQLt.Private_Seize_NoTruncate; 2 | IF OBJECT_ID('tSQLt.Private_Seize') IS NOT NULL DROP TABLE tSQLt.Private_Seize; 3 | GO 4 | ---Build+ 5 | GO 6 | CREATE TABLE tSQLt.Private_Seize( 7 | Kaput BIT CONSTRAINT [Private_Seize:PK] PRIMARY KEY CONSTRAINT [Private_Seize:CHK] CHECK(Kaput=1) 8 | ); 9 | GO 10 | CREATE TABLE tSQLt.Private_Seize_NoTruncate( 11 | NoTruncate BIT CONSTRAINT [Private_Seize_NoTruncate(NoTruncate):FK] FOREIGN KEY REFERENCES tSQLt.Private_Seize(Kaput) 12 | ); 13 | GO 14 | CREATE TRIGGER tSQLt.Private_Seize_Stop ON tSQLt.Private_Seize INSTEAD OF DELETE,UPDATE 15 | AS 16 | BEGIN 17 | RAISERROR('This is a private table that you should not mess with!',16,10); 18 | END; 19 | GO 20 | 21 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_SetConfiguration.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SetConfiguration') IS NOT NULL DROP PROCEDURE tSQLt.Private_SetConfiguration; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_SetConfiguration 6 | @Name NVARCHAR(100), 7 | @Value SQL_VARIANT 8 | AS 9 | BEGIN 10 | IF(EXISTS(SELECT 1 FROM tSQLt.Private_Configurations WITH(ROWLOCK,UPDLOCK) WHERE Name = @Name)) 11 | BEGIN 12 | UPDATE tSQLt.Private_Configurations SET 13 | Value = @Value 14 | WHERE Name = @Name; 15 | END; 16 | ELSE 17 | BEGIN 18 | INSERT tSQLt.Private_Configurations(Name,Value) 19 | VALUES(@Name,@Value); 20 | END; 21 | END; 22 | GO 23 | ---Build- 24 | GO 25 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_SkipTestAnnotationHelper.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SkipTestAnnotationHelper') IS NOT NULL DROP PROCEDURE tSQLt.Private_SkipTestAnnotationHelper; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_SkipTestAnnotationHelper 6 | @SkipReason NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | INSERT INTO #SkipTest VALUES(@SkipReason); 10 | END; 11 | GO 12 | ---Build- 13 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_SplitSqlVersion.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SplitSqlVersion') IS NOT NULL DROP FUNCTION tSQLt.Private_SplitSqlVersion; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_SplitSqlVersion(@ProductVersion NVARCHAR(128)) 6 | /* Important: Do not rename the @ProducVersion parameter! */ 7 | RETURNS TABLE 8 | AS 9 | RETURN 10 | /* Important: Do not rename the @ProducVersion parameter! */ 11 | /*StartSnip*/ 12 | SELECT REVERSE(PARSENAME(X.RP,1)) Major, 13 | REVERSE(PARSENAME(X.RP,2)) Minor, 14 | REVERSE(PARSENAME(X.RP,3)) Build, 15 | REVERSE(PARSENAME(X.RP,4)) Revision 16 | FROM (SELECT REVERSE(@ProductVersion)) AS X(RP) 17 | /*EndSnip*/ 18 | ; 19 | /* Important: Do not rename the @ProducVersion parameter! */ 20 | GO 21 | ---Build- 22 | GO 23 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_SqlVariantFormatter.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SqlVariantFormatter') IS NOT NULL DROP FUNCTION tSQLt.Private_SqlVariantFormatter; 2 | GO 3 | ---Build+ 4 | CREATE FUNCTION tSQLt.Private_SqlVariantFormatter(@Value SQL_VARIANT) 5 | RETURNS NVARCHAR(MAX) 6 | AS 7 | BEGIN 8 | RETURN CASE UPPER(CAST(SQL_VARIANT_PROPERTY(@Value,'BaseType')AS sysname)) 9 | WHEN 'FLOAT' THEN CONVERT(NVARCHAR(MAX),@Value,2) 10 | WHEN 'REAL' THEN CONVERT(NVARCHAR(MAX),@Value,1) 11 | WHEN 'MONEY' THEN CONVERT(NVARCHAR(MAX),@Value,2) 12 | WHEN 'SMALLMONEY' THEN CONVERT(NVARCHAR(MAX),@Value,2) 13 | WHEN 'DATE' THEN CONVERT(NVARCHAR(MAX),@Value,126) 14 | WHEN 'DATETIME' THEN CONVERT(NVARCHAR(MAX),@Value,126) 15 | WHEN 'DATETIME2' THEN CONVERT(NVARCHAR(MAX),@Value,126) 16 | WHEN 'DATETIMEOFFSET' THEN CONVERT(NVARCHAR(MAX),@Value,126) 17 | WHEN 'SMALLDATETIME' THEN CONVERT(NVARCHAR(MAX),@Value,126) 18 | WHEN 'TIME' THEN CONVERT(NVARCHAR(MAX),@Value,126) 19 | WHEN 'BINARY' THEN CONVERT(NVARCHAR(MAX),@Value,1) 20 | WHEN 'VARBINARY' THEN CONVERT(NVARCHAR(MAX),@Value,1) 21 | ELSE CAST(@Value AS NVARCHAR(MAX)) 22 | END; 23 | END 24 | ---Build- 25 | GO 26 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_SqlVersion.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SqlVersion') IS NOT NULL DROP FUNCTION tSQLt.Private_SqlVersion; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_SqlVersion() 6 | RETURNS TABLE 7 | AS 8 | RETURN 9 | SELECT 10 | CAST(SERVERPROPERTY('ProductVersion')AS NVARCHAR(128)) ProductVersion, 11 | CAST(SERVERPROPERTY('Edition')AS NVARCHAR(128)) Edition 12 | GO 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_SysIndexes.svw.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SysIndexes') IS NOT NULL DROP VIEW tSQLt.Private_SysIndexes; 2 | GO 3 | ---Build+ 4 | IF((SELECT SqlVersion FROM tSQLt.Info())>9) 5 | BEGIN 6 | EXEC('CREATE VIEW tSQLt.Private_SysIndexes AS SELECT * FROM sys.indexes;'); 7 | END 8 | ELSE 9 | BEGIN 10 | EXEC('CREATE VIEW tSQLt.Private_SysIndexes AS SELECT *,0 AS has_filter,'''' AS filter_definition FROM sys.indexes;'); 11 | END; 12 | ---Build- 13 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Private_SysTypes.svw.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_SysTypes') IS NOT NULL DROP VIEW tSQLt.Private_SysTypes; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE VIEW tSQLt.Private_SysTypes AS SELECT * FROM sys.types AS T; 6 | GO 7 | IF((SELECT SqlVersion FROM tSQLt.Info())=9) 8 | BEGIN 9 | EXEC('ALTER VIEW tSQLt.Private_SysTypes AS SELECT *,0 is_table_type FROM sys.types AS T;'); 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_TableToTextColumnListAdjustWidth.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_TableToTextColumnListAdjustWidth') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListAdjustWidth; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_TableToTextColumnListAdjustWidth( 6 | @tmpObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | ( 13 | SELECT 14 | ',C'+NN+' = CASE WHEN LEN(C.C'+NN+')>L.MCW '+ 15 | 'THEN LEFT(C.C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C.C'+NN+',(L.MCW-5)/2) '+ 16 | 'ELSE LEFT(C.C'+NN+'+REPLICATE('' '','+ 17 | 'CASE WHEN L.MCW < L.L'+NN+' '+ 18 | 'THEN L.MCW ELSE L.L'+NN+' END - '+ 19 | 'LEN(C.C'+NN+')),'+ 20 | 'CASE WHEN L.MCW < L.L'+NN+' '+ 21 | 'THEN L.MCW ELSE L.L'+NN+' END) '+ 22 | 'END' 23 | FROM( 24 | SELECT 25 | column_id,RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) NN 26 | FROM sys.columns 27 | WHERE object_id = @tmpObjectId 28 | AND column_id>1 29 | )X 30 | ORDER BY column_id 31 | FOR XML PATH(''),TYPE 32 | ).value('.','NVARCHAR(MAX)') [ColumnList]; 33 | GO 34 | ---Build- 35 | GO 36 | --+REPLICATE(' ',LEN(C'+NN+')) 37 | --',C'+NN+' = CASE WHEN LEN(C'+NN+')>L.MCW THEN LEFT(C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C'+NN+',(L.MCW-5)/2) ELSE LEFT(C'+NN+'+REPLICATE(' ',CASE WHEN L.MCW < L.L'+NN+' THEN L.MCW ELSE L.L'+NN+' END - LEN(C'+NN+')),9) END' -------------------------------------------------------------------------------- /Source/tSQLt.Private_TableToTextColumnListMaxLenNumbered.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_TableToTextColumnListMaxLenNumbered') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListMaxLenNumbered; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_TableToTextColumnListMaxLenNumbered( 6 | @tmpObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | ( 13 | SELECT 14 | ',MAX(LEN(''.''+C'+ 15 | RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4)+ 16 | '+''.''))-2 L'+ 17 | RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) 18 | FROM sys.columns 19 | WHERE object_id = @tmpObjectId 20 | AND column_id>1 21 | ORDER BY column_id 22 | FOR XML PATH(''),TYPE 23 | ).value('.','NVARCHAR(MAX)') [ColumnList]; 24 | GO 25 | ---Build- 26 | GO 27 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_TableToTextColumnListQuotedAndNumbered.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_TableToTextColumnListQuotedAndNumbered') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListQuotedAndNumbered; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_TableToTextColumnListQuotedAndNumbered( 6 | @tmpObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | ( 13 | SELECT 14 | ',CAST('+ 15 | QUOTENAME(name,'''')+ 16 | ' AS NVARCHAR(MAX)) C'+ 17 | RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) 18 | FROM sys.columns 19 | WHERE object_id = @tmpObjectId 20 | AND column_id>1 21 | ORDER BY column_id 22 | FOR XML PATH(''),TYPE 23 | ).value('.','NVARCHAR(MAX)') [ColumnList]; 24 | GO 25 | ---Build- 26 | GO 27 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_TableToTextColumnListSeparatorLine.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_TableToTextColumnListSeparatorLine') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextColumnListSeparatorLine; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_TableToTextColumnListSeparatorLine( 6 | @tmpObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | ( 13 | SELECT 14 | ',REPLICATE(''-'','+ 15 | 'CASE WHEN L.MCW < L.L'+NN+' '+ 16 | 'THEN L.MCW ELSE L.L'+NN+' END)' 17 | FROM( 18 | SELECT 19 | column_id,RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4) NN 20 | FROM sys.columns 21 | WHERE object_id = @tmpObjectId 22 | AND column_id>1 23 | )X 24 | ORDER BY column_id 25 | FOR XML PATH(''),TYPE 26 | ).value('.','NVARCHAR(MAX)') [ColumnList]; 27 | GO 28 | ---Build- 29 | GO 30 | --+REPLICATE(' ',LEN(C'+NN+')) 31 | --',C'+NN+' = CASE WHEN LEN(C'+NN+')>L.MCW THEN LEFT(C'+NN+',(L.MCW-5)/2)+''<...>''+RIGHT(C'+NN+',(L.MCW-5)/2) ELSE LEFT(C'+NN+'+REPLICATE(' ',CASE WHEN L.MCW < L.L'+NN+' THEN L.MCW ELSE L.L'+NN+' END - LEN(C'+NN+')),9) END' -------------------------------------------------------------------------------- /Source/tSQLt.Private_TableToTextNumberedColumnsWithSeparator.sfn.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_TableToTextNumberedColumnsWithSeparator') IS NOT NULL DROP FUNCTION tSQLt.Private_TableToTextNumberedColumnsWithSeparator; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE FUNCTION tSQLt.Private_TableToTextNumberedColumnsWithSeparator( 6 | @tmpObjectId INT 7 | ) 8 | RETURNS TABLE 9 | AS 10 | RETURN 11 | SELECT 12 | ( 13 | SELECT 14 | 'sep+C'+ 15 | RIGHT(CAST(10002+ROW_NUMBER()OVER(ORDER BY column_id) AS NVARCHAR(MAX)),4)+ 16 | '+' 17 | FROM sys.columns 18 | WHERE object_id = @tmpObjectId 19 | AND column_id>1 20 | ORDER BY column_id 21 | FOR XML PATH(''),TYPE 22 | ).value('.','NVARCHAR(MAX)') [ColumnList]; 23 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_UndoSingleTestDouble.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_UndoSingleTestDouble') IS NOT NULL DROP PROCEDURE tSQLt.Private_UndoSingleTestDouble; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_UndoSingleTestDouble 6 | @SchemaName NVARCHAR(MAX), 7 | @ObjectName NVARCHAR(MAX), 8 | @OriginalName NVARCHAR(MAX) 9 | AS 10 | BEGIN 11 | 12 | 13 | EXEC tSQLt.Private_RenameObject @SchemaName = @SchemaName, 14 | @ObjectName = @ObjectName, 15 | @NewName = @OriginalName; 16 | 17 | END; 18 | GO 19 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_ValidateFakeTableParameters.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_ValidateFakeTableParameters') IS NOT NULL DROP PROCEDURE tSQLt.Private_ValidateFakeTableParameters; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.Private_ValidateFakeTableParameters 5 | @SchemaName NVARCHAR(MAX), 6 | @OrigTableName NVARCHAR(MAX), 7 | @OrigSchemaName NVARCHAR(MAX) 8 | AS 9 | BEGIN 10 | IF @SchemaName IS NULL 11 | BEGIN 12 | DECLARE @FullName NVARCHAR(MAX); SET @FullName = @OrigTableName + COALESCE('.' + @OrigSchemaName, ''); 13 | 14 | RAISERROR ('FakeTable could not resolve the object name, ''%s''. (When calling tSQLt.FakeTable, avoid the use of the @SchemaName parameter, as it is deprecated.)', 15 | 16, 10, @FullName); 16 | END; 17 | END; 18 | ---Build- 19 | GO 20 | 21 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure') IS NOT NULL DROP PROCEDURE tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_ValidateProcedureCanBeUsedWithSpyProcedure 6 | @ProcedureName NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | IF NOT EXISTS(SELECT 1 FROM sys.procedures WHERE object_id = OBJECT_ID(@ProcedureName)) 10 | BEGIN 11 | RAISERROR('Cannot use SpyProcedure on %s because the procedure does not exist', 16, 10, @ProcedureName) WITH NOWAIT; 12 | END; 13 | 14 | IF (1020 < (SELECT COUNT(*) FROM sys.parameters WHERE object_id = OBJECT_ID(@ProcedureName))) 15 | BEGIN 16 | RAISERROR('Cannot use SpyProcedure on procedure %s because it contains more than 1020 parameters', 16, 10, @ProcedureName) WITH NOWAIT; 17 | END; 18 | END; 19 | GO 20 | 21 | 22 | -------------------------------------------------------------------------------- /Source/tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported') IS NOT NULL DROP PROCEDURE tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Private_ValidateThatAllDataTypesInTableAreSupported 6 | @ResultTable NVARCHAR(MAX), 7 | @ColumnList NVARCHAR(MAX) 8 | AS 9 | BEGIN 10 | BEGIN TRY 11 | EXEC('DECLARE @EatResult INT; SELECT @EatResult = COUNT(1) FROM ' + @ResultTable + ' GROUP BY ' + @ColumnList + ';'); 12 | END TRY 13 | BEGIN CATCH 14 | RAISERROR('The table contains a datatype that is not supported for tSQLt.AssertEqualsTable. Please refer to http://tsqlt.org/user-guide/assertions/assertequalstable/ for a list of unsupported datatypes.',16,10); 15 | END CATCH 16 | END; 17 | GO 18 | -------------------------------------------------------------------------------- /Source/tSQLt.RemoveAssemblyKey.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.RemoveAssemblyKey') IS NOT NULL DROP PROCEDURE tSQLt.RemoveAssemblyKey; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.RemoveAssemblyKey 6 | AS 7 | BEGIN 8 | IF(NOT EXISTS(SELECT * FROM sys.fn_my_permissions(NULL,'server') AS FMP WHERE FMP.permission_name = 'CONTROL SERVER')) 9 | BEGIN 10 | RAISERROR('Only principals with CONTROL SERVER permission can execute this procedure.',16,10); 11 | RETURN -1; 12 | END; 13 | 14 | DECLARE @master_sys_sp_executesql NVARCHAR(MAX); SET @master_sys_sp_executesql = 'master.sys.sp_executesql'; 15 | DECLARE @ProductMajorVersion INT; 16 | EXEC @ProductMajorVersion = tSQLt.Private_GetSQLProductMajorVersion; 17 | 18 | IF SUSER_ID('tSQLtAssemblyKey') IS NOT NULL DROP LOGIN tSQLtAssemblyKey; 19 | EXEC @master_sys_sp_executesql N'IF ASYMKEY_ID(''tSQLtAssemblyKey'') IS NOT NULL DROP ASYMMETRIC KEY tSQLtAssemblyKey;'; 20 | EXEC @master_sys_sp_executesql N'IF EXISTS(SELECT * FROM sys.assemblies WHERE name = ''tSQLtAssemblyKey'') DROP ASSEMBLY tSQLtAssemblyKey;'; 21 | 22 | DECLARE @cmd NVARCHAR(MAX); 23 | IF(@ProductMajorVersion>=14) 24 | BEGIN 25 | DECLARE @TrustedHash NVARCHAR(MAX); 26 | DECLARE @AssemblyKeyBytes VARBINARY(MAX); 27 | EXEC tSQLt.Private_GetAssemblyKeyBytes @AssemblyKeyBytes = @AssemblyKeyBytes OUT; 28 | SELECT @TrustedHash = CONVERT(NVARCHAR(MAX),HASHBYTES('SHA2_512',@AssemblyKeyBytes),1); 29 | SELECT @cmd = 30 | 'IF EXISTS(SELECT 1 FROM sys.trusted_assemblies WHERE hash = ' + @TrustedHash +' AND description = ''tSQLt Ephemeral'')'+ 31 | 'EXEC sys.sp_drop_trusted_assembly @hash = ' + @TrustedHash + ';'; 32 | EXEC master.sys.sp_executesql @cmd; 33 | END; 34 | 35 | 36 | END; 37 | GO 38 | ---Build- 39 | GO 40 | -------------------------------------------------------------------------------- /Source/tSQLt.RemoveExternalAccessKey.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.RemoveExternalAccessKey') IS NOT NULL DROP PROCEDURE tSQLt.RemoveExternalAccessKey; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.RemoveExternalAccessKey 6 | AS 7 | BEGIN 8 | EXEC tSQLt.Private_Print @Message='tSQLt.RemoveExternalAccessKey is deprecated. Please use tSQLt.RemoveAssemblyKey instead.'; 9 | EXEC tSQLt.RemoveAssemblyKey; 10 | RETURN; 11 | END; 12 | GO 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /Source/tSQLt.RemoveObject.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.RemoveObject') IS NOT NULL DROP PROCEDURE tSQLt.RemoveObject; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.RemoveObject 6 | @ObjectName NVARCHAR(MAX), 7 | @NewName NVARCHAR(MAX) = NULL OUTPUT, 8 | @IfExists INT = 0 9 | AS 10 | BEGIN 11 | DECLARE @ObjectId INT; 12 | SELECT @ObjectId = OBJECT_ID(@ObjectName); 13 | 14 | IF(@ObjectId IS NULL) 15 | BEGIN 16 | IF(@IfExists = 1) RETURN; 17 | RAISERROR('%s does not exist!',16,10,@ObjectName); 18 | END; 19 | 20 | EXEC tSQLt.Private_RenameObjectToUniqueNameUsingObjectId @ObjectId, @NewName = @NewName OUTPUT; 21 | END; 22 | GO 23 | ---Build- 24 | GO -------------------------------------------------------------------------------- /Source/tSQLt.RemoveObjectIfExists.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.RemoveObjectIfExists') IS NOT NULL DROP PROCEDURE tSQLt.RemoveObjectIfExists; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.RemoveObjectIfExists 6 | @ObjectName NVARCHAR(MAX), 7 | @NewName NVARCHAR(MAX) = NULL OUTPUT 8 | AS 9 | BEGIN 10 | EXEC tSQLt.RemoveObject @ObjectName = @ObjectName, @NewName = @NewName OUT, @IfExists = 1; 11 | END; 12 | GO -------------------------------------------------------------------------------- /Source/tSQLt.RenameClass.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.RenameClass') IS NOT NULL DROP PROCEDURE tSQLt.RenameClass; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.RenameClass 5 | @SchemaName NVARCHAR(MAX), 6 | @NewSchemaName NVARCHAR(MAX) 7 | AS 8 | BEGIN 9 | DECLARE @MigrateObjectsCommand NVARCHAR(MAX); 10 | 11 | SELECT @NewSchemaName = PARSENAME(@NewSchemaName, 1), 12 | @SchemaName = PARSENAME(@SchemaName, 1); 13 | 14 | EXEC tSQLt.NewTestClass @NewSchemaName; 15 | 16 | SELECT @MigrateObjectsCommand = ( 17 | SELECT Cmd AS [text()] FROM ( 18 | SELECT 'ALTER SCHEMA ' + QUOTENAME(@NewSchemaName) + ' TRANSFER ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(name) + ';' AS Cmd 19 | FROM sys.objects 20 | WHERE schema_id = SCHEMA_ID(@SchemaName) 21 | AND type NOT IN ('PK', 'F') 22 | UNION ALL 23 | SELECT 'ALTER SCHEMA ' + QUOTENAME(@NewSchemaName) + ' TRANSFER XML SCHEMA COLLECTION::' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(name) + ';' AS Cmd 24 | FROM sys.xml_schema_collections 25 | WHERE schema_id = SCHEMA_ID(@SchemaName) 26 | UNION ALL 27 | SELECT 'ALTER SCHEMA ' + QUOTENAME(@NewSchemaName) + ' TRANSFER TYPE::' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(name) + ';' AS Cmd 28 | FROM sys.types 29 | WHERE schema_id = SCHEMA_ID(@SchemaName) 30 | ) AS Cmds 31 | FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'); 32 | 33 | EXEC (@MigrateObjectsCommand); 34 | 35 | EXEC tSQLt.DropClass @SchemaName; 36 | END; 37 | ---Build- 38 | GO -------------------------------------------------------------------------------- /Source/tSQLt.Reset.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Reset') IS NOT NULL DROP PROCEDURE tSQLt.Reset; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Reset 6 | AS 7 | BEGIN 8 | EXEC tSQLt.Private_ResetNewTestClassList; 9 | END; 10 | GO 11 | ---Build- 12 | GO 13 | -------------------------------------------------------------------------------- /Source/tSQLt.SetSummaryError.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.SetSummaryError') IS NOT NULL DROP PROCEDURE tSQLt.SetSummaryError; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.SetSummaryError 6 | @SummaryError INT 7 | AS 8 | BEGIN 9 | IF(@SummaryError NOT IN (0,1)) 10 | BEGIN 11 | RAISERROR('@SummaryError has to be 0 or 1, but it was: %i',16,10,@SummaryError); 12 | END; 13 | EXEC tSQLt.Private_SetConfiguration @Name = 'SummaryError', @Value = @SummaryError; 14 | END; 15 | GO 16 | ---Build- 17 | GO -------------------------------------------------------------------------------- /Source/tSQLt.SetVerbose.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.SetVerbose') IS NOT NULL DROP PROCEDURE tSQLt.SetVerbose; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.SetVerbose 6 | @Verbose BIT = 1 7 | AS 8 | BEGIN 9 | EXEC tSQLt.Private_SetConfiguration @Name = 'Verbose', @Value = @Verbose; 10 | END; 11 | GO 12 | ---Build- 13 | GO 14 | -------------------------------------------------------------------------------- /Source/tSQLt.TempDropStatement.mdl.sql: -------------------------------------------------------------------------------- 1 | ---Build+ 2 | DECLARE @ClassName NVARCHAR(MAX) = 'tSQLt';/*--DROPSTATEMENT--*/ 3 | -------------------------------------------------------------------------------- /Source/tSQLt.TestClass.user.sql: -------------------------------------------------------------------------------- 1 | ---Build+ 2 | GO 3 | IF (USER_ID('tSQLt.TestClass') IS NULL) 4 | BEGIN 5 | CREATE USER [tSQLt.TestClass] WITHOUT LOGIN; 6 | END; 7 | GO 8 | ---Build- -------------------------------------------------------------------------------- /Source/tSQLt.TestClasses.view.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.TestClasses') IS NOT NULL DROP VIEW tSQLt.TestClasses; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE VIEW tSQLt.TestClasses 6 | AS 7 | SELECT s.name AS Name, s.schema_id AS SchemaId 8 | FROM sys.schemas s 9 | LEFT JOIN sys.extended_properties ep 10 | ON ep.major_id = s.schema_id 11 | WHERE ep.name = N'tSQLt.TestClass' 12 | OR s.principal_id = USER_ID('tSQLt.TestClass'); 13 | GO 14 | ---Build- 15 | -------------------------------------------------------------------------------- /Source/tSQLt.Tests.view.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Tests') IS NOT NULL DROP VIEW tSQLt.Tests; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE VIEW tSQLt.Tests 6 | AS 7 | SELECT classes.SchemaId, classes.Name AS TestClassName, 8 | procs.object_id AS ObjectId, procs.name AS Name 9 | FROM tSQLt.TestClasses classes 10 | JOIN sys.procedures procs ON classes.SchemaId = procs.schema_id 11 | WHERE LOWER(procs.name) LIKE 'test%'; 12 | GO 13 | ---Build- 14 | -------------------------------------------------------------------------------- /Source/tSQLt.Uninstall.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.Uninstall') IS NOT NULL DROP PROCEDURE tSQLt.Uninstall; 2 | GO 3 | ---Build+ 4 | GO 5 | CREATE PROCEDURE tSQLt.Uninstall 6 | AS 7 | BEGIN 8 | 9 | EXEC tSQLt.DropClass @ClassName = 'tSQLt'; 10 | 11 | IF(EXISTS(SELECT 1 FROM sys.assemblies WHERE name = 'tSQLtCLR'))DROP ASSEMBLY tSQLtCLR; 12 | 13 | IF USER_ID('tSQLt.TestClass') IS NOT NULL DROP USER [tSQLt.TestClass]; 14 | 15 | END; 16 | GO 17 | ---Build- 18 | -------------------------------------------------------------------------------- /Source/tSQLt._Footer.sql: -------------------------------------------------------------------------------- 1 | ---Build-n 2 | ---Build+ 3 | GO 4 | SET NOCOUNT ON; 5 | DECLARE @ver NVARCHAR(MAX); 6 | DECLARE @match INT; 7 | SELECT @ver = '| tSQLt Version: ' + I.Version, 8 | @match = CASE WHEN I.Version = I.ClrVersion THEN 1 ELSE 0 END 9 | FROM tSQLt.Info() AS I; 10 | SET @ver = @ver+SPACE(42-LEN(@ver))+'|'; 11 | 12 | RAISERROR('',0,1)WITH NOWAIT; 13 | RAISERROR('+-----------------------------------------+',0,1)WITH NOWAIT; 14 | RAISERROR('| |',0,1)WITH NOWAIT; 15 | RAISERROR('| Thank you for using tSQLt. |',0,1)WITH NOWAIT; 16 | RAISERROR('| |',0,1)WITH NOWAIT; 17 | RAISERROR(@ver,0,1)WITH NOWAIT; 18 | IF(@match = 0) 19 | BEGIN 20 | RAISERROR('| |',0,1)WITH NOWAIT; 21 | RAISERROR('| ERROR: mismatching CLR Version. |',0,1)WITH NOWAIT; 22 | RAISERROR('| Please download a new version of tSQLt. |',0,1)WITH NOWAIT; 23 | END 24 | RAISERROR('| |',0,1)WITH NOWAIT; 25 | RAISERROR('+-----------------------------------------+',0,1)WITH NOWAIT; 26 | -------------------------------------------------------------------------------- /Source/tSQLt._Header.sql: -------------------------------------------------------------------------------- 1 | ---Build-h 2 | ---Build+ 3 | /* 4 | Copyright 2011 tSQLt 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | DECLARE @Msg NVARCHAR(MAX);SELECT @Msg = 'Installed at '+CONVERT(NVARCHAR,GETDATE(),121);RAISERROR(@Msg,0,1); 19 | GO 20 | ---Build- -------------------------------------------------------------------------------- /Source/tSQLt.schema.sql: -------------------------------------------------------------------------------- 1 | ---Build+ 2 | IF EXISTS (SELECT 1 FROM sys.assemblies WHERE name = 'tSQLtCLR') 3 | DROP ASSEMBLY tSQLtCLR; 4 | GO 5 | 6 | CREATE SCHEMA tSQLt; 7 | GO 8 | SET QUOTED_IDENTIFIER ON; 9 | GO 10 | ---Build- 11 | -------------------------------------------------------------------------------- /Source/tSQLtCLR.mdl.sql: -------------------------------------------------------------------------------- 1 | ---Build+ 2 | GO 3 | DECLARE @cmd NVARCHAR(MAX) = ''; 4 | SET @cmd = @cmd + --<-- force NVARCHAR(MAX) 5 | 'CREATE ASSEMBLY [tSQLtCLR] AUTHORIZATION [dbo] FROM '+ 6 | '0x000000'+ 7 | ' WITH PERMISSION_SET = SAFE;'; 8 | EXEC(@cmd); 9 | GO 10 | -------------------------------------------------------------------------------- /Source/tSQLtDropBuildOrder.txt: -------------------------------------------------------------------------------- 1 | tSQLt.DropClass.ssp.sql 2 | -------------------------------------------------------------------------------- /TestUtil/BuildOrder.txt: -------------------------------------------------------------------------------- 1 | tSQLt_testutil.class.sql 2 | ../Build/temp/tSQLtTests/CreateTestUtilAssembly.sql 3 | ../Build/temp/tSQLtTests/GetUnsignedEmptyBytes.sql 4 | tSQLtTestUtilCLR_CreateItems.sql 5 | -------------------------------------------------------------------------------- /TestUtil/GetUnsignedEmptyBytes.mdl.sql: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION tSQLt_testutil.GetUnsignedEmptyBytes() 2 | RETURNS TABLE 3 | AS 4 | RETURN 5 | SELECT 0x000000 AS UnsignedEmptyBytes; 6 | -------------------------------------------------------------------------------- /TestUtil/TestUtil.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TestUtil 6 | {175C322C-24CB-461E-93CD-B47DB6141A87} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /TestUtil/tSQLtTestUtilCLR.mdl.sql: -------------------------------------------------------------------------------- 1 | CREATE ASSEMBLY [tSQLtTestUtilCLR] AUTHORIZATION [dbo] FROM 0x000000 WITH PERMISSION_SET = SAFE; -------------------------------------------------------------------------------- /TestUtilTests/TestUtilTests.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TestUtilTests 6 | {89304D64-1E01-4AA2-8A2A-646042F96D81} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests.EXTERNAL_ACCESS/Run_Methods_Tests_EA.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Run_Methods_Tests_EA'; 2 | GO 3 | CREATE TABLE Run_Methods_Tests_EA.[table 4 tSQLt.Private_InputBuffer tests]( 4 | InputBuffer NVARCHAR(MAX) 5 | ); 6 | GO 7 | --[@tSQLt:RunOnlyOnHostPlatform]('Windows') 8 | CREATE PROCEDURE Run_Methods_Tests_EA.[test tSQLt.Private_InputBuffer returns actual INPUTBUFFER] 9 | AS 10 | BEGIN 11 | EXEC tSQLt.NewConnection @command = 'TRUNCATE TABLE Run_Methods_Tests_EA.[table 4 tSQLt.Private_InputBuffer tests]'; 12 | DECLARE @ExecutedCmd NVARCHAR(MAX); 13 | SET @ExecutedCmd = 'DECLARE @r NVARCHAR(MAX);EXEC tSQLt.Private_InputBuffer @r OUT;INSERT INTO Run_Methods_Tests_EA.[table 4 tSQLt.Private_InputBuffer tests] SELECT @r;' 14 | EXEC tSQLt.NewConnection @command = @ExecutedCmd; 15 | DECLARE @Actual NVARCHAR(MAX); 16 | SELECT @Actual = InputBuffer FROM Run_Methods_Tests_EA.[table 4 tSQLt.Private_InputBuffer tests]; 17 | EXEC tSQLt.AssertEqualsString @Expected = @ExecutedCmd, @Actual = @Actual; 18 | END 19 | GO 20 | -------------------------------------------------------------------------------- /Tests.EXTERNAL_ACCESS/Tests.EXTERNAL_ACCESS.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tests.EXTERNAL_ACCESS 6 | {F7261171-19E3-441E-9622-9472A4792AE9} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests.EXTERNAL_ACCESS_KEY_EXISTS/Tests.EXTERNAL_ACCESS_KEY_EXISTS.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tests.EXTERNAL_ACCESS_KEY_EXISTS 6 | {AB42824F-D996-4DCA-89B1-A50D9EBE95A4} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests.SA/InstallExternalAccessKeyTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'InstallExternalAccessKeyTests'; 2 | GO 3 | CREATE PROCEDURE InstallExternalAccessKeyTests.[test calls tSQLt.InstallAssemblyKey] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.InstallAssemblyKey'; 7 | 8 | EXEC tSQLt.InstallExternalAccessKey; 9 | 10 | SELECT _id_ INTO #Actual FROM tSQLt.InstallAssemblyKey_SpyProcedureLog; 11 | 12 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 13 | 14 | INSERT INTO #Expected VALUES (1); 15 | 16 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 17 | 18 | END; 19 | GO 20 | 21 | CREATE PROCEDURE InstallExternalAccessKeyTests.[test prints sensible deprecation warning] 22 | AS 23 | BEGIN 24 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.InstallAssemblyKey'; 25 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_Print'; 26 | 27 | EXEC tSQLt.InstallExternalAccessKey; 28 | 29 | SELECT Message INTO #Actual FROM tSQLt.Private_Print_SpyProcedureLog ; 30 | 31 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 32 | INSERT INTO #Expected VALUES('tSQLt.InstallExternalAccessKey is deprecated. Please use tSQLt.InstallAssemblyKey instead.'); 33 | 34 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 35 | 36 | END; 37 | GO 38 | -------------------------------------------------------------------------------- /Tests.SA/Private_EnableCLRTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_EnableCLRTests'; 2 | GO 3 | CREATE PROCEDURE Private_EnableCLRTests.[test alters value for 'clr enabled' in serverconfigurations] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.CaptureOutput 'EXEC sys.sp_configure @configname=''clr enabled'', @configvalue=0;'; 7 | 8 | BEGIN TRY 9 | EXEC tSQLt.Private_EnableCLR; 10 | END TRY 11 | BEGIN CATCH 12 | PRINT ERROR_MESSAGE(); 13 | END CATCH 14 | 15 | SELECT name,value 16 | INTO #Actual 17 | FROM sys.configurations AS C 18 | WHERE C.name = 'clr enabled'; 19 | 20 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 21 | INSERT INTO #Expected VALUES('clr enabled',1); 22 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 23 | 24 | END; 25 | GO 26 | CREATE PROCEDURE Private_EnableCLRTests.[test does not alter other values in serverconfigurations] 27 | AS 28 | BEGIN 29 | SELECT C.name, 30 | C.value 31 | INTO #Expected 32 | FROM master.sys.configurations AS C 33 | WHERE name <> 'clr enabled'; 34 | 35 | BEGIN TRY 36 | EXEC tSQLt.Private_EnableCLR; 37 | END TRY 38 | BEGIN CATCH 39 | PRINT ERROR_MESSAGE(); 40 | END CATCH 41 | 42 | SELECT name,value 43 | INTO #Actual 44 | FROM sys.configurations AS C 45 | WHERE C.name <> 'clr enabled'; 46 | 47 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 48 | 49 | END; 50 | GO 51 | CREATE PROCEDURE Private_EnableCLRTests.[test calls RECONFIGURE] 52 | AS 53 | BEGIN 54 | EXEC tSQLt.ExpectException @ExpectedMessage = 'CONFIG statement cannot be used inside a user transaction.'; 55 | 56 | EXEC tSQLt.Private_EnableCLR; 57 | END; 58 | GO 59 | -------------------------------------------------------------------------------- /Tests.SA/RemoveExternalAccessKeyTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'RemoveExternalAccessKeyTests'; 2 | GO 3 | CREATE PROCEDURE RemoveExternalAccessKeyTests.[test calls tSQLt.RemoveAssemblyKey] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.RemoveAssemblyKey'; 7 | 8 | EXEC tSQLt.RemoveExternalAccessKey; 9 | 10 | SELECT _id_ INTO #Actual FROM tSQLt.RemoveAssemblyKey_SpyProcedureLog; 11 | 12 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 13 | 14 | INSERT INTO #Expected VALUES (1); 15 | 16 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 17 | 18 | END; 19 | GO 20 | 21 | CREATE PROCEDURE RemoveExternalAccessKeyTests.[test prints sensible deprecation warning] 22 | AS 23 | BEGIN 24 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.RemoveAssemblyKey'; 25 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_Print'; 26 | 27 | EXEC tSQLt.RemoveExternalAccessKey; 28 | 29 | SELECT Message INTO #Actual FROM tSQLt.Private_Print_SpyProcedureLog ; 30 | 31 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 32 | INSERT INTO #Expected VALUES('tSQLt.RemoveExternalAccessKey is deprecated. Please use tSQLt.RemoveAssemblyKey instead.'); 33 | 34 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 35 | 36 | END; 37 | GO 38 | -------------------------------------------------------------------------------- /Tests.SA/Tests.SA.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tests.SA 6 | {4183AC53-E498-4F50-9B76-2DDB36DBAA83} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests.SA/_ExploratoryTests_SA.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass '_ExploratoryTests_SA'; 2 | GO 3 | CREATE PROCEDURE [_ExploratoryTests_SA].[test MSSQL preserves COLLATION when using SELECT INTO across databases] 4 | AS 5 | BEGIN 6 | SELECT 7 | 'Hello World!' COLLATE SQL_Polish_CP1250_CI_AS c1, 8 | 'Hello World!' COLLATE SQL_Latin1_General_CP437_BIN c2, 9 | 'Hello World!' COLLATE Albanian_BIN2 c3 10 | INTO [_ExploratoryTests_SA].Table1 11 | 12 | SELECT * INTO tempdb.dbo.Table2 FROM [_ExploratoryTests_SA].Table1 13 | 14 | SELECT 15 | C.name COLLATE DATABASE_DEFAULT name, 16 | C.collation_name COLLATE DATABASE_DEFAULT collation_name 17 | INTO #Expected 18 | FROM sys.columns C 19 | WHERE C.object_id = OBJECT_ID('[_ExploratoryTests_SA].Table1'); 20 | 21 | SELECT 22 | C.name COLLATE DATABASE_DEFAULT name, 23 | C.collation_name COLLATE DATABASE_DEFAULT collation_name 24 | INTO #Actual 25 | FROM tempdb.sys.columns C 26 | WHERE C.object_id = OBJECT_ID('tempdb.dbo.Table2'); 27 | 28 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 29 | 30 | END; 31 | GO 32 | -------------------------------------------------------------------------------- /Tests/Private_GetSQLProductMajorVersionTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_GetSQLProductMajorVersionTests'; 2 | GO 3 | --[@tSQLt:MinSqlMajorVersion](10) 4 | --[@tSQLt:MaxSqlMajorVersion](10) 5 | CREATE PROCEDURE Private_GetSQLProductMajorVersionTests.[test return correct version on SQL Version = 10] 6 | AS 7 | BEGIN 8 | DECLARE @Version INT; 9 | EXEC @Version = tSQLt.Private_GetSQLProductMajorVersion; 10 | 11 | EXEC tSQLt.AssertEquals @Expected = 10, @Actual = @Version; 12 | END; 13 | GO 14 | --[@tSQLt:MinSqlMajorVersion](15) 15 | --[@tSQLt:MaxSqlMajorVersion](15) 16 | CREATE PROCEDURE Private_GetSQLProductMajorVersionTests.[test return correct version on SQL Version = 15] 17 | AS 18 | BEGIN 19 | DECLARE @Version INT; 20 | EXEC @Version = tSQLt.Private_GetSQLProductMajorVersion; 21 | 22 | EXEC tSQLt.AssertEquals @Expected = 15, @Actual = @Version; 23 | END; 24 | -------------------------------------------------------------------------------- /Tests/Private_InstallationInfoTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_InstallationInfoTests'; 2 | GO 3 | CREATE PROCEDURE Private_InstallationInfoTests.[test returns current SqlVersion] 4 | AS 5 | BEGIN 6 | SELECT SqlVersion INTO #Actual FROM tSQLt.Private_InstallationInfo(); 7 | 8 | SELECT SqlVersion INTO #Expected FROM tSQLt.Info(); 9 | 10 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 11 | END; 12 | GO 13 | CREATE FUNCTION Private_InstallationInfoTests.[return 98.76]() 14 | RETURNS TABLE 15 | AS 16 | RETURN SELECT CAST(98.76 AS NUMERIC(10,2)) AS SqlVersion; 17 | GO 18 | CREATE PROCEDURE Private_InstallationInfoTests.[test returns SqlVersion from tSQLt.Info after new install] 19 | AS 20 | BEGIN 21 | EXEC tSQLt.FakeFunction @FunctionName = 'tSQLt.Info', @FakeFunctionName = 'Private_InstallationInfoTests.[return 98.76]'; 22 | EXEC tSQLt.Private_CreateInstallationInfo; 23 | SELECT SqlVersion INTO #Actual FROM tSQLt.Private_InstallationInfo(); 24 | 25 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 26 | INSERT INTO #Expected VALUES(98.76); 27 | 28 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 29 | END; 30 | GO 31 | -------------------------------------------------------------------------------- /Tests/Private_NoTransactionTableActionTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_NoTransactionTableActionTests'; 2 | GO 3 | CREATE PROCEDURE Private_NoTransactionTableActionTests.[test contains all tSQLt tables] 4 | AS 5 | BEGIN 6 | SELECT Name INTO #Actual FROM tSQLt.Private_NoTransactionTableAction; 7 | 8 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 9 | INSERT INTO #Expected 10 | SELECT QUOTENAME(SCHEMA_NAME(t.schema_id))+'.'+QUOTENAME(t.name) 11 | FROM sys.tables t WHERE schema_id = SCHEMA_ID('tSQLt') AND name NOT LIKE ('%SpyProcedureLog'); 12 | 13 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 14 | END; 15 | GO 16 | CREATE PROCEDURE Private_NoTransactionTableActionTests.[test has the correct actions for all tSQLt tables] 17 | AS 18 | BEGIN 19 | SELECT Name, Action INTO #Actual FROM tSQLt.Private_NoTransactionTableAction; 20 | 21 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 22 | INSERT INTO #Expected 23 | SELECT '[tSQLt].[Private_NewTestClassList]','Hide' UNION ALL 24 | SELECT '[tSQLt].[Run_LastExecution]', 'Hide' UNION ALL 25 | SELECT '[tSQLt].[Private_Configurations]', 'Restore' UNION ALL 26 | SELECT '[tSQLt].[CaptureOutputLog]', 'Truncate' UNION ALL 27 | SELECT '[tSQLt].[Private_RenamedObjectLog]','Ignore' UNION ALL 28 | SELECT '[tSQLt].[Private_Seize]','Ignore' UNION ALL 29 | SELECT '[tSQLt].[Private_Seize_NoTruncate]','Ignore' UNION ALL 30 | SELECT '[tSQLt].[TestResult]', 'Restore'; 31 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 32 | END; 33 | GO -------------------------------------------------------------------------------- /Tests/Private_ResetNewTestClassListTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_ResetNewTestClassListTests'; 2 | GO 3 | CREATE PROCEDURE Private_ResetNewTestClassListTests.[test does not fail if Private_NewTestClassList is empty] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.FakeTable @TableName = 'tSQLt.Private_NewTestClassList'; 7 | 8 | EXEC tSQLt.ExpectNoException; 9 | EXEC tSQLt.Private_ResetNewTestClassList; 10 | END; 11 | GO 12 | CREATE PROCEDURE Private_ResetNewTestClassListTests.[test empties Private_NewTestClassList] 13 | AS 14 | BEGIN 15 | EXEC tSQLt.FakeTable @TableName = 'tSQLt.Private_NewTestClassList'; 16 | INSERT INTO tSQLt.Private_NewTestClassList VALUES('tc1'); 17 | INSERT INTO tSQLt.Private_NewTestClassList VALUES('tc2'); 18 | INSERT INTO tSQLt.Private_NewTestClassList VALUES('tc3'); 19 | 20 | EXEC tSQLt.Private_ResetNewTestClassList; 21 | 22 | EXEC tSQLt.AssertEmptyTable @TableName = 'tSQLt.Private_NewTestClassList'; 23 | END; 24 | GO 25 | -------------------------------------------------------------------------------- /Tests/Private_ResultsTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_ResultsTests'; 2 | GO 3 | CREATE PROCEDURE Private_ResultsTests.[test Contains all Result values (double ledger)] 4 | AS 5 | BEGIN 6 | SELECT Severity, Result INTO #Actual FROM tSQLt.Private_Results; 7 | 8 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 9 | INSERT INTO #Expected 10 | SELECT 1,'Success' UNION ALL 11 | SELECT 2,'Skipped' UNION ALL 12 | SELECT 3,'Failure' UNION ALL 13 | SELECT 4,'Error' UNION ALL 14 | SELECT 5,'Abort' UNION ALL 15 | SELECT 6,'FATAL' ; 16 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 17 | 18 | END; 19 | GO 20 | -------------------------------------------------------------------------------- /Tests/Private_SplitSqlVersionTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'Private_SplitSqlVersionTests'; 2 | GO 3 | CREATE PROCEDURE Private_SplitSqlVersionTests.[test splits a 4-part version correctly] 4 | AS 5 | BEGIN 6 | SELECT Major, 7 | Minor, 8 | Build, 9 | Revision 10 | INTO #Actual 11 | FROM tSQLt.Private_SplitSqlVersion('15.0.1.2345'); 12 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 13 | INSERT INTO #Expected 14 | VALUES('15','0','1','2345'); 15 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 16 | END; 17 | GO 18 | CREATE PROCEDURE Private_SplitSqlVersionTests.[test works with shorter versions] 19 | AS 20 | BEGIN 21 | SELECT Major, 22 | Minor, 23 | Build, 24 | Revision 25 | INTO #Actual 26 | FROM (VALUES('15.0.1'),('14.2'),('13'))Versions(V) 27 | CROSS APPLY tSQLt.Private_SplitSqlVersion(Versions.V); 28 | 29 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 30 | INSERT INTO #Expected VALUES('15','0','1',NULL); 31 | INSERT INTO #Expected VALUES('14','2',NULL,NULL); 32 | INSERT INTO #Expected VALUES('13',NULL,NULL,NULL); 33 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 34 | END; 35 | GO 36 | -------------------------------------------------------------------------------- /Tests/RemoveObjectIfExistsTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'RemoveObjectIfExistsTests'; 2 | GO 3 | CREATE PROCEDURE RemoveObjectIfExistsTests.[test calls tSQLt.RemoveObject with @IfExists = 1] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.RemoveObject', @CommandToExecute = NULL; 7 | 8 | EXEC tSQLt.RemoveObjectIfExists @ObjectName = 'some.name'; 9 | 10 | SELECT ObjectName,IfExists 11 | INTO #Actual 12 | FROM tSQLt.RemoveObject_SpyProcedureLog; 13 | 14 | SELECT TOP(0) * 15 | INTO #Expected 16 | FROM #Actual; 17 | 18 | INSERT INTO #Expected 19 | VALUES('some.name',1); 20 | 21 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 22 | 23 | END; 24 | GO 25 | CREATE PROCEDURE RemoveObjectIfExistsTests.[test calls tSQLt.RemoveObject passes @NewName back] 26 | AS 27 | BEGIN 28 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.RemoveObject', @CommandToExecute = 'SET @NewName = ''new.name'';'; 29 | 30 | DECLARE @ActualNewName NVARCHAR(MAX); SET @ActualNewName = 'No value was returned!'; 31 | 32 | EXEC tSQLt.RemoveObjectIfExists @ObjectName = 'some.name',@NewName = @ActualNewName OUT; 33 | 34 | EXEC tSQLt.AssertEqualsString @Expected = 'new.name', @Actual = @ActualNewName; 35 | 36 | END; 37 | GO 38 | -------------------------------------------------------------------------------- /Tests/ResetTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'ResetTests'; 2 | GO 3 | CREATE PROCEDURE ResetTests.[test calls tSQLt.Private_ResetNewTestClassList] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.SpyProcedure @ProcedureName = 'tSQLt.Private_ResetNewTestClassList'; 7 | EXEC tSQLt.Reset; 8 | 9 | SELECT _id_ 10 | INTO #Actual 11 | FROM tSQLt.Private_ResetNewTestClassList_SpyProcedureLog; 12 | 13 | SELECT TOP(0) A.* INTO #Expected FROM #Actual A RIGHT JOIN #Actual X ON 1=0; 14 | 15 | INSERT INTO #Expected 16 | VALUES(1); 17 | 18 | EXEC tSQLt.AssertEqualsTable '#Expected','#Actual'; 19 | END; 20 | GO 21 | -------------------------------------------------------------------------------- /Tests/StubRecordTests.class.sql: -------------------------------------------------------------------------------- 1 | EXEC tSQLt.NewTestClass 'StubRecordTests'; 2 | GO 3 | CREATE PROC StubRecordTests.[test StubRecord is deployed] 4 | AS 5 | BEGIN 6 | EXEC tSQLt.AssertObjectExists 'tSQLt.StubRecord'; 7 | END; 8 | GO 9 | -------------------------------------------------------------------------------- /Tests/Tests.sqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tests 6 | {5A1279BA-7094-4A0B-87E9-A1B3637B4F3D} 7 | Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider 8 | 1033, CI 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests/tSQLt.AssertNotEquals.ssp.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID('tSQLt.AssertNotEquals') IS NOT NULL DROP PROCEDURE tSQLt.AssertNotEquals; 2 | GO 3 | ---Build+ 4 | CREATE PROCEDURE tSQLt.AssertNotEquals 5 | @Expected SQL_VARIANT, 6 | @Actual SQL_VARIANT, 7 | @Message NVARCHAR(MAX) = '' 8 | AS 9 | BEGIN 10 | IF @Expected = @Actual EXEC tSQLt.Fail; 11 | RETURN 0; 12 | END; 13 | ---Build- 14 | GO 15 | -------------------------------------------------------------------------------- /UpgradeLog.XML: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.tsqlt.org -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | WELCOME TO TSQLT, THE OPEN SOURCE DATABASE UNIT TESTING FRAMEWORK FOR SQL SERVER -------------------------------------------------------------------------------- /tSQLt.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "powershell.codeFormatting.addWhitespaceAroundPipe": true, 9 | "yaml.schemaStore.enable": false, 10 | "dataworkspace.excludedProjects": [ 11 | ], 12 | "dotnet.preferCSharpExtension": true 13 | } 14 | } -------------------------------------------------------------------------------- /tSQLtCLR/OfficialSigningKey/CreateBase64KeyFile.ps1: -------------------------------------------------------------------------------- 1 | Set-Content -Path $PSScriptRoot'\tSQLtOfficialSigningKey.b64.txt' -Value ([Convert]::ToBase64String([IO.File]::ReadAllBytes($PSScriptRoot+'\tSQLtOfficialSigningKey.pfx'))) -------------------------------------------------------------------------------- /tSQLtCLR/OfficialSigningKey/tSQLtOfficialSigningKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tSQLt-org/tSQLt/4a921d0dacfb1d66b3db124c58158c80e5e910e6/tSQLtCLR/OfficialSigningKey/tSQLtOfficialSigningKey.pfx -------------------------------------------------------------------------------- /tSQLtCLR/UnsignedEmpty/Properties/XXXX.AssemblyInfo.cs.XXXX: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UnsignedEmpty")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UnsignedEmpty")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("215e1957-5189-4209-a3b0-6b25a4588762")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /tSQLtCLR/UnsignedEmpty/UnsignedEmpty.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net40 4 | true 5 | UnsignedEmpty 6 | An empty (no code) assembly that is not signed 7 | tSQLt Foundation 8 | tSQLt 9 | Copyright © sqlity.net 2010 - $(Year) 10 | false 11 | true 12 | Release 13 | 14 | false 15 | false 16 | true 17 | 18 | 19 | 20 | $([System.DateTime]::Now.Year) 21 | 1.0.0.0 22 | $(AssemblyVersion) 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtAssemblyKey/Properties/XXXX.AssemblyInfo.cs.XXXX: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("tSQLtAssemblyKey")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("tSQLt")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0356005b-71fd-4df3-8502-27c6a606e9e8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | 35 | // Sign assembly with key in this container: 36 | [assembly: System.Reflection.AssemblyKeyNameAttribute("tSQLt_OfficialSigningKey")] 37 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtAssemblyKey/empty.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace tSQLtAssemblyKey 3 | { 4 | class empty 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/CommandExecutorException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.Serialization; 5 | 6 | namespace tSQLtCLR 7 | { 8 | [Serializable] 9 | public class CommandExecutorException : Exception 10 | { 11 | public CommandExecutorException() : base() { } 12 | public CommandExecutorException(String message) : base(message) { } 13 | public CommandExecutorException(String message, Exception innerException) : base(message, innerException) { } 14 | protected CommandExecutorException(SerializationInfo info, StreamingContext context) : base(info, context) { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/InvalidResultSetException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.Serialization; 5 | 6 | namespace tSQLtCLR 7 | { 8 | [Serializable] 9 | public class InvalidResultSetException : Exception 10 | { 11 | public InvalidResultSetException() : base() { } 12 | public InvalidResultSetException(String message) : base(message) { } 13 | public InvalidResultSetException(String message, Exception innerException) : base(message, innerException) { } 14 | protected InvalidResultSetException(SerializationInfo info, StreamingContext context) : base(info, context) { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/OutputCaptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Data.SqlClient; 5 | using System.Data.SqlTypes; 6 | using System.Data; 7 | 8 | namespace tSQLtCLR 9 | { 10 | class OutputCaptor 11 | { 12 | private TestDatabaseFacade testDatabaseFacade; 13 | 14 | public OutputCaptor(TestDatabaseFacade testDatabaseFacade) 15 | { 16 | this.testDatabaseFacade = testDatabaseFacade; 17 | } 18 | 19 | internal void CaptureOutputToLogTable(System.Data.SqlTypes.SqlString command) 20 | { 21 | ExecuteCommand(command); 22 | testDatabaseFacade.logCapturedOutput(testDatabaseFacade.InfoMessage); 23 | } 24 | 25 | internal void SuppressOutput(System.Data.SqlTypes.SqlString command) 26 | { 27 | ExecuteCommand(command); 28 | } 29 | 30 | internal void ExecuteCommand(System.Data.SqlTypes.SqlString command) 31 | { 32 | SqlDataReader reader = testDatabaseFacade.executeCommand(command); 33 | reader.Close(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/PostBuild.bat: -------------------------------------------------------------------------------- 1 | ECHO GOTHERE 2 | CALL :RUN %* > "%~f1\buildlog.txt" 2>"%~f1\builderr.txt" 3 | GOTO :EOF 4 | :RUN 5 | SET tSQLtPath=%~f1\..\ 6 | SET tSQLtCLRTargetFile=%~f2 7 | 8 | ECHO tSQLtPath = %tSQLtPath% 9 | ECHO tSQLtCLRTargetFile = %tSQLtCLRTargetFile% 10 | 11 | ECHO Starting tSQLt.class.sql 12 | sqlcmd -E -S localhost -d tSQLt -b -i "%~f1\..\tSQLt.class.sql" 13 | ECHO Starting tSQLtCLR.sql 14 | sqlcmd -E -S localhost -d tSQLt -b -i "%~f1\..\tSQLtCLR.sql" 15 | ECHO Starting tSQLtCLR_CreateProcs.sql 16 | sqlcmd -E -S localhost -d tSQLt -b -i "%~f1\..\tSQLtCLR_CreateProcs.sql" 17 | ECHO %ERRORLEVEL% 18 | 19 | ECHO Finished! 20 | :EOF -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/StoredProcedures.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Data.Sql; 4 | using System.Data.SqlTypes; 5 | using System.Data.SqlClient; 6 | 7 | using Microsoft.SqlServer.Server; 8 | 9 | namespace tSQLtCLR 10 | { 11 | public static partial class StoredProcedures 12 | { 13 | public static void AssertResultSetsHaveSameMetaData(SqlString expectedCommand, SqlString actualCommand) 14 | { 15 | MetaDataEqualityAsserter asserter = new MetaDataEqualityAsserter(new TestDatabaseFacade()); 16 | asserter.AssertResultSetsHaveSameMetaData(expectedCommand, actualCommand); 17 | } 18 | 19 | public static void ResultSetFilter(SqlInt32 resultSetNo, SqlString command) 20 | { 21 | ResultSetFilter filter = new ResultSetFilter(new TestDatabaseFacade()); 22 | filter.sendSelectedResultSetToSqlContext(resultSetNo, command); 23 | } 24 | 25 | public static void NewConnection(SqlString command) 26 | { 27 | CommandExecutor executor = new CommandExecutor(); 28 | executor.Execute(command); 29 | } 30 | 31 | public static void CaptureOutput(SqlString command) 32 | { 33 | OutputCaptor captor = new OutputCaptor(new TestDatabaseFacade()); 34 | captor.CaptureOutputToLogTable(command); 35 | } 36 | 37 | public static void SuppressOutput(SqlString command) 38 | { 39 | OutputCaptor captor = new OutputCaptor(new TestDatabaseFacade()); 40 | captor.SuppressOutput(command); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace tSQLtCLR 6 | { 7 | public static class StringExtensions 8 | { 9 | public static String tSQLtReplicate(this String repeatString, int count) 10 | { 11 | return new StringBuilder().Insert(0, repeatString, count).ToString(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtCLR/XXXXX.user.XXXX: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/ClrFunctions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Microsoft.SqlServer.Server; 6 | using System.Data.SqlTypes; 7 | 8 | namespace tSQLtTestUtilCLR 9 | { 10 | public class ClrFunctions 11 | { 12 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)] 13 | public static SqlString AClrSvf(SqlString p1, SqlString p2) 14 | { 15 | return new SqlString("AClrSvf:["+p1.ToString()+"|"+p2.ToString()+"]"); 16 | } 17 | 18 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, TableDefinition = "id INT,val NVARCHAR(MAX)", FillRowMethodName = "AClrTvf_Row")] 19 | public static IEnumerable AClrTvf(SqlString p1, SqlString p2) 20 | { 21 | return new Dictionary { { 1, p1 }, { 2, p2 } }; 22 | } 23 | 24 | [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, TableDefinition = "id INT,val NVARCHAR(MAX)", FillRowMethodName = "AClrTvf_Row")] 25 | public static IEnumerable AnEmptyClrTvf(SqlString p1, SqlString p2) 26 | { 27 | return new Dictionary { }; 28 | } 29 | 30 | private static void AClrTvf_Row(object row, out SqlInt32 id, out SqlString val) 31 | { 32 | var keyValuePair = (KeyValuePair)row; 33 | id = keyValuePair.Key; 34 | val = keyValuePair.Value; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/ClrStoredProcedures.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace tSQLtTestUtilCLR 6 | { 7 | public class ClrStoredProcedures 8 | { 9 | public static void AClrSsp() 10 | { 11 | return; 12 | } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/DataTypeByteOrdered.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.SqlTypes; 3 | using System.IO; 4 | using Microsoft.SqlServer.Server; 5 | 6 | namespace tSQLtTestUtilCLR 7 | { 8 | [SqlUserDefinedType(Format.UserDefined, MaxByteSize = 5, IsFixedLength = true, IsByteOrdered = true)] 9 | public class DataTypeByteOrdered : INullable, IBinarySerialize, IComparable 10 | { 11 | private int _i; 12 | 13 | public bool IsNull { get; private set; } 14 | 15 | public override string ToString() 16 | { 17 | return $"<>"; 18 | } 19 | 20 | public int CompareTo(object obj) 21 | { 22 | if (!(obj is DataTypeByteOrdered)) 23 | { 24 | throw new ArgumentException("Object is not a DataTypeByteOrdered."); 25 | } 26 | 27 | var p2 = (DataTypeByteOrdered)obj; 28 | 29 | return _i.CompareTo(p2._i); 30 | } 31 | 32 | public static DataTypeByteOrdered Parse(SqlString s) 33 | { 34 | return new DataTypeByteOrdered() { IsNull = (s.IsNull), _i = int.Parse(s.Value) }; 35 | } 36 | 37 | public static DataTypeByteOrdered Null 38 | { 39 | get { return new DataTypeByteOrdered() { IsNull = true }; } 40 | } 41 | 42 | public void Read(BinaryReader r) 43 | { 44 | IsNull = r.ReadBoolean(); 45 | _i = r.ReadInt32(); 46 | } 47 | 48 | public void Write(BinaryWriter w) 49 | { 50 | w.Write(IsNull); 51 | w.Write(_i); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/DataTypeNoEqual.cs: -------------------------------------------------------------------------------- 1 | using System.Data.SqlTypes; 2 | using System.IO; 3 | using Microsoft.SqlServer.Server; 4 | 5 | namespace tSQLtTestUtilCLR 6 | { 7 | [SqlUserDefinedType(Format.UserDefined, MaxByteSize = 5, IsFixedLength = true)] 8 | public class DataTypeNoEqual : INullable, IBinarySerialize 9 | { 10 | private int _i; 11 | 12 | public bool IsNull { get; private set; } 13 | 14 | public override string ToString() 15 | { 16 | return "<>"; 17 | } 18 | 19 | public static DataTypeNoEqual Parse(SqlString s) 20 | { 21 | return new DataTypeNoEqual() { IsNull = (s.IsNull), _i = int.Parse(s.Value)}; 22 | } 23 | 24 | public static DataTypeNoEqual Null 25 | { 26 | get { return new DataTypeNoEqual() {IsNull = true}; } 27 | } 28 | 29 | public void Read(BinaryReader r) 30 | { 31 | IsNull = r.ReadBoolean(); 32 | _i = r.ReadInt32(); 33 | } 34 | 35 | public void Write(BinaryWriter w) 36 | { 37 | w.Write(IsNull); 38 | w.Write(_i); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/DataTypeWithEqual.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.SqlTypes; 3 | using System.IO; 4 | using Microsoft.SqlServer.Server; 5 | 6 | namespace tSQLtTestUtilCLR 7 | { 8 | [SqlUserDefinedType(Format.UserDefined, MaxByteSize = 5, IsFixedLength = true)] 9 | public class DataTypeWithEqual : INullable, IBinarySerialize, IComparable 10 | { 11 | private int _i; 12 | 13 | public bool IsNull { get; private set; } 14 | 15 | public override string ToString() 16 | { 17 | return "<>"; 18 | } 19 | 20 | public int CompareTo(object obj) 21 | { 22 | if (!(obj is DataTypeWithEqual)) 23 | { 24 | throw new ArgumentException("Object is not a DataTypeWithEqual."); 25 | } 26 | 27 | var p2 = (DataTypeWithEqual) obj; 28 | 29 | return _i.CompareTo(p2._i); 30 | } 31 | 32 | public static DataTypeWithEqual Parse(SqlString s) 33 | { 34 | return new DataTypeWithEqual() { IsNull = (s.IsNull), _i = int.Parse(s.Value) }; 35 | } 36 | 37 | public static DataTypeWithEqual Null 38 | { 39 | get { return new DataTypeWithEqual() { IsNull = true }; } 40 | } 41 | 42 | public void Read(BinaryReader r) 43 | { 44 | IsNull = r.ReadBoolean(); 45 | _i = r.ReadInt32(); 46 | } 47 | 48 | public void Write(BinaryWriter w) 49 | { 50 | w.Write(IsNull); 51 | w.Write(_i); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/Properties/XXX.AssemblyInfo.cs.XXXX: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("tSQLtTestUtilCLR")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("tSQLtTestUtilCLR")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("82c6526b-de5c-4b32-a99b-24d75acb9f4f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | 38 | [assembly: System.Security.AllowPartiallyTrustedCallers] 39 | 40 | // Sign assembly with key in this container: 41 | [assembly: System.Reflection.AssemblyKeyNameAttribute("tSQLt_OfficialSigningKey")] 42 | -------------------------------------------------------------------------------- /tSQLtCLR/tSQLtTestUtilCLR/XXXX.app.config.XXXX: -------------------------------------------------------------------------------- 1 |  2 | 3 | --------------------------------------------------------------------------------