Merge branch 'release/2.1' into release/2.2
This commit is contained in:
Коммит
67511a675f
21
EFCore.sln
21
EFCore.sln
|
@ -101,6 +101,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.SqlServer.NTS", "src
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Sqlite.NTS", "src\EFCore.Sqlite.NTS\EFCore.Sqlite.NTS.csproj", "{1747A095-A464-4445-9F39-A80531FB24FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.Core", "src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj", "{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite", "src\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.csproj", "{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.Tests.csproj", "{51DAD0D5-5564-4FB7-B34C-98814C900DF9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -251,6 +257,18 @@ Global
|
|||
{1747A095-A464-4445-9F39-A80531FB24FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1747A095-A464-4445-9F39-A80531FB24FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1747A095-A464-4445-9F39-A80531FB24FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -295,6 +313,9 @@ Global
|
|||
{B4E155E5-C0B8-4680-92A0-A0DE745486B1} = {258D5057-81B9-40EC-A872-D21E27452749}
|
||||
{F53EB45F-84D7-4520-B813-8916C0C756BB} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
|
||||
{1747A095-A464-4445-9F39-A80531FB24FD} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
|
||||
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
|
||||
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
|
||||
{51DAD0D5-5564-4FB7-B34C-98814C900DF9} = {258D5057-81B9-40EC-A872-D21E27452749}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {285A5EB4-BCF4-40EB-B9E1-DF6DBCB5E705}
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2005
|
||||
MinimumVisualStudioVersion = 15.0.26730.03
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9396F8F4-299D-427C-B829-EF9A931DAA3C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite.Core", "src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj", "{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{ECB63F46-D037-4EEA-A4CD-BF18B5B9D2C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.Tests.csproj", "{69D2DA13-6774-43A9-A2E3-709594136FF8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite", "src\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.csproj", "{298DB9C7-8C81-40A7-B042-20D62C914820}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{964B9063-40FE-4DB2-A80D-3073CAC4E7BA}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.appveyor.yml = .appveyor.yml
|
||||
.gitattributes = .gitattributes
|
||||
.gitignore = .gitignore
|
||||
.travis.yml = .travis.yml
|
||||
build.cmd = build.cmd
|
||||
build.ps1 = build.ps1
|
||||
build.sh = build.sh
|
||||
CONTRIBUTING.md = CONTRIBUTING.md
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
LICENSE.txt = LICENSE.txt
|
||||
NuGet.config = NuGet.config
|
||||
NuGetPackageVerifier.json = NuGetPackageVerifier.json
|
||||
README.md = README.md
|
||||
version.xml = version.xml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateFunctionSample", "samples\AggregateFunctionSample\AggregateFunctionSample.csproj", "{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncSample", "samples\AsyncSample\AsyncSample.csproj", "{FC71113A-A71D-459C-A7A9-1531D9A037D4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BatchingSample", "samples\BatchingSample\BatchingSample.csproj", "{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BulkInsertSample", "samples\BulkInsertSample\BulkInsertSample.csproj", "{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollationSample", "samples\CollationSample\CollationSample.csproj", "{A5E96F24-953A-4E71-9081-736E11D8229F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DateAndTimeSample", "samples\DateAndTimeSample\DateAndTimeSample.csproj", "{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DirtyReadSample", "samples\DirtyReadSample\DirtyReadSample.csproj", "{CB405B7D-81E5-48B6-9E24-AC901D0423EE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EncryptionSample", "samples\EncryptionSample\EncryptionSample.csproj", "{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InMemorySample", "samples\InMemorySample\InMemorySample.csproj", "{CA7F7B53-9EE1-4516-874A-88EC717D5264}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropSample", "samples\InteropSample\InteropSample.csproj", "{068B819D-809E-421F-96A1-DAE67CDD79AE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegularExpressionSample", "samples\RegularExpressionSample\RegularExpressionSample.csproj", "{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResultMetadataSample", "samples\ResultMetadataSample\ResultMetadataSample.csproj", "{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScalarFunctionSample", "samples\ScalarFunctionSample\ScalarFunctionSample.csproj", "{4A78B130-96DB-408F-A601-AFDA94347F06}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{298DB9C7-8C81-40A7-B042-20D62C914820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{298DB9C7-8C81-40A7-B042-20D62C914820}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{298DB9C7-8C81-40A7-B042-20D62C914820}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{298DB9C7-8C81-40A7-B042-20D62C914820}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5E96F24-953A-4E71-9081-736E11D8229F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5E96F24-953A-4E71-9081-736E11D8229F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5E96F24-953A-4E71-9081-736E11D8229F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5E96F24-953A-4E71-9081-736E11D8229F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A78B130-96DB-408F-A601-AFDA94347F06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A78B130-96DB-408F-A601-AFDA94347F06}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A78B130-96DB-408F-A601-AFDA94347F06}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A78B130-96DB-408F-A601-AFDA94347F06}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D} = {9396F8F4-299D-427C-B829-EF9A931DAA3C}
|
||||
{69D2DA13-6774-43A9-A2E3-709594136FF8} = {ECB63F46-D037-4EEA-A4CD-BF18B5B9D2C4}
|
||||
{298DB9C7-8C81-40A7-B042-20D62C914820} = {9396F8F4-299D-427C-B829-EF9A931DAA3C}
|
||||
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{FC71113A-A71D-459C-A7A9-1531D9A037D4} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{A5E96F24-953A-4E71-9081-736E11D8229F} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{CB405B7D-81E5-48B6-9E24-AC901D0423EE} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{CA7F7B53-9EE1-4516-874A-88EC717D5264} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{068B819D-809E-421F-96A1-DAE67CDD79AE} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
{4A78B130-96DB-408F-A601-AFDA94347F06} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DF78D8CC-5604-4059-9EFB-291E2629523E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,86 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArgumentName/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArgumentNameForLiteralExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Sqlite/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Sqlite"><HtmlReformatCode>True</HtmlReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_IMPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><XMLReformatCode>True</XMLReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSharpFormatDocComments>True</CSharpFormatDocComments><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings></Profile></s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Sqlite</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">Sqlite</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARGUMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_ATTRIBUTE_STYLE/@EntryValue">SEPARATE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_DO_EXPRESSION/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_IF_EXPRESSION/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_WHILE_EXPRESSION/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_USINGS_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_LINQ_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_FIRST_TYPE_PARAMETER_CONSTRAINT/@EntryValue">True</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">140</s:Int64>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_MULTIPLE_TYPE_PARAMEER_CONSTRAINTS_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
|
||||
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/JavaScriptFormatOther/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlFormatter/WrapBeforeAttr/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlFormatter/WrapInsideText/@EntryValue">True</s:Boolean>
|
||||
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
|
||||
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) .NET Foundation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Constructor/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Constructor/Options/=XmlDocumentation/@EntryIndexedValue">True</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Equality/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ChangeEquals/@EntryIndexedValue">Side by side</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ChangeGetHashCode/@EntryIndexedValue">Side by side</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=EqualityOperators/@EntryIndexedValue">False</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ImplementIEquatable/@EntryIndexedValue">False</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=WrapInRegion/@EntryIndexedValue">False</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=WrapInRegion/@EntryIndexedValue">False</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/IntroduceVariableUseVar/UseVarForIntroduceVariableRefactoring/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=042e7460_002D3ec6_002D4f1c_002D87c3_002Dfc91240d4c90/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Public" Description="Test Methods"><ElementKinds><Kind Name="TEST_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="Aa_bb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/AbsolutePath/@EntryValue">D:\code\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.sln.DotSettings</s:String>
|
||||
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/RelativePath/@EntryValue"></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File3F8396C34A1E534D98BAC4E46C6A441A/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File3F8396C34A1E534D98BAC4E46C6A441A/RelativePriority/@EntryValue">1</s:Double>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsParsFormattingSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -32,15 +32,20 @@
|
|||
<OracleManagedDataAccessPackageVersion>12.2.1100</OracleManagedDataAccessPackageVersion>
|
||||
<RemotionLinqPackageVersion>2.2.0</RemotionLinqPackageVersion>
|
||||
<SQLitePCLRawBundleGreenPackageVersion>1.1.11</SQLitePCLRawBundleGreenPackageVersion>
|
||||
<SQLitePCLRawBundleSqlcipherPackageVersion>1.1.11</SQLitePCLRawBundleSqlcipherPackageVersion>
|
||||
<SQLitePCLRawCorePackageVersion>1.1.11</SQLitePCLRawCorePackageVersion>
|
||||
<StyleCopAnalyzersPackageVersion>1.0.0</StyleCopAnalyzersPackageVersion>
|
||||
<SystemCollectionsImmutablePackageVersion>1.5.0</SystemCollectionsImmutablePackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>4.5.0</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDataSqlClientPackageVersion>4.6.0-preview3-27001-02</SystemDataSqlClientPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemInteractiveAsyncPackageVersion>3.1.1</SystemInteractiveAsyncPackageVersion>
|
||||
<SystemInteractiveAsyncPackageVersion>3.2.0</SystemInteractiveAsyncPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
|
||||
<XunitAssertPackageVersion>2.3.1</XunitAssertPackageVersion>
|
||||
<XunitCorePackageVersion>2.3.1</XunitCorePackageVersion>
|
||||
<XunitExtensibilityExecutionPackageVersion>2.3.1</XunitExtensibilityExecutionPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<ExcludeFromTest Include="$(RepositoryRoot)test\EFCore.SqlServer.FunctionalTests\*.csproj" Condition="'$(OS)' != 'Windows_NT' AND '$(Test__SqlServer__DefaultConnection)' == ''"/>
|
||||
<ExcludeSolutions Include="$(RepositoryRoot)EFCore.Runtime.sln" />
|
||||
<ExcludeSolutions Include="$(RepositoryRoot)EFCore.Cosmos.sln" />
|
||||
<ExcludeSolutions Include="$(RepositoryRoot)Microsoft.Data.Sqlite.sln" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace AggregateFunctionSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE student (
|
||||
gpa REAL
|
||||
);
|
||||
|
||||
INSERT INTO student
|
||||
VALUES (4.0),
|
||||
(3.0),
|
||||
(3.0),
|
||||
(2.0),
|
||||
(2.0),
|
||||
(2.0),
|
||||
(2.0),
|
||||
(1.0),
|
||||
(1.0),
|
||||
(0.0);
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
connection.CreateAggregate(
|
||||
"stdev",
|
||||
new StdDevContext(),
|
||||
|
||||
// This is called for each row
|
||||
(StdDevContext context, double value) =>
|
||||
{
|
||||
context.Count++;
|
||||
var delta = value - context.Mean;
|
||||
context.Mean += delta / context.Count;
|
||||
context.Sum += delta * (value - context.Mean);
|
||||
|
||||
return context;
|
||||
},
|
||||
|
||||
// This is called to get the final result
|
||||
context => Math.Sqrt(context.Sum / (context.Count - 1)));
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT stdev(gpa)
|
||||
FROM student
|
||||
";
|
||||
var stdDev = (double)queryCommand.ExecuteScalar();
|
||||
|
||||
Console.WriteLine($"Standard deviation: {stdDev}");
|
||||
}
|
||||
|
||||
struct StdDevContext
|
||||
{
|
||||
public int Count { get; set; }
|
||||
public double Mean { get; set; }
|
||||
public double Sum { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace AsyncSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static async Task Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=AsyncSample.db");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE data (
|
||||
value BLOB
|
||||
)
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
// SQLite doesn't support asynchronous I/O. Instead, they recommend using a
|
||||
// write -ahead log (WAL) which improves write performance. This sample
|
||||
// demonstrates the anti-pattern of using ADO.NET's async methods with
|
||||
// Microsoft.Data.Sqlite.
|
||||
|
||||
var insertCommand = connection.CreateCommand();
|
||||
insertCommand.CommandText =
|
||||
@"
|
||||
INSERT INTO data
|
||||
VALUES ($value)
|
||||
";
|
||||
|
||||
Console.WriteLine("Generating 100 MB of data...");
|
||||
var value = new byte[100_000_000];
|
||||
var random = new Random();
|
||||
random.NextBytes(value);
|
||||
insertCommand.Parameters.AddWithValue("$value", value);
|
||||
|
||||
Console.WriteLine("Inserting data...");
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var task = insertCommand.ExecuteNonQueryAsync();
|
||||
Console.WriteLine($"Blocked for {stopwatch.ElapsedMilliseconds} ms");
|
||||
|
||||
stopwatch.Restart();
|
||||
await task;
|
||||
Console.WriteLine($"Yielded for {stopwatch.ElapsedMilliseconds} ms");
|
||||
|
||||
// Clean up
|
||||
connection.Close();
|
||||
File.Delete("AsyncSample.db");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace BatchingSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
// SQLite doesn't support batching natively. Since there's no network involved, it
|
||||
// wouldn't really help with performance anyway. Batching is implemented in
|
||||
// Microsoft.Data.Sqlite as a convenience. For better command performance, see
|
||||
// BulkInsertSample.
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE blog (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE post (
|
||||
id INTEGER PRIMARY KEY,
|
||||
title TEXT,
|
||||
blog_id INTEGER NOT NULL,
|
||||
FOREIGN KEY (blog_id) REFERENCES blog
|
||||
);
|
||||
|
||||
INSERT INTO blog
|
||||
VALUES (1, 'Brice''s Blog');
|
||||
|
||||
INSERT INTO post
|
||||
VALUES (1, 'Hello, World!', 1),
|
||||
(2, 'SQLite on .NET Core', 1);
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT *
|
||||
FROM blog;
|
||||
|
||||
SELECT *
|
||||
FROM post;
|
||||
";
|
||||
var reader = queryCommand.ExecuteReader();
|
||||
|
||||
// Read the first result set
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine($"Blog {reader["id"]}: {reader["name"]}");
|
||||
}
|
||||
|
||||
// Read the second result set
|
||||
reader.NextResult();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine($"Post {reader["id"]} in blog {reader["blog_id"]}: {reader["title"]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace BulkInsertSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE data (
|
||||
value INTEGER
|
||||
)
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
// There is no special API for inserting data in bulk. For the best performance,
|
||||
// follow this pattern.
|
||||
|
||||
Console.WriteLine("Inserting 150,000 rows...");
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
// Always use a transaction
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
var insertCommand = connection.CreateCommand();
|
||||
insertCommand.CommandText =
|
||||
@"
|
||||
INSERT INTO data
|
||||
VALUES ($value)
|
||||
";
|
||||
|
||||
// Re-use the same parameterized SqliteCommand
|
||||
var valueParameter = insertCommand.CreateParameter();
|
||||
valueParameter.ParameterName = "$value";
|
||||
insertCommand.Parameters.Add(valueParameter);
|
||||
|
||||
// No need to call Prepare() since it's done lazily during the first execution.
|
||||
//insertCommand.Prepare();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
for (int i = 0; i < 150_000; i++)
|
||||
{
|
||||
valueParameter.Value = random.Next();
|
||||
insertCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
Console.WriteLine($"Done. (took {stopwatch.ElapsedMilliseconds} ms)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace CollationSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE greek_letter (
|
||||
value TEXT
|
||||
);
|
||||
|
||||
INSERT INTO greek_letter
|
||||
VALUES ('Λ'),
|
||||
('λ');
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
// Without this, the query returns one since the built-in NOCASE collation only
|
||||
// handles ASCII characters (A-Z)
|
||||
connection.CreateCollation("NOCASE", (x, y) => string.Compare(x, y, ignoreCase: true));
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT count()
|
||||
FROM greek_letter
|
||||
WHERE value = 'λ' COLLATE NOCASE
|
||||
";
|
||||
var count = (long)queryCommand.ExecuteScalar();
|
||||
|
||||
Console.WriteLine($"Results: {count}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace DateAndTimeSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
// SQLite doesn't support primitive DateTime and TimeSpan values. Instead, it
|
||||
// provides date and time functions to help you perform operations based on strings
|
||||
// and Julian day values.
|
||||
|
||||
var dateTime1 = new DateTime(2017, 10, 20);
|
||||
var dateTime2 = new DateTime(2017, 10, 16);
|
||||
var timeSpan1 = new TimeSpan(1, 00, 0);
|
||||
var timeSpan2 = new TimeSpan(0, 30, 0);
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
SELECT
|
||||
|
||||
-- Comparisons work as expected
|
||||
$dateTime1 > $dateTime2,
|
||||
$timeSpan1 > $timeSpan2,
|
||||
|
||||
-- DateTime operations require converting to Julian days
|
||||
julianday($dateTime1) - julianday($dateTime2),
|
||||
|
||||
-- TimeSpan operations require REAL parameters
|
||||
$realTimeSpan1 - $realTimeSpan2,
|
||||
|
||||
-- More examples
|
||||
julianday($dateTime1) - $realTimeSpan1,
|
||||
$realTimeSpan1 / $realTimeSpan2,
|
||||
$realTimeSpan1 / 2.0
|
||||
";
|
||||
command.Parameters.AddWithValue("$dateTime1", dateTime1);
|
||||
command.Parameters.AddWithValue("$dateTime2", dateTime2);
|
||||
command.Parameters.AddWithValue("$timeSpan1", timeSpan1);
|
||||
command.Parameters.AddWithValue("$timeSpan2", timeSpan2);
|
||||
command.Parameters.Add("$realTimeSpan1", SqliteType.Real).Value = timeSpan1;
|
||||
command.Parameters.Add("$realTimeSpan2", SqliteType.Real).Value = timeSpan2;
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
var dateTimeComparison = reader.GetBoolean(0);
|
||||
Console.WriteLine($"{dateTime1} > {dateTime2} = {dateTimeComparison}");
|
||||
|
||||
var timeSpanComparison = reader.GetBoolean(1);
|
||||
Console.WriteLine($"{timeSpan1} > {timeSpan2} = {timeSpanComparison}");
|
||||
|
||||
var dateTimeDifference = reader.GetTimeSpan(2);
|
||||
Console.WriteLine($"{dateTime1} - {dateTime2} = {dateTimeDifference}");
|
||||
|
||||
var timeSpanDifference = reader.GetTimeSpan(3);
|
||||
Console.WriteLine($"{timeSpan1} - {timeSpan2} = {timeSpanDifference}");
|
||||
|
||||
var dateTimeSubtractTimeSpan = reader.GetDateTime(4);
|
||||
Console.WriteLine($"{dateTime1} - {timeSpan1} = {dateTimeSubtractTimeSpan}");
|
||||
|
||||
var timeSpanDividedByTimeSpan = reader.GetDouble(5);
|
||||
Console.WriteLine($"{timeSpan1} / {timeSpan2} = {timeSpanDividedByTimeSpan}");
|
||||
|
||||
var timeSpanDividedByDivisor = reader.GetTimeSpan(6);
|
||||
Console.WriteLine($"{timeSpan1} / 2.0 = {timeSpanDividedByDivisor}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace DirtyReadSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
// The connections must use a shared cache
|
||||
const string connectionString = "Data Source=DirtyReadSample;Mode=Memory;Cache=Shared";
|
||||
|
||||
var firstConnection = new SqliteConnection(connectionString);
|
||||
firstConnection.Open();
|
||||
|
||||
var createCommand = firstConnection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE data (
|
||||
value TEXT
|
||||
);
|
||||
|
||||
INSERT INTO data
|
||||
VALUES ('clean');
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
using (firstConnection.BeginTransaction())
|
||||
{
|
||||
var updateCommand = firstConnection.CreateCommand();
|
||||
updateCommand.CommandText =
|
||||
@"
|
||||
UPDATE data
|
||||
SET value = 'dirty'
|
||||
";
|
||||
updateCommand.ExecuteNonQuery();
|
||||
|
||||
var secondConnection = new SqliteConnection(connectionString);
|
||||
secondConnection.Open();
|
||||
|
||||
// Without ReadUncommitted, the command will time out since the table is locked
|
||||
// while the transaction on the first connection is active
|
||||
using (secondConnection.BeginTransaction(IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
var queryCommand = secondConnection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT *
|
||||
FROM data
|
||||
";
|
||||
var value = (string)queryCommand.ExecuteScalar();
|
||||
Console.WriteLine($"Value: {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_sqlcipher" Version="$(SQLitePCLRawBundleSqlcipherPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace EncryptionSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
const string connectionString = "Data Source=EncryptionSample.db";
|
||||
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
// Notice which packages are referenced by this project:
|
||||
// - Microsoft.Data.Sqlite.Core
|
||||
// - SQLitePCLRaw.bundle_sqlcipher
|
||||
|
||||
// Immediately after opening the connection, send PRAGMA key to use encryption
|
||||
var keyCommand = connection.CreateCommand();
|
||||
keyCommand.CommandText =
|
||||
@"
|
||||
PRAGMA key = 'password';
|
||||
";
|
||||
keyCommand.ExecuteNonQuery();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE data (
|
||||
value TEXT
|
||||
);
|
||||
|
||||
INSERT INTO data
|
||||
VALUES ('Hello, encryption!');
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
Console.Write("Password (it's 'password'): ");
|
||||
var password = Console.ReadLine();
|
||||
|
||||
// Sanitize the user input using the quote() function
|
||||
var quoteCommand = connection.CreateCommand();
|
||||
quoteCommand.CommandText =
|
||||
@"
|
||||
SELECT quote($value)
|
||||
";
|
||||
quoteCommand.Parameters.AddWithValue("$value", password);
|
||||
var quotedPassword = (string)quoteCommand.ExecuteScalar();
|
||||
|
||||
// PRAGMA statements can't be parameterized. We're forced to concatenate the
|
||||
// escaped user input
|
||||
var keyCommand = connection.CreateCommand();
|
||||
keyCommand.CommandText =
|
||||
$@"
|
||||
PRAGMA key = {quotedPassword}
|
||||
";
|
||||
keyCommand.ExecuteScalar();
|
||||
|
||||
try
|
||||
{
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT *
|
||||
FROM data
|
||||
";
|
||||
var data = (string)queryCommand.ExecuteScalar();
|
||||
Console.WriteLine(data);
|
||||
}
|
||||
catch (SqliteException ex) when (ex.SqliteErrorCode == SQLitePCL.raw.SQLITE_NOTADB)
|
||||
{
|
||||
Console.WriteLine("Access denied.");
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
File.Delete("EncryptionSample.db");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace InMemorySample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
// Using a name and a shared cache allows multiple connections to access the same
|
||||
// in-memory database
|
||||
const string connectionString = "Data Source=InMemorySample;Mode=Memory;Cache=Shared";
|
||||
|
||||
// The in-memory database only persists while a connection is open to it. To manage
|
||||
// its lifetime, keep one open connection around for as long as you need it.
|
||||
var masterConnection = new SqliteConnection(connectionString);
|
||||
masterConnection.Open();
|
||||
|
||||
var createCommand = masterConnection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE data (
|
||||
value TEXT
|
||||
)
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
using (var firstConnection = new SqliteConnection(connectionString))
|
||||
{
|
||||
firstConnection.Open();
|
||||
|
||||
var updateCommand = firstConnection.CreateCommand();
|
||||
updateCommand.CommandText =
|
||||
@"
|
||||
INSERT INTO data
|
||||
VALUES ('Hello, memory!')
|
||||
";
|
||||
updateCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (var secondConnection = new SqliteConnection(connectionString))
|
||||
{
|
||||
secondConnection.Open();
|
||||
var queryCommand = secondConnection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT *
|
||||
FROM data
|
||||
";
|
||||
var value = (string)queryCommand.ExecuteScalar();
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
|
||||
// After all the connections are closed, the database is deleted.
|
||||
masterConnection.Close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace InteropSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
// Get the underlying sqlite3 object
|
||||
var db = connection.Handle;
|
||||
SQLitePCL.raw.sqlite3_trace(
|
||||
db,
|
||||
(_, statement) => Console.WriteLine(statement),
|
||||
null);
|
||||
|
||||
// You could also use db.ptr to access the native sqlite3 struct to, for example,
|
||||
// invoke a [DllImport] method.
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT $value";
|
||||
command.Parameters.AddWithValue("$value", "Trace me!");
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
// Get the underlying sqlite3_stmt object
|
||||
var stmt = reader.Handle;
|
||||
var steps = SQLitePCL.raw.sqlite3_stmt_status(
|
||||
stmt,
|
||||
SQLitePCL.raw.SQLITE_STMTSTATUS_VM_STEP,
|
||||
resetFlg: 0);
|
||||
Console.WriteLine($"VM operations: {steps}");
|
||||
|
||||
// Likewise, use stmt.ptr to access the native sqlite3_stmt struct.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace RegularExpressionSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE user (
|
||||
name TEXT,
|
||||
bio TEXT
|
||||
);
|
||||
|
||||
INSERT INTO user
|
||||
VALUES ('Arthur', 'I put two spaces after my full stops. Always.'),
|
||||
('Brice', 'I used to double-space after periods. I stopped.');
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
// Registering this function enables the REGEXP operator
|
||||
connection.CreateFunction(
|
||||
"regexp",
|
||||
(string pattern, string input)
|
||||
=> Regex.IsMatch(input, pattern));
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT count()
|
||||
FROM user
|
||||
WHERE bio REGEXP '\w\. {2,}\w'
|
||||
";
|
||||
var count = (long)queryCommand.ExecuteScalar();
|
||||
|
||||
Console.WriteLine($"Double-spacers: {count}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace ResultMetadataSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE post (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL UNIQUE,
|
||||
body TEXT
|
||||
);
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT id AS post_id,
|
||||
title,
|
||||
body,
|
||||
random() AS random
|
||||
FROM post;
|
||||
";
|
||||
|
||||
var reader = queryCommand.ExecuteReader();
|
||||
|
||||
var schemaTable = reader.GetSchemaTable();
|
||||
foreach (DataRow column in schemaTable.Rows)
|
||||
{
|
||||
if ((bool)column[SchemaTableColumn.IsExpression])
|
||||
{
|
||||
Console.Write("(expression) ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write($"{column[SchemaTableColumn.BaseColumnName]} ");
|
||||
}
|
||||
|
||||
if ((bool)column[SchemaTableColumn.IsAliased])
|
||||
{
|
||||
Console.Write($"AS {column[SchemaTableColumn.ColumnName]} ");
|
||||
}
|
||||
|
||||
Console.Write($"{column["DataTypeName"]} ");
|
||||
|
||||
if (column[SchemaTableColumn.AllowDBNull] as bool? == false)
|
||||
{
|
||||
Console.Write("NOT NULL ");
|
||||
}
|
||||
|
||||
if (column[SchemaTableColumn.IsKey] as bool? == true)
|
||||
{
|
||||
Console.Write("PRIMARY KEY ");
|
||||
}
|
||||
|
||||
if (column[SchemaTableOptionalColumn.IsAutoIncrement] as bool? == true)
|
||||
{
|
||||
Console.Write("AUTOINCREMENT ");
|
||||
}
|
||||
|
||||
if (column[SchemaTableColumn.IsUnique] as bool? == true)
|
||||
{
|
||||
Console.Write("UNIQUE ");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace ScalarFunctionSample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var connection = new SqliteConnection("Data Source=:memory:");
|
||||
connection.Open();
|
||||
|
||||
var createCommand = connection.CreateCommand();
|
||||
createCommand.CommandText =
|
||||
@"
|
||||
CREATE TABLE cylinder (
|
||||
name TEXT,
|
||||
radius REAL,
|
||||
height REAL
|
||||
);
|
||||
|
||||
INSERT INTO cylinder
|
||||
VALUES ('1x2', 1.0, 2.0),
|
||||
('2x1', 2.0, 1.0);
|
||||
";
|
||||
createCommand.ExecuteNonQuery();
|
||||
|
||||
// SQLite will invoke this managed delegate. Debug it like you would any other code
|
||||
// by setting breakpoints, etc.
|
||||
connection.CreateFunction(
|
||||
"volume",
|
||||
(double radius, double height)
|
||||
=> Math.PI * Math.Pow(radius, 2) * height);
|
||||
|
||||
var queryCommand = connection.CreateCommand();
|
||||
queryCommand.CommandText =
|
||||
@"
|
||||
SELECT name,
|
||||
volume(radius, height) AS volume
|
||||
FROM cylinder
|
||||
ORDER BY volume DESC
|
||||
";
|
||||
|
||||
var reader = queryCommand.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine($"{reader["name"]}: {reader["volume"]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EFCore.Relational\EFCore.Relational.csproj" PrivateAssets="contentfiles;build" />
|
||||
<ProjectReference Include="..\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="$(MicrosoftDataSqliteCorePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopAnalyzersPackageVersion)" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace SQLitePCL
|
||||
{
|
||||
internal static class SQLitePCLExtensions
|
||||
{
|
||||
public static void Dispose2(this sqlite3 db)
|
||||
=> raw.sqlite3_close_v2(db);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal static class SqliteConnectionExtensions
|
||||
{
|
||||
public static int ExecuteNonQuery(
|
||||
this SqliteConnection connection,
|
||||
string commandText)
|
||||
{
|
||||
using (var command = connection.CreateCommand())
|
||||
{
|
||||
command.CommandText = commandText;
|
||||
|
||||
return command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
public static T ExecuteScalar<T>(
|
||||
this SqliteConnection connection,
|
||||
string commandText)
|
||||
=> (T)connection.ExecuteScalar(commandText);
|
||||
|
||||
private static object ExecuteScalar(this SqliteConnection connection, string commandText)
|
||||
{
|
||||
using (var command = connection.CreateCommand())
|
||||
{
|
||||
command.CommandText = commandText;
|
||||
|
||||
return command.ExecuteScalar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
public static bool IsNullable(this Type type)
|
||||
=> !type.IsValueType
|
||||
|| (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
|
||||
|
||||
public static Type UnwrapEnumType(this Type type)
|
||||
=> type.GetTypeInfo().IsEnum ? Enum.GetUnderlyingType(type) : type;
|
||||
|
||||
public static Type UnwrapNullableType(this Type type)
|
||||
=> Nullable.GetUnderlyingType(type) ?? type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Microsoft.Data.Sqlite</AssemblyName>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
<PackageId>Microsoft.Data.Sqlite.Core</PackageId>
|
||||
<Description>SQLite implementation of the System.Data.Common provider model.
|
||||
|
||||
Commonly Used Types:
|
||||
Microsoft.Data.Sqlite.SqliteCommand
|
||||
Microsoft.Data.Sqlite.SqliteConnection
|
||||
Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
|
||||
Microsoft.Data.Sqlite.SqliteDataReader
|
||||
Microsoft.Data.Sqlite.SqliteException
|
||||
Microsoft.Data.Sqlite.SqliteFactory
|
||||
Microsoft.Data.Sqlite.SqliteParameter
|
||||
Microsoft.Data.Sqlite.SqliteTransaction</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<MinClientVersion>3.6</MinClientVersion>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<CodeAnalysisRuleSet>Microsoft.Data.Sqlite.Core.ruleset</CodeAnalysisRuleSet>
|
||||
<PackageTags>SQLite;Data;ADO.NET</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Resources.Designer.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Update="SqliteConnection.CreateAggregate.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>SqliteConnection.CreateAggregate.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Update="SqliteConnection.CreateFunction.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>SqliteConnection.CreateFunction.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.core" Version="$(SQLitePCLRawCorePackageVersion)" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopAnalyzersPackageVersion)" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.Designer.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="SqliteCommand.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Update="SqliteConnection.CreateAggregate.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>SqliteConnection.CreateAggregate.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="SqliteConnection.CreateFunction.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>SqliteConnection.CreateFunction.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="SqliteConnection.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,145 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Rules for Microsoft.Data.Sqlite" Description="Code analysis rules for Microsoft.Data.Sqlite." ToolsVersion="14.0">
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA1000" Action="None" />
|
||||
<Rule Id="SA1001" Action="None" />
|
||||
<Rule Id="SA1002" Action="None" />
|
||||
<Rule Id="SA1003" Action="None" />
|
||||
<Rule Id="SA1004" Action="None" />
|
||||
<Rule Id="SA1005" Action="None" />
|
||||
<Rule Id="SA1006" Action="None" />
|
||||
<Rule Id="SA1007" Action="None" />
|
||||
<Rule Id="SA1008" Action="None" />
|
||||
<Rule Id="SA1009" Action="None" />
|
||||
<Rule Id="SA1010" Action="None" />
|
||||
<Rule Id="SA1011" Action="None" />
|
||||
<Rule Id="SA1012" Action="None" />
|
||||
<Rule Id="SA1013" Action="None" />
|
||||
<Rule Id="SA1014" Action="None" />
|
||||
<Rule Id="SA1015" Action="None" />
|
||||
<Rule Id="SA1016" Action="None" />
|
||||
<Rule Id="SA1017" Action="None" />
|
||||
<Rule Id="SA1018" Action="None" />
|
||||
<Rule Id="SA1019" Action="None" />
|
||||
<Rule Id="SA1020" Action="None" />
|
||||
<Rule Id="SA1021" Action="None" />
|
||||
<Rule Id="SA1022" Action="None" />
|
||||
<Rule Id="SA1023" Action="None" />
|
||||
<Rule Id="SA1024" Action="None" />
|
||||
<Rule Id="SA1025" Action="None" />
|
||||
<Rule Id="SA1026" Action="None" />
|
||||
<Rule Id="SA1027" Action="None" />
|
||||
<Rule Id="SA1028" Action="None" />
|
||||
<Rule Id="SA1100" Action="None" />
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1102" Action="None" />
|
||||
<Rule Id="SA1103" Action="None" />
|
||||
<Rule Id="SA1104" Action="None" />
|
||||
<Rule Id="SA1105" Action="None" />
|
||||
<Rule Id="SA1106" Action="None" />
|
||||
<Rule Id="SA1107" Action="None" />
|
||||
<Rule Id="SA1108" Action="None" />
|
||||
<Rule Id="SA1110" Action="None" />
|
||||
<Rule Id="SA1111" Action="None" />
|
||||
<Rule Id="SA1112" Action="None" />
|
||||
<Rule Id="SA1113" Action="None" />
|
||||
<Rule Id="SA1114" Action="None" />
|
||||
<Rule Id="SA1115" Action="None" />
|
||||
<Rule Id="SA1116" Action="None" />
|
||||
<Rule Id="SA1117" Action="None" />
|
||||
<Rule Id="SA1118" Action="None" />
|
||||
<Rule Id="SA1119" Action="None" />
|
||||
<Rule Id="SA1120" Action="None" />
|
||||
<Rule Id="SA1121" Action="None" />
|
||||
<Rule Id="SA1122" Action="None" />
|
||||
<Rule Id="SA1123" Action="None" />
|
||||
<Rule Id="SA1124" Action="None" />
|
||||
<Rule Id="SA1125" Action="None" />
|
||||
<Rule Id="SA1127" Action="None" />
|
||||
<Rule Id="SA1128" Action="None" />
|
||||
<Rule Id="SA1129" Action="None" />
|
||||
<Rule Id="SA1130" Action="None" />
|
||||
<Rule Id="SA1131" Action="None" />
|
||||
<Rule Id="SA1132" Action="None" />
|
||||
<Rule Id="SA1133" Action="None" />
|
||||
<Rule Id="SA1134" Action="None" />
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1201" Action="None" />
|
||||
<Rule Id="SA1202" Action="None" />
|
||||
<Rule Id="SA1203" Action="None" />
|
||||
<Rule Id="SA1204" Action="None" />
|
||||
<Rule Id="SA1205" Action="None" />
|
||||
<Rule Id="SA1206" Action="None" />
|
||||
<Rule Id="SA1207" Action="None" />
|
||||
<Rule Id="SA1208" Action="None" />
|
||||
<Rule Id="SA1209" Action="None" />
|
||||
<Rule Id="SA1210" Action="None" />
|
||||
<Rule Id="SA1211" Action="None" />
|
||||
<Rule Id="SA1212" Action="None" />
|
||||
<Rule Id="SA1213" Action="None" />
|
||||
<Rule Id="SA1214" Action="None" />
|
||||
<Rule Id="SA1216" Action="None" />
|
||||
<Rule Id="SA1217" Action="None" />
|
||||
<Rule Id="SA1300" Action="None" />
|
||||
<Rule Id="SA1302" Action="None" />
|
||||
<Rule Id="SA1303" Action="None" />
|
||||
<Rule Id="SA1304" Action="None" />
|
||||
<Rule Id="SA1306" Action="None" />
|
||||
<Rule Id="SA1307" Action="None" />
|
||||
<Rule Id="SA1308" Action="None" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1310" Action="None" />
|
||||
<Rule Id="SA1311" Action="None" />
|
||||
<Rule Id="SA1312" Action="None" />
|
||||
<Rule Id="SA1313" Action="None" />
|
||||
<Rule Id="SA1400" Action="None" />
|
||||
<Rule Id="SA1401" Action="None" />
|
||||
<Rule Id="SA1402" Action="None" />
|
||||
<Rule Id="SA1403" Action="None" />
|
||||
<Rule Id="SA1404" Action="None" />
|
||||
<Rule Id="SA1405" Action="None" />
|
||||
<Rule Id="SA1406" Action="None" />
|
||||
<Rule Id="SA1407" Action="None" />
|
||||
<Rule Id="SA1408" Action="None" />
|
||||
<Rule Id="SA1410" Action="None" />
|
||||
<Rule Id="SA1411" Action="None" />
|
||||
<Rule Id="SA1500" Action="None" />
|
||||
<Rule Id="SA1501" Action="None" />
|
||||
<Rule Id="SA1502" Action="None" />
|
||||
<Rule Id="SA1503" Action="None" />
|
||||
<Rule Id="SA1504" Action="None" />
|
||||
<Rule Id="SA1505" Action="None" />
|
||||
<Rule Id="SA1506" Action="None" />
|
||||
<Rule Id="SA1507" Action="None" />
|
||||
<Rule Id="SA1508" Action="None" />
|
||||
<Rule Id="SA1509" Action="None" />
|
||||
<Rule Id="SA1510" Action="None" />
|
||||
<Rule Id="SA1511" Action="None" />
|
||||
<Rule Id="SA1512" Action="None" />
|
||||
<Rule Id="SA1513" Action="None" />
|
||||
<Rule Id="SA1514" Action="None" />
|
||||
<Rule Id="SA1515" Action="None" />
|
||||
<Rule Id="SA1516" Action="None" />
|
||||
<Rule Id="SA1517" Action="None" />
|
||||
<Rule Id="SA1518" Action="None" />
|
||||
<Rule Id="SA1519" Action="None" />
|
||||
<Rule Id="SA1520" Action="None" />
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<Rule Id="SA1601" Action="None" />
|
||||
<Rule Id="SA1605" Action="None" />
|
||||
<Rule Id="SA1609" Action="Warning" />
|
||||
<Rule Id="SA1612" Action="None" />
|
||||
<Rule Id="SA1619" Action="None" />
|
||||
<Rule Id="SA1626" Action="None" />
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
<Rule Id="SA1634" Action="None" />
|
||||
<Rule Id="SA1635" Action="None" />
|
||||
<Rule Id="SA1636" Action="None" />
|
||||
<Rule Id="SA1637" Action="None" />
|
||||
<Rule Id="SA1638" Action="None" />
|
||||
<Rule Id="SA1640" Action="None" />
|
||||
<Rule Id="SA1641" Action="None" />
|
||||
<Rule Id="SA1649" Action="None" />
|
||||
<Rule Id="SA1652" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo(
|
||||
"Microsoft.Data.Sqlite.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
|
@ -0,0 +1,250 @@
|
|||
// <auto-generated />
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
namespace Microsoft.Data.Sqlite.Properties
|
||||
{
|
||||
internal static class Resources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.Data.Sqlite.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// {methodName} can only be called when the connection is open.
|
||||
/// </summary>
|
||||
public static string CallRequiresOpenConnection(object methodName)
|
||||
=> string.Format(
|
||||
GetString("CallRequiresOpenConnection", nameof(methodName)),
|
||||
methodName);
|
||||
|
||||
/// <summary>
|
||||
/// CommandText must be set before {methodName} can be called.
|
||||
/// </summary>
|
||||
public static string CallRequiresSetCommandText(object methodName)
|
||||
=> string.Format(
|
||||
GetString("CallRequiresSetCommandText", nameof(methodName)),
|
||||
methodName);
|
||||
|
||||
/// <summary>
|
||||
/// ConnectionString cannot be set when the connection is open.
|
||||
/// </summary>
|
||||
public static string ConnectionStringRequiresClosedConnection
|
||||
=> GetString("ConnectionStringRequiresClosedConnection");
|
||||
|
||||
/// <summary>
|
||||
/// Invalid attempt to call {operation} when reader is closed.
|
||||
/// </summary>
|
||||
public static string DataReaderClosed(object operation)
|
||||
=> string.Format(
|
||||
GetString("DataReaderClosed", nameof(operation)),
|
||||
operation);
|
||||
|
||||
/// <summary>
|
||||
/// The cache mode '{mode}' is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidCacheMode(object mode)
|
||||
=> string.Format(
|
||||
GetString("InvalidCacheMode", nameof(mode)),
|
||||
mode);
|
||||
|
||||
/// <summary>
|
||||
/// The CommandBehavior '{behavior}' is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidCommandBehavior(object behavior)
|
||||
=> string.Format(
|
||||
GetString("InvalidCommandBehavior", nameof(behavior)),
|
||||
behavior);
|
||||
|
||||
/// <summary>
|
||||
/// The CommandType '{commandType}' is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidCommandType(object commandType)
|
||||
=> string.Format(
|
||||
GetString("InvalidCommandType", nameof(commandType)),
|
||||
commandType);
|
||||
|
||||
/// <summary>
|
||||
/// The IsolationLevel '{isolationLevel}' is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidIsolationLevel(object isolationLevel)
|
||||
=> string.Format(
|
||||
GetString("InvalidIsolationLevel", nameof(isolationLevel)),
|
||||
isolationLevel);
|
||||
|
||||
/// <summary>
|
||||
/// The ParameterDirection '{direction}' is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidParameterDirection(object direction)
|
||||
=> string.Format(
|
||||
GetString("InvalidParameterDirection", nameof(direction)),
|
||||
direction);
|
||||
|
||||
/// <summary>
|
||||
/// Keyword not supported: '{keyword}'.
|
||||
/// </summary>
|
||||
public static string KeywordNotSupported(object keyword)
|
||||
=> string.Format(
|
||||
GetString("KeywordNotSupported", nameof(keyword)),
|
||||
keyword);
|
||||
|
||||
/// <summary>
|
||||
/// Must add values for the following parameters: {parameters}
|
||||
/// </summary>
|
||||
public static string MissingParameters(object parameters)
|
||||
=> string.Format(
|
||||
GetString("MissingParameters", nameof(parameters)),
|
||||
parameters);
|
||||
|
||||
/// <summary>
|
||||
/// No data exists for the row/column.
|
||||
/// </summary>
|
||||
public static string NoData
|
||||
=> GetString("NoData");
|
||||
|
||||
/// <summary>
|
||||
/// ConnectionString must be set before Open can be called.
|
||||
/// </summary>
|
||||
public static string OpenRequiresSetConnectionString
|
||||
=> GetString("OpenRequiresSetConnectionString");
|
||||
|
||||
/// <summary>
|
||||
/// SqliteConnection does not support nested transactions.
|
||||
/// </summary>
|
||||
public static string ParallelTransactionsNotSupported
|
||||
=> GetString("ParallelTransactionsNotSupported");
|
||||
|
||||
/// <summary>
|
||||
/// A SqliteParameter with ParameterName '{parameterName}' is not contained by this SqliteParameterCollection.
|
||||
/// </summary>
|
||||
public static string ParameterNotFound(object parameterName)
|
||||
=> string.Format(
|
||||
GetString("ParameterNotFound", nameof(parameterName)),
|
||||
parameterName);
|
||||
|
||||
/// <summary>
|
||||
/// {propertyName} must be set.
|
||||
/// </summary>
|
||||
public static string RequiresSet(object propertyName)
|
||||
=> string.Format(
|
||||
GetString("RequiresSet", nameof(propertyName)),
|
||||
propertyName);
|
||||
|
||||
/// <summary>
|
||||
/// This SqliteTransaction has completed; it is no longer usable.
|
||||
/// </summary>
|
||||
public static string TransactionCompleted
|
||||
=> GetString("TransactionCompleted");
|
||||
|
||||
/// <summary>
|
||||
/// The transaction object is not associated with the connection object.
|
||||
/// </summary>
|
||||
public static string TransactionConnectionMismatch
|
||||
=> GetString("TransactionConnectionMismatch");
|
||||
|
||||
/// <summary>
|
||||
/// Execute requires the command to have a transaction object when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.
|
||||
/// </summary>
|
||||
public static string TransactionRequired
|
||||
=> GetString("TransactionRequired");
|
||||
|
||||
/// <summary>
|
||||
/// No mapping exists from object type {typeName} to a known managed provider native type.
|
||||
/// </summary>
|
||||
public static string UnknownDataType(object typeName)
|
||||
=> string.Format(
|
||||
GetString("UnknownDataType", nameof(typeName)),
|
||||
typeName);
|
||||
|
||||
/// <summary>
|
||||
/// SQLite Error {errorCode}: '{message}'.
|
||||
/// </summary>
|
||||
public static string SqliteNativeError(object errorCode, object message)
|
||||
=> string.Format(
|
||||
GetString("SqliteNativeError", nameof(errorCode), nameof(message)),
|
||||
errorCode, message);
|
||||
|
||||
/// <summary>
|
||||
/// For more information on this error code see http://sqlite.org/rescode.html
|
||||
/// </summary>
|
||||
public static string DefaultNativeError
|
||||
=> GetString("DefaultNativeError");
|
||||
|
||||
/// <summary>
|
||||
/// Cannot bind the value for parameter '{parameterName}' because multiple matching parameters were found in the command text. Specify the parameter name with the symbol prefix, e.g. '@{parameterName}'.
|
||||
/// </summary>
|
||||
public static string AmbiguousParameterName(object parameterName)
|
||||
=> string.Format(
|
||||
GetString("AmbiguousParameterName", nameof(parameterName)),
|
||||
parameterName);
|
||||
|
||||
/// <summary>
|
||||
/// The SQLite library is already loaded. UseWinSqlite3 must be called before using SQLite.
|
||||
/// </summary>
|
||||
public static string AlreadyLoaded
|
||||
=> GetString("AlreadyLoaded");
|
||||
|
||||
/// <summary>
|
||||
/// The {enumType} enumeration value, {value}, is invalid.
|
||||
/// </summary>
|
||||
public static string InvalidEnumValue(object enumType, object value)
|
||||
=> string.Format(
|
||||
GetString("InvalidEnumValue", nameof(enumType), nameof(value)),
|
||||
enumType, value);
|
||||
|
||||
/// <summary>
|
||||
/// Cannot convert object of type '{sourceType}' to object of type '{targetType}'.
|
||||
/// </summary>
|
||||
public static string ConvertFailed(object sourceType, object targetType)
|
||||
=> string.Format(
|
||||
GetString("ConvertFailed", nameof(sourceType), nameof(targetType)),
|
||||
sourceType, targetType);
|
||||
|
||||
/// <summary>
|
||||
/// Cannot store 'NaN' values.
|
||||
/// </summary>
|
||||
public static string CannotStoreNaN
|
||||
=> GetString("CannotStoreNaN");
|
||||
|
||||
/// <summary>
|
||||
/// An open reader is already associated with this command. Close it before opening a new one.
|
||||
/// </summary>
|
||||
public static string DataReaderOpen
|
||||
=> GetString("DataReaderOpen");
|
||||
|
||||
/// <summary>
|
||||
/// An open reader is associated with this command. Close it before changing the {propertyName} property.
|
||||
/// </summary>
|
||||
public static string SetRequiresNoOpenReader(object propertyName)
|
||||
=> string.Format(
|
||||
GetString("SetRequiresNoOpenReader", nameof(propertyName)),
|
||||
propertyName);
|
||||
|
||||
/// <summary>
|
||||
/// The data is NULL at ordinal {ordinal}. This method can't be called on NULL values. Check using IsDBNull before calling.
|
||||
/// </summary>
|
||||
public static string CalledOnNullValue(object ordinal)
|
||||
=> string.Format(
|
||||
GetString("CalledOnNullValue", nameof(ordinal)),
|
||||
ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// The SQL function '{function}' was called with a NULL argument at ordinal {ordinal}. Create the function using a Nullable parameter or rewrite your query to avoid passing NULL.
|
||||
/// </summary>
|
||||
public static string UDFCalledWithNull(object function, object ordinal)
|
||||
=> string.Format(
|
||||
GetString("UDFCalledWithNull", nameof(function), nameof(ordinal)),
|
||||
function, ordinal);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<#
|
||||
Session["ResourceFile"] = "Resources.resx";
|
||||
#>
|
||||
<#@ include file="..\..\..\tools\SqliteResources.tt" #>
|
|
@ -0,0 +1,213 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CallRequiresOpenConnection" xml:space="preserve">
|
||||
<value>{methodName} can only be called when the connection is open.</value>
|
||||
</data>
|
||||
<data name="CallRequiresSetCommandText" xml:space="preserve">
|
||||
<value>CommandText must be set before {methodName} can be called.</value>
|
||||
</data>
|
||||
<data name="ConnectionStringRequiresClosedConnection" xml:space="preserve">
|
||||
<value>ConnectionString cannot be set when the connection is open.</value>
|
||||
</data>
|
||||
<data name="DataReaderClosed" xml:space="preserve">
|
||||
<value>Invalid attempt to call {operation} when reader is closed.</value>
|
||||
</data>
|
||||
<data name="InvalidCacheMode" xml:space="preserve">
|
||||
<value>The cache mode '{mode}' is invalid.</value>
|
||||
</data>
|
||||
<data name="InvalidCommandBehavior" xml:space="preserve">
|
||||
<value>The CommandBehavior '{behavior}' is invalid.</value>
|
||||
</data>
|
||||
<data name="InvalidCommandType" xml:space="preserve">
|
||||
<value>The CommandType '{commandType}' is invalid.</value>
|
||||
</data>
|
||||
<data name="InvalidIsolationLevel" xml:space="preserve">
|
||||
<value>The IsolationLevel '{isolationLevel}' is invalid.</value>
|
||||
</data>
|
||||
<data name="InvalidParameterDirection" xml:space="preserve">
|
||||
<value>The ParameterDirection '{direction}' is invalid.</value>
|
||||
</data>
|
||||
<data name="KeywordNotSupported" xml:space="preserve">
|
||||
<value>Keyword not supported: '{keyword}'.</value>
|
||||
</data>
|
||||
<data name="MissingParameters" xml:space="preserve">
|
||||
<value>Must add values for the following parameters: {parameters}</value>
|
||||
</data>
|
||||
<data name="NoData" xml:space="preserve">
|
||||
<value>No data exists for the row/column.</value>
|
||||
</data>
|
||||
<data name="OpenRequiresSetConnectionString" xml:space="preserve">
|
||||
<value>ConnectionString must be set before Open can be called.</value>
|
||||
</data>
|
||||
<data name="ParallelTransactionsNotSupported" xml:space="preserve">
|
||||
<value>SqliteConnection does not support nested transactions.</value>
|
||||
</data>
|
||||
<data name="ParameterNotFound" xml:space="preserve">
|
||||
<value>A SqliteParameter with ParameterName '{parameterName}' is not contained by this SqliteParameterCollection.</value>
|
||||
</data>
|
||||
<data name="RequiresSet" xml:space="preserve">
|
||||
<value>{propertyName} must be set.</value>
|
||||
</data>
|
||||
<data name="TransactionCompleted" xml:space="preserve">
|
||||
<value>This SqliteTransaction has completed; it is no longer usable.</value>
|
||||
</data>
|
||||
<data name="TransactionConnectionMismatch" xml:space="preserve">
|
||||
<value>The transaction object is not associated with the connection object.</value>
|
||||
</data>
|
||||
<data name="TransactionRequired" xml:space="preserve">
|
||||
<value>Execute requires the command to have a transaction object when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.</value>
|
||||
</data>
|
||||
<data name="UnknownDataType" xml:space="preserve">
|
||||
<value>No mapping exists from object type {typeName} to a known managed provider native type.</value>
|
||||
</data>
|
||||
<data name="SqliteNativeError" xml:space="preserve">
|
||||
<value>SQLite Error {errorCode}: '{message}'.</value>
|
||||
</data>
|
||||
<data name="DefaultNativeError" xml:space="preserve">
|
||||
<value>For more information on this error code see http://sqlite.org/rescode.html</value>
|
||||
</data>
|
||||
<data name="AmbiguousParameterName" xml:space="preserve">
|
||||
<value>Cannot bind the value for parameter '{parameterName}' because multiple matching parameters were found in the command text. Specify the parameter name with the symbol prefix, e.g. '@{parameterName}'.</value>
|
||||
</data>
|
||||
<data name="AlreadyLoaded" xml:space="preserve">
|
||||
<value>The SQLite library is already loaded. UseWinSqlite3 must be called before using SQLite.</value>
|
||||
</data>
|
||||
<data name="InvalidEnumValue" xml:space="preserve">
|
||||
<value>The {enumType} enumeration value, {value}, is invalid.</value>
|
||||
</data>
|
||||
<data name="ConvertFailed" xml:space="preserve">
|
||||
<value>Cannot convert object of type '{sourceType}' to object of type '{targetType}'.</value>
|
||||
</data>
|
||||
<data name="CannotStoreNaN" xml:space="preserve">
|
||||
<value>Cannot store 'NaN' values.</value>
|
||||
</data>
|
||||
<data name="DataReaderOpen" xml:space="preserve">
|
||||
<value>An open reader is already associated with this command. Close it before opening a new one.</value>
|
||||
</data>
|
||||
<data name="SetRequiresNoOpenReader" xml:space="preserve">
|
||||
<value>An open reader is associated with this command. Close it before changing the {propertyName} property.</value>
|
||||
</data>
|
||||
<data name="CalledOnNullValue" xml:space="preserve">
|
||||
<value>The data is NULL at ordinal {ordinal}. This method can't be called on NULL values. Check using IsDBNull before calling.</value>
|
||||
</data>
|
||||
<data name="UDFCalledWithNull" xml:space="preserve">
|
||||
<value>The SQL function '{function}' was called with a NULL argument at ordinal {ordinal}. Create the function using a Nullable parameter or rewrite your query to avoid passing NULL.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the caching modes that can be used when creating a new <see cref="SqliteConnection" />.
|
||||
/// </summary>
|
||||
/// <seealso href="http://sqlite.org/sharedcache.html">SQLite Shared-Cache Mode</seealso>
|
||||
public enum SqliteCacheMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Default mode.
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// Private-cache mode. Each connection uses a private cache.
|
||||
/// </summary>
|
||||
Private,
|
||||
|
||||
/// <summary>
|
||||
/// Shared-cache mode. Connections share a cache. This mode can change the behavior of transaction and table
|
||||
/// locking.
|
||||
/// </summary>
|
||||
Shared
|
||||
}
|
||||
}
|
|
@ -0,0 +1,588 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a SQL statement to be executed against a SQLite database.
|
||||
/// </summary>
|
||||
public class SqliteCommand : DbCommand
|
||||
{
|
||||
private readonly Lazy<SqliteParameterCollection> _parameters = new Lazy<SqliteParameterCollection>(
|
||||
() => new SqliteParameterCollection());
|
||||
|
||||
private readonly ICollection<sqlite3_stmt> _preparedStatements = new List<sqlite3_stmt>();
|
||||
private SqliteConnection _connection;
|
||||
private string _commandText;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
|
||||
/// </summary>
|
||||
public SqliteCommand()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
|
||||
/// </summary>
|
||||
/// <param name="commandText">The SQL to execute against the database.</param>
|
||||
public SqliteCommand(string commandText)
|
||||
=> CommandText = commandText;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
|
||||
/// </summary>
|
||||
/// <param name="commandText">The SQL to execute against the database.</param>
|
||||
/// <param name="connection">The connection used by the command.</param>
|
||||
public SqliteCommand(string commandText, SqliteConnection connection)
|
||||
: this(commandText)
|
||||
{
|
||||
Connection = connection;
|
||||
CommandTimeout = connection.DefaultTimeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
|
||||
/// </summary>
|
||||
/// <param name="commandText">The SQL to execute against the database.</param>
|
||||
/// <param name="connection">The connection used by the command.</param>
|
||||
/// <param name="transaction">The transaction within which the command executes.</param>
|
||||
public SqliteCommand(string commandText, SqliteConnection connection, SqliteTransaction transaction)
|
||||
: this(commandText, connection)
|
||||
=> Transaction = transaction;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating how <see cref="CommandText" /> is interpreted. Only
|
||||
/// <see cref="CommandType.Text" /> is supported.
|
||||
/// </summary>
|
||||
/// <value>A value indicating how <see cref="CommandText" /> is interpreted.</value>
|
||||
public override CommandType CommandType
|
||||
{
|
||||
get => CommandType.Text;
|
||||
set
|
||||
{
|
||||
if (value != CommandType.Text)
|
||||
{
|
||||
throw new ArgumentException(Resources.InvalidCommandType(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the SQL to execute against the database.
|
||||
/// </summary>
|
||||
/// <value>The SQL to execute against the database.</value>
|
||||
public override string CommandText
|
||||
{
|
||||
get => _commandText;
|
||||
set
|
||||
{
|
||||
if (DataReader != null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(CommandText)));
|
||||
}
|
||||
|
||||
if (value != _commandText)
|
||||
{
|
||||
DisposePreparedStatements();
|
||||
_commandText = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection used by the command.
|
||||
/// </summary>
|
||||
/// <value>The connection used by the command.</value>
|
||||
public new virtual SqliteConnection Connection
|
||||
{
|
||||
get => _connection;
|
||||
set
|
||||
{
|
||||
if (DataReader != null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(Connection)));
|
||||
}
|
||||
|
||||
if (value != _connection)
|
||||
{
|
||||
DisposePreparedStatements();
|
||||
|
||||
_connection?.RemoveCommand(this);
|
||||
_connection = value;
|
||||
value?.AddCommand(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection used by the command. Must be a <see cref="SqliteConnection" />.
|
||||
/// </summary>
|
||||
/// <value>The connection used by the command.</value>
|
||||
protected override DbConnection DbConnection
|
||||
{
|
||||
get => Connection;
|
||||
set => Connection = (SqliteConnection)value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction within which the command executes.
|
||||
/// </summary>
|
||||
/// <value>The transaction within which the command executes.</value>
|
||||
public new virtual SqliteTransaction Transaction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction within which the command executes. Must be a <see cref="SqliteTransaction" />.
|
||||
/// </summary>
|
||||
/// <value>The transaction within which the command executes.</value>
|
||||
protected override DbTransaction DbTransaction
|
||||
{
|
||||
get => Transaction;
|
||||
set => Transaction = (SqliteTransaction)value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of parameters used by the command.
|
||||
/// </summary>
|
||||
/// <value>The collection of parameters used by the command.</value>
|
||||
public new virtual SqliteParameterCollection Parameters
|
||||
=> _parameters.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of parameters used by the command.
|
||||
/// </summary>
|
||||
/// <value>The collection of parameters used by the command.</value>
|
||||
protected override DbParameterCollection DbParameterCollection
|
||||
=> Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of seconds to wait before terminating the attempt to execute the command. Defaults to 30.
|
||||
/// </summary>
|
||||
/// <value>The number of seconds to wait before terminating the attempt to execute the command.</value>
|
||||
/// <remarks>
|
||||
/// The timeout is used when the command is waiting to obtain a lock on the table.
|
||||
/// </remarks>
|
||||
public override int CommandTimeout { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the command should be visible in an interface control.
|
||||
/// </summary>
|
||||
/// <value>A value indicating whether the command should be visible in an interface control.</value>
|
||||
public override bool DesignTimeVisible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating how the results are applied to the row being updated.
|
||||
/// </summary>
|
||||
/// <value>A value indicating how the results are applied to the row being updated.</value>
|
||||
public override UpdateRowSource UpdatedRowSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data reader currently being used by the command, or null if none.
|
||||
/// </summary>
|
||||
/// <value>The data reader currently being used by the command.</value>
|
||||
protected internal virtual SqliteDataReader DataReader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Releases any resources used by the connection and closes it.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
DisposePreparedStatements(disposing);
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter.
|
||||
/// </summary>
|
||||
/// <returns>The new parameter.</returns>
|
||||
public new virtual SqliteParameter CreateParameter()
|
||||
=> new SqliteParameter();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter.
|
||||
/// </summary>
|
||||
/// <returns>The new parameter.</returns>
|
||||
protected override DbParameter CreateDbParameter()
|
||||
=> CreateParameter();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a prepared version of the command on the database.
|
||||
/// </summary>
|
||||
public override void Prepare()
|
||||
{
|
||||
if (_connection?.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(Prepare)));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_commandText))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(Prepare)));
|
||||
}
|
||||
|
||||
if (_preparedStatements.Count != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var timer = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
using (var enumerator = PrepareAndEnumerateStatements(timer).GetEnumerator())
|
||||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
DisposePreparedStatements();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <returns>The data reader.</returns>
|
||||
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
|
||||
public new virtual SqliteDataReader ExecuteReader()
|
||||
=> ExecuteReader(CommandBehavior.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="behavior">
|
||||
/// A description of the results of the query and its effect on the database.
|
||||
/// <para>
|
||||
/// Only <see cref="CommandBehavior.Default" />, <see cref="CommandBehavior.SequentialAccess" />,
|
||||
/// <see cref="CommandBehavior.SingleResult" />, <see cref="CommandBehavior.SingleRow" />, and
|
||||
/// <see cref="CommandBehavior.CloseConnection" /> are supported.
|
||||
/// </para>
|
||||
/// </param>
|
||||
/// <returns>The data reader.</returns>
|
||||
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
|
||||
public new virtual SqliteDataReader ExecuteReader(CommandBehavior behavior)
|
||||
{
|
||||
if ((behavior & ~(CommandBehavior.Default | CommandBehavior.SequentialAccess | CommandBehavior.SingleResult
|
||||
| CommandBehavior.SingleRow | CommandBehavior.CloseConnection)) != 0)
|
||||
{
|
||||
throw new ArgumentException(Resources.InvalidCommandBehavior(behavior));
|
||||
}
|
||||
|
||||
if (DataReader != null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderOpen);
|
||||
}
|
||||
|
||||
if (_connection?.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteReader)));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_commandText))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteReader)));
|
||||
}
|
||||
|
||||
if (Transaction != _connection.Transaction)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
Transaction == null
|
||||
? Resources.TransactionRequired
|
||||
: Resources.TransactionConnectionMismatch);
|
||||
}
|
||||
if (_connection.Transaction?.ExternalRollback == true)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.TransactionCompleted);
|
||||
}
|
||||
|
||||
var hasChanges = false;
|
||||
var changes = 0;
|
||||
int rc;
|
||||
var stmts = new Queue<(sqlite3_stmt, bool)>();
|
||||
var unprepared = _preparedStatements.Count == 0;
|
||||
var timer = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var stmt in unprepared
|
||||
? PrepareAndEnumerateStatements(timer)
|
||||
: _preparedStatements)
|
||||
{
|
||||
var boundParams = 0;
|
||||
|
||||
if (_parameters.IsValueCreated)
|
||||
{
|
||||
boundParams = _parameters.Value.Bind(stmt);
|
||||
}
|
||||
|
||||
var expectedParams = raw.sqlite3_bind_parameter_count(stmt);
|
||||
if (expectedParams != boundParams)
|
||||
{
|
||||
var unboundParams = new List<string>();
|
||||
for (var i = 1; i <= expectedParams; i++)
|
||||
{
|
||||
var name = raw.sqlite3_bind_parameter_name(stmt, i);
|
||||
|
||||
if (_parameters.IsValueCreated
|
||||
|| !_parameters.Value.Cast<SqliteParameter>().Any(p => p.ParameterName == name))
|
||||
{
|
||||
unboundParams.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(Resources.MissingParameters(string.Join(", ", unboundParams)));
|
||||
}
|
||||
|
||||
while (IsBusy(rc = raw.sqlite3_step(stmt)))
|
||||
{
|
||||
if (timer.ElapsedMilliseconds >= CommandTimeout * 1000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
raw.sqlite3_reset(stmt);
|
||||
|
||||
// TODO: Consider having an async path that uses Task.Delay()
|
||||
Thread.Sleep(150);
|
||||
}
|
||||
|
||||
SqliteException.ThrowExceptionForRC(rc, _connection.Handle);
|
||||
|
||||
if (rc == raw.SQLITE_ROW
|
||||
// NB: This is only a heuristic to separate SELECT statements from INSERT/UPDATE/DELETE statements.
|
||||
// It will result in false positives, but it's the best we can do without re-parsing SQL
|
||||
|| raw.sqlite3_stmt_readonly(stmt) != 0)
|
||||
{
|
||||
stmts.Enqueue((stmt, rc != raw.SQLITE_DONE));
|
||||
}
|
||||
else
|
||||
{
|
||||
raw.sqlite3_reset(stmt);
|
||||
hasChanges = true;
|
||||
changes += raw.sqlite3_changes(_connection.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch when (unprepared)
|
||||
{
|
||||
DisposePreparedStatements();
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
var closeConnection = (behavior & CommandBehavior.CloseConnection) != 0;
|
||||
|
||||
return DataReader = new SqliteDataReader(this, stmts, hasChanges ? changes : -1, closeConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="behavior">A description of query's results and its effect on the database.</param>
|
||||
/// <returns>The data reader.</returns>
|
||||
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
|
||||
=> ExecuteReader(behavior);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <remarks>
|
||||
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
|
||||
/// </remarks>
|
||||
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
|
||||
public new virtual Task<SqliteDataReader> ExecuteReaderAsync()
|
||||
=> ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <remarks>
|
||||
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
|
||||
/// </remarks>
|
||||
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
|
||||
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(CancellationToken cancellationToken)
|
||||
=> ExecuteReaderAsync(CommandBehavior.Default, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="behavior">A description of query's results and its effect on the database.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <remarks>
|
||||
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
|
||||
/// </remarks>
|
||||
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
|
||||
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(CommandBehavior behavior)
|
||||
=> ExecuteReaderAsync(behavior, CancellationToken.None);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="behavior">A description of query's results and its effect on the database.</param>
|
||||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <remarks>
|
||||
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
|
||||
/// </remarks>
|
||||
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
|
||||
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(
|
||||
CommandBehavior behavior,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
return Task.FromResult(ExecuteReader(behavior));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
|
||||
/// </summary>
|
||||
/// <param name="behavior">A description of query's results and its effect on the database.</param>
|
||||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(
|
||||
CommandBehavior behavior,
|
||||
CancellationToken cancellationToken)
|
||||
=> await ExecuteReaderAsync(behavior, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> against the database.
|
||||
/// </summary>
|
||||
/// <returns>The number of rows inserted, updated, or deleted. -1 for SELECT statements.</returns>
|
||||
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
|
||||
public override int ExecuteNonQuery()
|
||||
{
|
||||
if (_connection?.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteNonQuery)));
|
||||
}
|
||||
if (_commandText == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteNonQuery)));
|
||||
}
|
||||
|
||||
var reader = ExecuteReader();
|
||||
reader.Dispose();
|
||||
|
||||
return reader.RecordsAffected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the <see cref="CommandText" /> against the database and returns the result.
|
||||
/// </summary>
|
||||
/// <returns>The first column of the first row of the results, or null if no results.</returns>
|
||||
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
|
||||
public override object ExecuteScalar()
|
||||
{
|
||||
if (_connection?.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteScalar)));
|
||||
}
|
||||
if (_commandText == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteScalar)));
|
||||
}
|
||||
|
||||
using (var reader = ExecuteReader())
|
||||
{
|
||||
return reader.Read()
|
||||
? reader.GetValue(0)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cancel the execution of the command. Does nothing.
|
||||
/// </summary>
|
||||
public override void Cancel()
|
||||
{
|
||||
}
|
||||
|
||||
private IEnumerable<sqlite3_stmt> PrepareAndEnumerateStatements(Stopwatch timer)
|
||||
{
|
||||
int rc;
|
||||
sqlite3_stmt stmt;
|
||||
var tail = _commandText;
|
||||
do
|
||||
{
|
||||
string nextTail;
|
||||
while (IsBusy(rc = raw.sqlite3_prepare_v2(_connection.Handle, tail, out stmt, out nextTail)))
|
||||
{
|
||||
if (timer.ElapsedMilliseconds >= CommandTimeout * 1000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(150);
|
||||
}
|
||||
tail = nextTail;
|
||||
|
||||
SqliteException.ThrowExceptionForRC(rc, _connection.Handle);
|
||||
|
||||
// Statement was empty, white space, or a comment
|
||||
if (stmt.ptr == IntPtr.Zero)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tail))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_preparedStatements.Add(stmt);
|
||||
|
||||
yield return stmt;
|
||||
}
|
||||
while (!string.IsNullOrEmpty(tail));
|
||||
}
|
||||
|
||||
private void DisposePreparedStatements(bool disposing = true)
|
||||
{
|
||||
if (disposing
|
||||
&& DataReader != null)
|
||||
{
|
||||
DataReader.Dispose();
|
||||
DataReader = null;
|
||||
}
|
||||
|
||||
if (_preparedStatements != null)
|
||||
{
|
||||
foreach (var stmt in _preparedStatements)
|
||||
{
|
||||
stmt.Dispose();
|
||||
}
|
||||
|
||||
_preparedStatements.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsBusy(int rc)
|
||||
=> rc == raw.SQLITE_LOCKED
|
||||
|| rc == raw.SQLITE_BUSY
|
||||
|| rc == raw.SQLITE_LOCKED_SHAREDCACHE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,999 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
partial class SqliteConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate>(string name, Func<TAccumulate, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 0, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, TAccumulate>(string name, Func<TAccumulate, T1, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 1, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, TAccumulate>(string name, Func<TAccumulate, T1, T2, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 2, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 3, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 4, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 5, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 6, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 7, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 8, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 9, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 10, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 11, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 12, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 13, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 14, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 15, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate>(string name, Func<TAccumulate, object[], TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, -1, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 0, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 2, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 3, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 4, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 5, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 6, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 7, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 8, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 9, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 10, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 11, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 12, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 13, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 14, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 15, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, object[], TAccumulate> func, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, -1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), a => a, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 0, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 2, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 3, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 4, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 5, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 6, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 7, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 8, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 9, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 10, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 11, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 12, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 13, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 14, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, 15, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), resultSelector, isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, object[], TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, -1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), resultSelector, isDeterministic);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
partial class SqliteConnection
|
||||
{
|
||||
<#
|
||||
var ordinal = new[] { "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth" };
|
||||
|
||||
var first = true;
|
||||
foreach (var resultSelector in new[] { false, true })
|
||||
{
|
||||
var resultTypeArgument = resultSelector
|
||||
? ", TResult"
|
||||
: "";
|
||||
|
||||
var resultSelectorParameter = resultSelector
|
||||
? ", Func<TAccumulate, TResult> resultSelector"
|
||||
: "";
|
||||
|
||||
var resultSelectorArgument = resultSelector
|
||||
? "resultSelector"
|
||||
: "a => a";
|
||||
|
||||
foreach (var seed in new[] { false, true })
|
||||
{
|
||||
if (resultSelector && !seed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var seedParameter = seed
|
||||
? ", TAccumulate seed"
|
||||
: "";
|
||||
|
||||
var seedArgument = seed
|
||||
? "seed"
|
||||
: "default";
|
||||
|
||||
for (var arity = 0; arity <= 15; arity++)
|
||||
{
|
||||
var parameterTypeArgumentList = Enumerable.Range(1, arity).Select(j => "T" + j).ToList();
|
||||
|
||||
var typeArgumentsList = new List<string>();
|
||||
typeArgumentsList.AddRange(parameterTypeArgumentList);
|
||||
typeArgumentsList.Add("TAccumulate");
|
||||
|
||||
if (resultSelector)
|
||||
{
|
||||
typeArgumentsList.Add("TResult");
|
||||
}
|
||||
|
||||
var typeArguments = String.Join(", ", typeArgumentsList);
|
||||
|
||||
var lambdaTypeArgumentList = new List<string>();
|
||||
lambdaTypeArgumentList.Add("TAccumulate");
|
||||
lambdaTypeArgumentList.AddRange(parameterTypeArgumentList);
|
||||
lambdaTypeArgumentList.Add("TAccumulate");
|
||||
|
||||
var lambdaTypeArguments = string.Join(", ", lambdaTypeArgumentList);
|
||||
|
||||
var lambdaArgumentsList = new List<string>();
|
||||
|
||||
lambdaArgumentsList.Add("a");
|
||||
|
||||
for (var i = 0; i < parameterTypeArgumentList.Count; i++)
|
||||
{
|
||||
lambdaArgumentsList.Add("r.GetFieldValue<" + parameterTypeArgumentList[i] + ">(" + i + ")");
|
||||
}
|
||||
|
||||
var lambdaArguments = string.Join(", ", lambdaArgumentsList);
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine("");
|
||||
}
|
||||
#>
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
<# for (var i = 1; i <= arity; i++) { #>
|
||||
/// <typeparam name="T<#= i #>">The type of the <#= ordinal[i - 1] #> parameter of the function.</typeparam>
|
||||
<# } #>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
<# if (resultSelector) { #>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
<# } #>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
<# if (seed) { #>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
<# } #>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
<# if (resultSelector) { #>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
<# } #>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<<#= typeArguments #>>(string name<#= seedParameter #>, Func<<#= lambdaTypeArguments #>> func<#= resultSelectorParameter #>, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, <#= arity #>, <#= seedArgument #>, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(<#= lambdaArguments #>)), <#= resultSelectorArgument #>, isDeterministic);
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines an aggregate SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
|
||||
<# if (resultSelector) { #>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
<# } #>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
<# if (seed) { #>
|
||||
/// <param name="seed">The initial accumulator value.</param>
|
||||
<# } #>
|
||||
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
|
||||
<# if (resultSelector) { #>
|
||||
/// <param name="resultSelector">
|
||||
/// A function to transform the final accumulator value into the result value. Pass null to
|
||||
/// delete a function.
|
||||
/// </param>
|
||||
<# } #>
|
||||
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
|
||||
public virtual void CreateAggregate<TAccumulate<#= resultTypeArgument #>>(string name<#= seedParameter #>, Func<TAccumulate, object[], TAccumulate> func<#= resultSelectorParameter #>, bool isDeterministic = false)
|
||||
=> CreateAggregateCore(name, -1, <#= seedArgument #>, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), <#= resultSelectorArgument #>, isDeterministic);
|
||||
<#
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,650 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
partial class SqliteConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TResult>(string name, Func<TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 0, null, IfNotNull<object, TResult>(function, (s, r) => function()), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, TResult>(string name, Func<T1, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 1, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, TResult>(string name, Func<T1, T2, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 2, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, TResult>(string name, Func<T1, T2, T3, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 3, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 4, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, TResult>(string name, Func<T1, T2, T3, T4, T5, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 5, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 6, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 7, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 8, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 9, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 10, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 11, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 12, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 13, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 14, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 15, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T16">The type of the sixteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 16, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14), r.GetFieldValue<T16>(15))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TResult>(string name, Func<object[], TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, -1, null, IfNotNull<object, TResult>(function, (s, r) => function(GetValues(r))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, TResult>(string name, TState state, Func<TState, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 0, state, IfNotNull<TState, TResult>(function, (s, r) => function(s)), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, TResult>(string name, TState state, Func<TState, T1, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 1, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, TResult>(string name, TState state, Func<TState, T1, T2, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 2, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, TResult>(string name, TState state, Func<TState, T1, T2, T3, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 3, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 4, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 5, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 6, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 7, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 8, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 9, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 10, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 11, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 12, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 13, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 14, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
|
||||
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, 15, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), isDeterministic);
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<TState, TResult>(string name, TState state, Func<TState, object[], TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, -1, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, GetValues(r))), isDeterministic);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
partial class SqliteConnection
|
||||
{
|
||||
<#
|
||||
var ordinal = new[] { "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth" };
|
||||
|
||||
var first = true;
|
||||
foreach (var state in new[] { false, true })
|
||||
{
|
||||
var maxArguments = state
|
||||
? 15
|
||||
: 16;
|
||||
|
||||
var stateTypeArgument = state
|
||||
? "TState, "
|
||||
: "";
|
||||
|
||||
var stateParameter = state
|
||||
? "TState state, "
|
||||
: "";
|
||||
|
||||
var stateArgument = state
|
||||
? "state"
|
||||
: "null";
|
||||
|
||||
var stateParameterType = state
|
||||
? "TState"
|
||||
: "object";
|
||||
|
||||
var lambdaStateArgument = state
|
||||
? "s, "
|
||||
: "";
|
||||
|
||||
for (var arity = 0; arity <= maxArguments; arity++)
|
||||
{
|
||||
var parameterTypeArgumentList = Enumerable.Range(1, arity).Select(j => "T" + j).ToList();
|
||||
|
||||
var typeArgumentsList = new List<string>();
|
||||
|
||||
if (state)
|
||||
{
|
||||
typeArgumentsList.Add("TState");
|
||||
}
|
||||
|
||||
typeArgumentsList.AddRange(parameterTypeArgumentList);
|
||||
typeArgumentsList.Add("TResult");
|
||||
|
||||
var typeArguments = String.Join(", ", typeArgumentsList);
|
||||
|
||||
var lambdaArgumentsList = new List<string>();
|
||||
|
||||
if (state)
|
||||
{
|
||||
lambdaArgumentsList.Add("s");
|
||||
}
|
||||
|
||||
for (var i = 0; i < parameterTypeArgumentList.Count; i++)
|
||||
{
|
||||
lambdaArgumentsList.Add("r.GetFieldValue<" + parameterTypeArgumentList[i] + ">(" + i + ")");
|
||||
}
|
||||
|
||||
var lambdaArguments = string.Join(", ", lambdaArgumentsList);
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine("");
|
||||
}
|
||||
#>
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
<# if (state) { #>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
<# } #>
|
||||
<# for (var i = 1; i <= arity; i++) { #>
|
||||
/// <typeparam name="T<#= i #>">The type of the <#= ordinal[i - 1] #> parameter of the function.</typeparam>
|
||||
<# } #>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
<# if (state) { #>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
<# } #>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<<#= typeArguments #>>(string name, <#= stateParameter #>Func<<#= typeArguments #>> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, <#= arity #>, <#= stateArgument #>, IfNotNull<<#= stateParameterType #>, TResult>(function, (s, r) => function(<#= lambdaArguments #>)), isDeterministic);
|
||||
<#
|
||||
}
|
||||
|
||||
#>
|
||||
|
||||
/// <summary>
|
||||
/// Creates or redefines a SQL function.
|
||||
/// </summary>
|
||||
<# if (state) { #>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
<# } #>
|
||||
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
|
||||
/// <param name="name">The name of the SQL function.</param>
|
||||
<# if (state) { #>
|
||||
/// <param name="state">An object available during each invocation of the function.</param>
|
||||
<# } #>
|
||||
/// <param name="function">The function to be invoked.</param>
|
||||
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
|
||||
public virtual void CreateFunction<<#= stateTypeArgument #>TResult>(string name, <#= stateParameter #>Func<<#= stateTypeArgument #>object[], TResult> function, bool isDeterministic = false)
|
||||
=> CreateFunctionCore(name, -1, <#= stateArgument #>, IfNotNull<<#= stateParameterType #>, TResult>(function, (s, r) => function(<#= lambdaStateArgument #>GetValues(r))), isDeterministic);
|
||||
<#
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,621 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using Microsoft.Data.Sqlite.Utilities;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a connection to a SQLite database.
|
||||
/// </summary>
|
||||
public partial class SqliteConnection : DbConnection
|
||||
{
|
||||
private const string MainDatabaseName = "main";
|
||||
|
||||
private readonly IList<WeakReference<SqliteCommand>> _commands = new List<WeakReference<SqliteCommand>>();
|
||||
|
||||
private string _connectionString;
|
||||
private ConnectionState _state;
|
||||
private sqlite3 _db;
|
||||
|
||||
static SqliteConnection()
|
||||
=> BundleInitializer.Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteConnection" /> class.
|
||||
/// </summary>
|
||||
public SqliteConnection()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteConnection" /> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The string used to open the connection.</param>
|
||||
/// <seealso cref="SqliteConnectionStringBuilder" />
|
||||
public SqliteConnection(string connectionString)
|
||||
=> ConnectionString = connectionString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a handle to underlying database connection.
|
||||
/// </summary>
|
||||
/// <value>A handle to underlying database connection.</value>
|
||||
/// <seealso href="http://sqlite.org/c3ref/sqlite3.html">Database Connection Handle</seealso>
|
||||
public virtual sqlite3 Handle
|
||||
=> _db;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a string used to open the connection.
|
||||
/// </summary>
|
||||
/// <value>A string used to open the connection.</value>
|
||||
/// <seealso cref="SqliteConnectionStringBuilder" />
|
||||
public override string ConnectionString
|
||||
{
|
||||
get => _connectionString;
|
||||
set
|
||||
{
|
||||
if (State != ConnectionState.Closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.ConnectionStringRequiresClosedConnection);
|
||||
}
|
||||
|
||||
_connectionString = value;
|
||||
ConnectionStringBuilder = new SqliteConnectionStringBuilder(value);
|
||||
}
|
||||
}
|
||||
|
||||
internal SqliteConnectionStringBuilder ConnectionStringBuilder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the current database. Always 'main'.
|
||||
/// </summary>
|
||||
/// <value>The name of the current database.</value>
|
||||
public override string Database
|
||||
=> MainDatabaseName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the database file. Will be absolute for open connections.
|
||||
/// </summary>
|
||||
/// <value>The path to the database file.</value>
|
||||
public override string DataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
string dataSource = null;
|
||||
if (State == ConnectionState.Open)
|
||||
{
|
||||
dataSource = raw.sqlite3_db_filename(_db, MainDatabaseName);
|
||||
}
|
||||
|
||||
return dataSource ?? ConnectionStringBuilder.DataSource;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default <see cref="SqliteCommand.CommandTimeout"/> value for commands created using
|
||||
/// this connection. This is also used for internal commands in methods like
|
||||
/// <see cref="BeginTransaction()"/>.
|
||||
/// </summary>
|
||||
/// <value>The default <see cref="SqliteCommand.CommandTimeout"/> value</value>
|
||||
public virtual int DefaultTimeout { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of SQLite used by the connection.
|
||||
/// </summary>
|
||||
/// <value>The version of SQLite used by the connection.</value>
|
||||
public override string ServerVersion
|
||||
=> raw.sqlite3_libversion();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state of the connection.
|
||||
/// </summary>
|
||||
/// <value>The current state of the connection.</value>
|
||||
public override ConnectionState State
|
||||
=> _state;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DbProviderFactory" /> for this connection.
|
||||
/// </summary>
|
||||
/// <value>The <see cref="DbProviderFactory" />.</value>
|
||||
protected override DbProviderFactory DbProviderFactory
|
||||
=> SqliteFactory.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction currently being used by the connection, or null if none.
|
||||
/// </summary>
|
||||
/// <value>The transaction currently being used by the connection.</value>
|
||||
protected internal virtual SqliteTransaction Transaction { get; set; }
|
||||
|
||||
private void SetState(ConnectionState value)
|
||||
{
|
||||
var originalState = _state;
|
||||
if (originalState != value)
|
||||
{
|
||||
_state = value;
|
||||
OnStateChange(new StateChangeEventArgs(originalState, value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a connection to the database using the value of <see cref="ConnectionString" />. If
|
||||
/// <c>Mode=ReadWriteCreate</c> is used (the default) the file is created, if it doesn't already exist.
|
||||
/// </summary>
|
||||
/// <exception cref="SqliteException">A SQLite error occurs while opening the connection.</exception>
|
||||
public override void Open()
|
||||
{
|
||||
if (State == ConnectionState.Open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (ConnectionString == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.OpenRequiresSetConnectionString);
|
||||
}
|
||||
|
||||
var filename = ConnectionStringBuilder.DataSource;
|
||||
var flags = 0;
|
||||
|
||||
if (filename.StartsWith("file:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
flags |= raw.SQLITE_OPEN_URI;
|
||||
}
|
||||
|
||||
switch (ConnectionStringBuilder.Mode)
|
||||
{
|
||||
case SqliteOpenMode.ReadOnly:
|
||||
flags |= raw.SQLITE_OPEN_READONLY;
|
||||
break;
|
||||
|
||||
case SqliteOpenMode.ReadWrite:
|
||||
flags |= raw.SQLITE_OPEN_READWRITE;
|
||||
break;
|
||||
|
||||
case SqliteOpenMode.Memory:
|
||||
flags |= raw.SQLITE_OPEN_READWRITE | raw.SQLITE_OPEN_CREATE | raw.SQLITE_OPEN_MEMORY;
|
||||
if ((flags & raw.SQLITE_OPEN_URI) == 0)
|
||||
{
|
||||
flags |= raw.SQLITE_OPEN_URI;
|
||||
filename = "file:" + filename;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(
|
||||
ConnectionStringBuilder.Mode == SqliteOpenMode.ReadWriteCreate,
|
||||
"ConnectionStringBuilder.Mode is not ReadWriteCreate");
|
||||
flags |= raw.SQLITE_OPEN_READWRITE | raw.SQLITE_OPEN_CREATE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ConnectionStringBuilder.Cache)
|
||||
{
|
||||
case SqliteCacheMode.Shared:
|
||||
flags |= raw.SQLITE_OPEN_SHAREDCACHE;
|
||||
break;
|
||||
|
||||
case SqliteCacheMode.Private:
|
||||
flags |= raw.SQLITE_OPEN_PRIVATECACHE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(
|
||||
ConnectionStringBuilder.Cache == SqliteCacheMode.Default,
|
||||
"ConnectionStringBuilder.Cache is not Default.");
|
||||
break;
|
||||
}
|
||||
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
|
||||
if (!string.IsNullOrEmpty(dataDirectory)
|
||||
&& (flags & raw.SQLITE_OPEN_URI) == 0
|
||||
&& !filename.Equals(":memory:", StringComparison.OrdinalIgnoreCase)
|
||||
&& !Path.IsPathRooted(filename))
|
||||
{
|
||||
filename = Path.Combine(dataDirectory, filename);
|
||||
}
|
||||
|
||||
var rc = raw.sqlite3_open_v2(filename, out _db, flags, vfs: null);
|
||||
SqliteException.ThrowExceptionForRC(rc, _db);
|
||||
|
||||
SetState(ConnectionState.Open);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the connection to the database. Open transactions are rolled back.
|
||||
/// </summary>
|
||||
public override void Close()
|
||||
{
|
||||
if (_db == null
|
||||
|| _db.ptr == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction?.Dispose();
|
||||
|
||||
foreach (var reference in _commands)
|
||||
{
|
||||
if (reference.TryGetTarget(out var command))
|
||||
{
|
||||
command.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
_commands.Clear();
|
||||
|
||||
_db.Dispose2();
|
||||
_db = null;
|
||||
SetState(ConnectionState.Closed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases any resources used by the connection and closes it.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new command associated with the connection.
|
||||
/// </summary>
|
||||
/// <returns>The new command.</returns>
|
||||
/// <remarks>
|
||||
/// The command's <seealso cref="SqliteCommand.Transaction" /> property will also be set to the current
|
||||
/// transaction.
|
||||
/// </remarks>
|
||||
public new virtual SqliteCommand CreateCommand()
|
||||
=> new SqliteCommand { Connection = this, CommandTimeout = DefaultTimeout, Transaction = Transaction };
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new command associated with the connection.
|
||||
/// </summary>
|
||||
/// <returns>The new command.</returns>
|
||||
protected override DbCommand CreateDbCommand()
|
||||
=> CreateCommand();
|
||||
|
||||
internal void AddCommand(SqliteCommand command)
|
||||
=> _commands.Add(new WeakReference<SqliteCommand>(command));
|
||||
|
||||
internal void RemoveCommand(SqliteCommand command)
|
||||
{
|
||||
for (var i = _commands.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!_commands[i].TryGetTarget(out var item)
|
||||
|| item == command)
|
||||
{
|
||||
_commands.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create custom collation.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the collation.</param>
|
||||
/// <param name="comparison">Method that compares two strings.</param>
|
||||
public virtual void CreateCollation(string name, Comparison<string> comparison)
|
||||
=> CreateCollation(name, null, comparison != null ? (_, s1, s2) => comparison(s1, s2) : (Func<object, string, string, int>)null);
|
||||
|
||||
/// <summary>
|
||||
/// Create custom collation.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the state object.</typeparam>
|
||||
/// <param name="name">Name of the collation.</param>
|
||||
/// <param name="state">State object passed to each invocation of the collation.</param>
|
||||
/// <param name="comparison">Method that compares two strings, using additional state.</param>
|
||||
public virtual void CreateCollation<T>(string name, T state, Func<T, string, string, int> comparison)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
if (State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateCollation)));
|
||||
}
|
||||
|
||||
var collation = comparison != null ? (v, s1, s2) => comparison((T)v, s1, s2) : (delegate_collation)null;
|
||||
var rc = raw.sqlite3_create_collation(_db, name, state, collation);
|
||||
SqliteException.ThrowExceptionForRC(rc, _db);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins a transaction on the connection.
|
||||
/// </summary>
|
||||
/// <returns>The transaction.</returns>
|
||||
public new virtual SqliteTransaction BeginTransaction()
|
||||
=> BeginTransaction(IsolationLevel.Unspecified);
|
||||
|
||||
/// <summary>
|
||||
/// Begins a transaction on the connection.
|
||||
/// </summary>
|
||||
/// <param name="isolationLevel">The isolation level of the transaction.</param>
|
||||
/// <returns>The transaction.</returns>
|
||||
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
|
||||
=> BeginTransaction(isolationLevel);
|
||||
|
||||
/// <summary>
|
||||
/// Begins a transaction on the connection.
|
||||
/// </summary>
|
||||
/// <param name="isolationLevel">The isolation level of the transaction.</param>
|
||||
/// <returns>The transaction.</returns>
|
||||
public new virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel)
|
||||
{
|
||||
if (State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BeginTransaction)));
|
||||
}
|
||||
if (Transaction != null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.ParallelTransactionsNotSupported);
|
||||
}
|
||||
|
||||
return Transaction = new SqliteTransaction(this, isolationLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current database. Not supported.
|
||||
/// </summary>
|
||||
/// <param name="databaseName">The name of the database to use.</param>
|
||||
/// <exception cref="NotSupportedException">Always.</exception>
|
||||
public override void ChangeDatabase(string databaseName)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// Enables extension loading on the connection.
|
||||
/// </summary>
|
||||
/// <param name="enable">true to enable; false to disable</param>
|
||||
/// <seealso href="http://sqlite.org/loadext.html">Run-Time Loadable Extensions</seealso>
|
||||
public virtual void EnableExtensions(bool enable = true)
|
||||
{
|
||||
if (_db == null
|
||||
|| _db.ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(EnableExtensions)));
|
||||
}
|
||||
|
||||
var rc = raw.sqlite3_enable_load_extension(_db, enable ? 1 : 0);
|
||||
SqliteException.ThrowExceptionForRC(rc, _db);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backup of the connected database.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination of the backup.</param>
|
||||
public virtual void BackupDatabase(SqliteConnection destination)
|
||||
=> BackupDatabase(destination, MainDatabaseName, MainDatabaseName);
|
||||
|
||||
/// <summary>
|
||||
/// Backup of the connected database.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination of the backup.</param>
|
||||
/// <param name="destinationName">The name of the destination database.</param>
|
||||
/// <param name="sourceName">The name of the source database.</param>
|
||||
public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName)
|
||||
{
|
||||
if (_db == null
|
||||
|| _db.ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BackupDatabase)));
|
||||
}
|
||||
if (destination == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
}
|
||||
|
||||
var close = false;
|
||||
if (destination.State != ConnectionState.Open)
|
||||
{
|
||||
destination.Open();
|
||||
close = true;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (var backup = raw.sqlite3_backup_init(destination._db, destinationName, _db, sourceName))
|
||||
{
|
||||
int rc;
|
||||
if (backup.ptr == IntPtr.Zero)
|
||||
{
|
||||
rc = raw.sqlite3_errcode(destination._db);
|
||||
SqliteException.ThrowExceptionForRC(rc, destination._db);
|
||||
}
|
||||
|
||||
rc = raw.sqlite3_backup_step(backup, -1);
|
||||
SqliteException.ThrowExceptionForRC(rc, destination._db);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (close)
|
||||
{
|
||||
destination.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateFunctionCore<TState, TResult>(
|
||||
string name,
|
||||
int arity,
|
||||
TState state,
|
||||
Func<TState, SqliteValueReader, TResult> function,
|
||||
bool isDeterministic)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
if (State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateFunction)));
|
||||
}
|
||||
|
||||
delegate_function_scalar func = null;
|
||||
if (function != null)
|
||||
{
|
||||
func = (ctx, user_data, args) =>
|
||||
{
|
||||
// TODO: Avoid allocation when niladic
|
||||
var values = new SqliteParameterReader(name, args);
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Avoid closure by passing function via user_data
|
||||
var result = function((TState)user_data, values);
|
||||
|
||||
new SqliteResultBinder(ctx, result).Bind();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
raw.sqlite3_result_error(ctx, ex.Message);
|
||||
|
||||
if (ex is SqliteException sqlEx)
|
||||
{
|
||||
// NB: This must be called after sqlite3_result_error()
|
||||
raw.sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var rc = raw.sqlite3_create_function(
|
||||
_db,
|
||||
name,
|
||||
arity,
|
||||
isDeterministic ? raw.SQLITE_DETERMINISTIC : 0,
|
||||
state,
|
||||
func);
|
||||
SqliteException.ThrowExceptionForRC(rc, _db);
|
||||
}
|
||||
|
||||
private void CreateAggregateCore<TAccumulate, TResult>(
|
||||
string name,
|
||||
int arity,
|
||||
TAccumulate seed,
|
||||
Func<TAccumulate, SqliteValueReader, TAccumulate> func,
|
||||
Func<TAccumulate, TResult> resultSelector,
|
||||
bool isDeterministic)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
if (State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateAggregate)));
|
||||
}
|
||||
|
||||
delegate_function_aggregate_step func_step = null;
|
||||
if (func != null)
|
||||
{
|
||||
func_step = (ctx, user_data, args) =>
|
||||
{
|
||||
var context = (AggregateContext<TAccumulate>)user_data;
|
||||
if (context.Exception != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Avoid allocation when niladic
|
||||
var reader = new SqliteParameterReader(name, args);
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Avoid closure by passing func via user_data
|
||||
// NB: No need to set ctx.state since we just mutate the instance
|
||||
context.Accumulate = func(context.Accumulate, reader);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.Exception = ex;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
delegate_function_aggregate_final func_final = null;
|
||||
if (resultSelector != null)
|
||||
{
|
||||
func_final = (ctx, user_data) =>
|
||||
{
|
||||
var context = (AggregateContext<TAccumulate>)user_data;
|
||||
|
||||
if (context.Exception == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Avoid closure by passing resultSelector via user_data
|
||||
var result = resultSelector(context.Accumulate);
|
||||
|
||||
new SqliteResultBinder(ctx, result).Bind();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.Exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Exception != null)
|
||||
{
|
||||
raw.sqlite3_result_error(ctx, context.Exception.Message);
|
||||
|
||||
if (context.Exception is SqliteException sqlEx)
|
||||
{
|
||||
// NB: This must be called after sqlite3_result_error()
|
||||
raw.sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var rc = raw.sqlite3_create_function(
|
||||
_db,
|
||||
name,
|
||||
arity,
|
||||
isDeterministic ? raw.SQLITE_DETERMINISTIC : 0,
|
||||
new AggregateContext<TAccumulate>(seed),
|
||||
func_step,
|
||||
func_final);
|
||||
SqliteException.ThrowExceptionForRC(rc, _db);
|
||||
}
|
||||
|
||||
private static Func<TState, SqliteValueReader, TResult> IfNotNull<TState, TResult>(
|
||||
object x,
|
||||
Func<TState, SqliteValueReader, TResult> value)
|
||||
=> x != null ? value : null;
|
||||
|
||||
private static object[] GetValues(SqliteValueReader reader)
|
||||
{
|
||||
var values = new object[reader.FieldCount];
|
||||
reader.GetValues(values);
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private class AggregateContext<T>
|
||||
{
|
||||
public AggregateContext(T seed)
|
||||
=> Accumulate = seed;
|
||||
|
||||
public T Accumulate { get; set; }
|
||||
public Exception Exception { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,317 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a simple way to create and manage the contents of connection strings used by
|
||||
/// <see cref="SqliteConnection" />.
|
||||
/// </summary>
|
||||
public class SqliteConnectionStringBuilder : DbConnectionStringBuilder
|
||||
{
|
||||
private const string DataSourceKeyword = "Data Source";
|
||||
private const string DataSourceNoSpaceKeyword = "DataSource";
|
||||
private const string ModeKeyword = "Mode";
|
||||
private const string CacheKeyword = "Cache";
|
||||
private const string FilenameKeyword = "Filename";
|
||||
|
||||
private enum Keywords
|
||||
{
|
||||
DataSource,
|
||||
Mode,
|
||||
Cache
|
||||
}
|
||||
|
||||
private static readonly IReadOnlyList<string> _validKeywords;
|
||||
private static readonly IReadOnlyDictionary<string, Keywords> _keywords;
|
||||
|
||||
private string _dataSource = string.Empty;
|
||||
private SqliteOpenMode _mode = SqliteOpenMode.ReadWriteCreate;
|
||||
private SqliteCacheMode _cache = SqliteCacheMode.Default;
|
||||
|
||||
static SqliteConnectionStringBuilder()
|
||||
{
|
||||
var validKeywords = new string[3];
|
||||
validKeywords[(int)Keywords.DataSource] = DataSourceKeyword;
|
||||
validKeywords[(int)Keywords.Mode] = ModeKeyword;
|
||||
validKeywords[(int)Keywords.Cache] = CacheKeyword;
|
||||
_validKeywords = validKeywords;
|
||||
|
||||
_keywords = new Dictionary<string, Keywords>(3, StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
[DataSourceKeyword] = Keywords.DataSource,
|
||||
[ModeKeyword] = Keywords.Mode,
|
||||
[CacheKeyword] = Keywords.Cache,
|
||||
|
||||
// aliases
|
||||
[FilenameKeyword] = Keywords.DataSource,
|
||||
[DataSourceNoSpaceKeyword] = Keywords.DataSource
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteConnectionStringBuilder" /> class.
|
||||
/// </summary>
|
||||
public SqliteConnectionStringBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteConnectionStringBuilder" /> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">
|
||||
/// The initial connection string the builder will represent. Can be null.
|
||||
/// </param>
|
||||
public SqliteConnectionStringBuilder(string connectionString)
|
||||
=> ConnectionString = connectionString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the database file.
|
||||
/// </summary>
|
||||
/// <value>The database file.</value>
|
||||
public virtual string DataSource
|
||||
{
|
||||
get => _dataSource;
|
||||
set => base[DataSourceKeyword] = _dataSource = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection mode.
|
||||
/// </summary>
|
||||
/// <value>The connection mode.</value>
|
||||
public virtual SqliteOpenMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set => base[ModeKeyword] = _mode = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the keys used by the connection string.
|
||||
/// </summary>
|
||||
/// <value>A collection containing the keys used by the connection string.</value>
|
||||
public override ICollection Keys
|
||||
=> new ReadOnlyCollection<string>((string[])_validKeywords);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the values used by the connection string.
|
||||
/// </summary>
|
||||
/// <value>A collection containing the values used by the connection string.</value>
|
||||
public override ICollection Values
|
||||
{
|
||||
get
|
||||
{
|
||||
var values = new object[_validKeywords.Count];
|
||||
for (var i = 0; i < _validKeywords.Count; i++)
|
||||
{
|
||||
values[i] = GetAt((Keywords)i);
|
||||
}
|
||||
|
||||
return new ReadOnlyCollection<object>(values);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the caching mode used by the connection.
|
||||
/// </summary>
|
||||
/// <value>The caching mode used by the connection.</value>
|
||||
/// <seealso href="http://sqlite.org/sharedcache.html">SQLite Shared-Cache Mode</seealso>
|
||||
public virtual SqliteCacheMode Cache
|
||||
{
|
||||
get => _cache;
|
||||
set => base[CacheKeyword] = _cache = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value associated with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="keyword">The key.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public override object this[string keyword]
|
||||
{
|
||||
get => GetAt(GetIndex(keyword));
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Remove(keyword);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GetIndex(keyword))
|
||||
{
|
||||
case Keywords.DataSource:
|
||||
DataSource = Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
return;
|
||||
|
||||
case Keywords.Mode:
|
||||
Mode = ConvertToEnum<SqliteOpenMode>(value);
|
||||
return;
|
||||
|
||||
case Keywords.Cache:
|
||||
Cache = ConvertToEnum<SqliteCacheMode>(value);
|
||||
return;
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected keyword: " + keyword);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TEnum ConvertToEnum<TEnum>(object value)
|
||||
where TEnum : struct
|
||||
{
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return (TEnum)Enum.Parse(typeof(TEnum), stringValue, ignoreCase: true);
|
||||
}
|
||||
|
||||
if (value is TEnum enumValue)
|
||||
{
|
||||
enumValue = (TEnum)value;
|
||||
}
|
||||
else if (value.GetType().GetTypeInfo().IsEnum)
|
||||
{
|
||||
throw new ArgumentException(Resources.ConvertFailed(value.GetType(), typeof(TEnum)));
|
||||
}
|
||||
else
|
||||
{
|
||||
enumValue = (TEnum)Enum.ToObject(typeof(TEnum), value);
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(typeof(TEnum), enumValue))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(value),
|
||||
value,
|
||||
Resources.InvalidEnumValue(typeof(TEnum), enumValue));
|
||||
}
|
||||
|
||||
return enumValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the contents of the builder.
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
|
||||
for (var i = 0; i < _validKeywords.Count; i++)
|
||||
{
|
||||
Reset((Keywords)i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified key is used by the connection string.
|
||||
/// </summary>
|
||||
/// <param name="keyword">The key to look for.</param>
|
||||
/// <returns>true if it is use; otherwise, false.</returns>
|
||||
public override bool ContainsKey(string keyword)
|
||||
=> _keywords.ContainsKey(keyword);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified key and its value from the connection string.
|
||||
/// </summary>
|
||||
/// <param name="keyword">The key to remove.</param>
|
||||
/// <returns>true if the key was used; otherwise, false.</returns>
|
||||
public override bool Remove(string keyword)
|
||||
{
|
||||
if (!_keywords.TryGetValue(keyword, out var index)
|
||||
|| !base.Remove(_validKeywords[(int)index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Reset(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified key should be serialized into the connection string.
|
||||
/// </summary>
|
||||
/// <param name="keyword">The key to check.</param>
|
||||
/// <returns>true if it should be serialized; otherwise, false.</returns>
|
||||
public override bool ShouldSerialize(string keyword)
|
||||
=> _keywords.TryGetValue(keyword, out var index) && base.ShouldSerialize(_validKeywords[(int)index]);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified key if it is used.
|
||||
/// </summary>
|
||||
/// <param name="keyword">The key.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>true if the key was used; otherwise, false.</returns>
|
||||
public override bool TryGetValue(string keyword, out object value)
|
||||
{
|
||||
if (!_keywords.TryGetValue(keyword, out var index))
|
||||
{
|
||||
value = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
value = GetAt(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private object GetAt(Keywords index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case Keywords.DataSource:
|
||||
return DataSource;
|
||||
|
||||
case Keywords.Mode:
|
||||
return Mode;
|
||||
|
||||
case Keywords.Cache:
|
||||
return Cache;
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected keyword: " + index);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Keywords GetIndex(string keyword)
|
||||
=> !_keywords.TryGetValue(keyword, out var index)
|
||||
? throw new ArgumentException(Resources.KeywordNotSupported(keyword))
|
||||
: index;
|
||||
|
||||
private void Reset(Keywords index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case Keywords.DataSource:
|
||||
_dataSource = string.Empty;
|
||||
return;
|
||||
|
||||
case Keywords.Mode:
|
||||
_mode = SqliteOpenMode.ReadWriteCreate;
|
||||
return;
|
||||
|
||||
case Keywords.Cache:
|
||||
_cache = SqliteCacheMode.Default;
|
||||
return;
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected keyword: " + index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,585 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for reading the result of a command executed against a SQLite database.
|
||||
/// </summary>
|
||||
public class SqliteDataReader : DbDataReader
|
||||
{
|
||||
private readonly SqliteCommand _command;
|
||||
private readonly bool _closeConnection;
|
||||
private readonly Queue<(sqlite3_stmt stmt, bool)> _stmtQueue;
|
||||
private sqlite3_stmt _stmt;
|
||||
private SqliteDataRecord _record;
|
||||
private bool _hasRows;
|
||||
private bool _stepped;
|
||||
private bool _done;
|
||||
private bool _closed;
|
||||
|
||||
internal SqliteDataReader(
|
||||
SqliteCommand command,
|
||||
Queue<(sqlite3_stmt, bool)> stmtQueue,
|
||||
int recordsAffected,
|
||||
bool closeConnection)
|
||||
{
|
||||
if (stmtQueue.Count != 0)
|
||||
{
|
||||
(_stmt, _hasRows) = stmtQueue.Dequeue();
|
||||
_record = new SqliteDataRecord(_stmt);
|
||||
}
|
||||
|
||||
_command = command;
|
||||
_stmtQueue = stmtQueue;
|
||||
RecordsAffected = recordsAffected;
|
||||
_closeConnection = closeConnection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the depth of nesting for the current row. Always zero.
|
||||
/// </summary>
|
||||
/// <value>The depth of nesting for the current row.</value>
|
||||
public override int Depth
|
||||
=> 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of columns in the current row.
|
||||
/// </summary>
|
||||
/// <value>The number of columns in the current row.</value>
|
||||
public override int FieldCount
|
||||
=> _closed
|
||||
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(FieldCount)))
|
||||
: _record.FieldCount;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a handle to underlying prepared statement.
|
||||
/// </summary>
|
||||
/// <value>A handle to underlying prepared statement.</value>
|
||||
/// <seealso href="http://sqlite.org/c3ref/stmt.html">Prepared Statement Object</seealso>
|
||||
public virtual sqlite3_stmt Handle
|
||||
=> _stmt;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the data reader contains any rows.
|
||||
/// </summary>
|
||||
/// <value>A value indicating whether the data reader contains any rows.</value>
|
||||
public override bool HasRows
|
||||
=> _hasRows;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the data reader is closed.
|
||||
/// </summary>
|
||||
/// <value>A value indicating whether the data reader is closed.</value>
|
||||
public override bool IsClosed
|
||||
=> _closed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of rows inserted, updated, or deleted. -1 for SELECT statements.
|
||||
/// </summary>
|
||||
/// <value>The number of rows inserted, updated, or deleted.</value>
|
||||
public override int RecordsAffected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the column. The value is case-sensitive.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public override object this[string name]
|
||||
=> _record[name];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public override object this[int ordinal]
|
||||
=> _record[ordinal];
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator that can be used to iterate through the rows in the data reader.
|
||||
/// </summary>
|
||||
/// <returns>The enumerator.</returns>
|
||||
public override IEnumerator GetEnumerator()
|
||||
=> new DbEnumerator(this, closeReader: false);
|
||||
|
||||
/// <summary>
|
||||
/// Advances to the next row in the result set.
|
||||
/// </summary>
|
||||
/// <returns>true if there are more rows; otherwise, false.</returns>
|
||||
public override bool Read()
|
||||
{
|
||||
if (_closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(Read)));
|
||||
}
|
||||
|
||||
if (!_stepped)
|
||||
{
|
||||
_stepped = true;
|
||||
|
||||
return _hasRows;
|
||||
}
|
||||
|
||||
var rc = raw.sqlite3_step(_stmt);
|
||||
SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle);
|
||||
_record.Clear();
|
||||
|
||||
_done = rc == raw.SQLITE_DONE;
|
||||
|
||||
return !_done;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advances to the next result set for batched statements.
|
||||
/// </summary>
|
||||
/// <returns>true if there are more result sets; otherwise, false.</returns>
|
||||
public override bool NextResult()
|
||||
{
|
||||
if (_stmtQueue.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
raw.sqlite3_reset(_stmt);
|
||||
|
||||
(_stmt, _hasRows) = _stmtQueue.Dequeue();
|
||||
_record = new SqliteDataRecord(_stmt);
|
||||
_stepped = false;
|
||||
_done = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the data reader.
|
||||
/// </summary>
|
||||
public override void Close()
|
||||
=> Dispose(true);
|
||||
|
||||
/// <summary>
|
||||
/// Releases any resources used by the data reader and closes it.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_command.DataReader = null;
|
||||
|
||||
if (_stmt != null)
|
||||
{
|
||||
raw.sqlite3_reset(_stmt);
|
||||
_stmt = null;
|
||||
_record = null;
|
||||
}
|
||||
|
||||
while (_stmtQueue.Count != 0)
|
||||
{
|
||||
raw.sqlite3_reset(_stmtQueue.Dequeue().stmt);
|
||||
}
|
||||
|
||||
_closed = true;
|
||||
|
||||
if (_closeConnection)
|
||||
{
|
||||
_command.Connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The name of the column.</returns>
|
||||
public override string GetName(int ordinal)
|
||||
{
|
||||
if (_closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetName)));
|
||||
}
|
||||
|
||||
return _record.GetName(ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ordinal of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the column.</param>
|
||||
/// <returns>The zero-based column ordinal.</returns>
|
||||
public override int GetOrdinal(string name)
|
||||
=> _record.GetOrdinal(name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the declared data type name of the specified column. The storage class is returned for computed
|
||||
/// columns.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The data type name of the column.</returns>
|
||||
/// <remarks>Due to SQLite's dynamic type system, this may not reflect the actual type of the value.</remarks>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public override string GetDataTypeName(int ordinal)
|
||||
{
|
||||
if (_closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDataTypeName)));
|
||||
}
|
||||
|
||||
return _record.GetDataTypeName(ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data type of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The data type of the column.</returns>
|
||||
public override Type GetFieldType(int ordinal)
|
||||
{
|
||||
if (_closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldType)));
|
||||
}
|
||||
|
||||
return _record.GetFieldType(ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the specified column is <see cref="DBNull" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>true if the specified column is <see cref="DBNull" />; otherwise, false.</returns>
|
||||
public override bool IsDBNull(int ordinal)
|
||||
=> _closed
|
||||
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(IsDBNull)))
|
||||
: !_stepped || _done
|
||||
? throw new InvalidOperationException(Resources.NoData)
|
||||
: _record.IsDBNull(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="bool" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override bool GetBoolean(int ordinal)
|
||||
=> _record.GetBoolean(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="byte" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override byte GetByte(int ordinal)
|
||||
=> _record.GetByte(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="char" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override char GetChar(int ordinal)
|
||||
=> _record.GetChar(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="DateTime" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override DateTime GetDateTime(int ordinal)
|
||||
=> _record.GetDateTime(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="DateTimeOffset" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
|
||||
=> _record.GetDateTimeOffset(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="TimeSpan" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public virtual TimeSpan GetTimeSpan(int ordinal)
|
||||
=> _record.GetTimeSpan(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="decimal" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override decimal GetDecimal(int ordinal)
|
||||
=> _record.GetDecimal(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="double" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override double GetDouble(int ordinal)
|
||||
=> _record.GetDouble(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="float" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override float GetFloat(int ordinal)
|
||||
=> _record.GetFloat(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="Guid" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override Guid GetGuid(int ordinal)
|
||||
=> _record.GetGuid(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="short" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override short GetInt16(int ordinal)
|
||||
=> _record.GetInt16(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="int" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override int GetInt32(int ordinal)
|
||||
=> _record.GetInt32(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="long" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override long GetInt64(int ordinal)
|
||||
=> _record.GetInt64(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column as a <see cref="string" />.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override string GetString(int ordinal)
|
||||
=> _record.GetString(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a stream of bytes from the specified column. Not supported.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <param name="dataOffset">The index from which to begin the read operation.</param>
|
||||
/// <param name="buffer">The buffer into which the data is copied.</param>
|
||||
/// <param name="bufferOffset">The index to which the data will be copied.</param>
|
||||
/// <param name="length">The maximum number of bytes to read.</param>
|
||||
/// <returns>The actual number of bytes read.</returns>
|
||||
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
|
||||
=> _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a stream of characters from the specified column. Not supported.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <param name="dataOffset">The index from which to begin the read operation.</param>
|
||||
/// <param name="buffer">The buffer into which the data is copied.</param>
|
||||
/// <param name="bufferOffset">The index to which the data will be copied.</param>
|
||||
/// <param name="length">The maximum number of characters to read.</param>
|
||||
/// <returns>The actual number of characters read.</returns>
|
||||
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
|
||||
=> _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves data as a Stream.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The returned object.</returns>
|
||||
public override Stream GetStream(int ordinal)
|
||||
=> _record.GetStream(ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value.</typeparam>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override T GetFieldValue<T>(int ordinal)
|
||||
{
|
||||
if (typeof(T) == typeof(DBNull)
|
||||
&& (!_stepped || _done))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoData);
|
||||
}
|
||||
|
||||
return _record.GetFieldValue<T>(ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="ordinal">The zero-based column ordinal.</param>
|
||||
/// <returns>The value of the column.</returns>
|
||||
public override object GetValue(int ordinal)
|
||||
{
|
||||
if (_closed)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValue)));
|
||||
}
|
||||
if (!_stepped || _done)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.NoData);
|
||||
}
|
||||
|
||||
return _record.GetValue(ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column values of the current row.
|
||||
/// </summary>
|
||||
/// <param name="values">An array into which the values are copied.</param>
|
||||
/// <returns>The number of values copied into the array.</returns>
|
||||
public override int GetValues(object[] values)
|
||||
=> _record.GetValues(values);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader.
|
||||
/// </summary>
|
||||
/// <returns>A System.Data.DataTable that describes the column metadata.</returns>
|
||||
public override DataTable GetSchemaTable()
|
||||
{
|
||||
var schemaTable = new DataTable("SchemaTable");
|
||||
|
||||
var ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string));
|
||||
var ColumnOrdinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int));
|
||||
var ColumnSize = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int));
|
||||
var NumericPrecision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(short));
|
||||
var NumericScale = new DataColumn(SchemaTableColumn.NumericScale, typeof(short));
|
||||
|
||||
var DataType = new DataColumn(SchemaTableColumn.DataType, typeof(Type));
|
||||
var DataTypeName = new DataColumn("DataTypeName", typeof(string));
|
||||
|
||||
var IsLong = new DataColumn(SchemaTableColumn.IsLong, typeof(bool));
|
||||
var AllowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool));
|
||||
|
||||
var IsUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool));
|
||||
var IsKey = new DataColumn(SchemaTableColumn.IsKey, typeof(bool));
|
||||
var IsAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool));
|
||||
|
||||
var BaseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string));
|
||||
var BaseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string));
|
||||
var BaseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string));
|
||||
var BaseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string));
|
||||
|
||||
var BaseServerName = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(string));
|
||||
var IsAliased = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool));
|
||||
var IsExpression = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool));
|
||||
|
||||
var columns = schemaTable.Columns;
|
||||
|
||||
columns.Add(ColumnName);
|
||||
columns.Add(ColumnOrdinal);
|
||||
columns.Add(ColumnSize);
|
||||
columns.Add(NumericPrecision);
|
||||
columns.Add(NumericScale);
|
||||
columns.Add(IsUnique);
|
||||
columns.Add(IsKey);
|
||||
columns.Add(BaseServerName);
|
||||
columns.Add(BaseCatalogName);
|
||||
columns.Add(BaseColumnName);
|
||||
columns.Add(BaseSchemaName);
|
||||
columns.Add(BaseTableName);
|
||||
columns.Add(DataType);
|
||||
columns.Add(DataTypeName);
|
||||
columns.Add(AllowDBNull);
|
||||
columns.Add(IsAliased);
|
||||
columns.Add(IsExpression);
|
||||
columns.Add(IsAutoIncrement);
|
||||
columns.Add(IsLong);
|
||||
|
||||
for (var i = 0; i < FieldCount; i++)
|
||||
{
|
||||
var schemaRow = schemaTable.NewRow();
|
||||
schemaRow[ColumnName] = GetName(i);
|
||||
schemaRow[ColumnOrdinal] = i;
|
||||
schemaRow[ColumnSize] = DBNull.Value;
|
||||
schemaRow[NumericPrecision] = DBNull.Value;
|
||||
schemaRow[NumericScale] = DBNull.Value;
|
||||
schemaRow[BaseServerName] = _command.Connection.DataSource;
|
||||
var databaseName = raw.sqlite3_column_database_name(_stmt, i);
|
||||
schemaRow[BaseCatalogName] = databaseName;
|
||||
var columnName = raw.sqlite3_column_origin_name(_stmt, i);
|
||||
schemaRow[BaseColumnName] = columnName;
|
||||
schemaRow[BaseSchemaName] = DBNull.Value;
|
||||
var tableName = raw.sqlite3_column_table_name(_stmt, i);
|
||||
schemaRow[BaseTableName] = tableName;
|
||||
schemaRow[DataType] = GetFieldType(i);
|
||||
schemaRow[DataTypeName] = GetDataTypeName(i);
|
||||
schemaRow[IsAliased] = columnName != GetName(i);
|
||||
schemaRow[IsExpression] = columnName == null;
|
||||
schemaRow[IsLong] = DBNull.Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(tableName)
|
||||
&& !string.IsNullOrEmpty(columnName))
|
||||
{
|
||||
using (var command = _command.Connection.CreateCommand())
|
||||
{
|
||||
command.CommandText = new StringBuilder()
|
||||
.AppendLine("SELECT COUNT(*)")
|
||||
.AppendLine("FROM pragma_index_list($table) i, pragma_index_info(i.name) c")
|
||||
.AppendLine("WHERE \"unique\" = 1 AND c.name = $column AND")
|
||||
.AppendLine("NOT EXISTS (SELECT * FROM pragma_index_info(i.name) c2 WHERE c2.name != c.name);").ToString();
|
||||
command.Parameters.AddWithValue("$table", tableName);
|
||||
command.Parameters.AddWithValue("$column", columnName);
|
||||
|
||||
var cnt = (long)command.ExecuteScalar();
|
||||
schemaRow[IsUnique] = cnt != 0;
|
||||
|
||||
command.Parameters.Clear();
|
||||
var columnType = "typeof(\"" + columnName.Replace("\"", "\"\"") + "\")";
|
||||
command.CommandText = new StringBuilder()
|
||||
.AppendLine($"SELECT {columnType}")
|
||||
.AppendLine($"FROM \"{tableName}\"")
|
||||
.AppendLine($"WHERE {columnType} != 'null'")
|
||||
.AppendLine($"GROUP BY {columnType}")
|
||||
.AppendLine("ORDER BY count() DESC")
|
||||
.AppendLine("LIMIT 1;").ToString();
|
||||
|
||||
var type = (string)command.ExecuteScalar();
|
||||
schemaRow[DataType] = SqliteDataRecord.GetFieldType(type);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(databaseName))
|
||||
{
|
||||
var rc = raw.sqlite3_table_column_metadata(_command.Connection.Handle, databaseName, tableName, columnName, out var dataType, out var collSeq, out var notNull, out var primaryKey, out var autoInc);
|
||||
SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle);
|
||||
|
||||
schemaRow[IsKey] = primaryKey != 0;
|
||||
schemaRow[AllowDBNull] = notNull == 0;
|
||||
schemaRow[IsAutoIncrement] = autoInc != 0;
|
||||
}
|
||||
}
|
||||
|
||||
schemaTable.Rows.Add(schemaRow);
|
||||
}
|
||||
|
||||
return schemaTable;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal class SqliteDataRecord : SqliteValueReader
|
||||
{
|
||||
private readonly sqlite3_stmt _stmt;
|
||||
private readonly byte[][] _blobCache;
|
||||
|
||||
public SqliteDataRecord(sqlite3_stmt stmt)
|
||||
{
|
||||
_stmt = stmt;
|
||||
_blobCache = new byte[FieldCount][];
|
||||
}
|
||||
|
||||
public virtual object this[string name]
|
||||
=> GetValue(GetOrdinal(name));
|
||||
|
||||
public virtual object this[int ordinal]
|
||||
=> GetValue(ordinal);
|
||||
|
||||
public override int FieldCount
|
||||
=> raw.sqlite3_column_count(_stmt);
|
||||
|
||||
protected override double GetDoubleCore(int ordinal)
|
||||
=> raw.sqlite3_column_double(_stmt, ordinal);
|
||||
|
||||
protected override long GetInt64Core(int ordinal)
|
||||
=> raw.sqlite3_column_int64(_stmt, ordinal);
|
||||
|
||||
protected override string GetStringCore(int ordinal)
|
||||
=> raw.sqlite3_column_text(_stmt, ordinal);
|
||||
|
||||
protected override byte[] GetBlobCore(int ordinal)
|
||||
=> raw.sqlite3_column_blob(_stmt, ordinal);
|
||||
|
||||
protected override int GetSqliteType(int ordinal)
|
||||
{
|
||||
var type = raw.sqlite3_column_type(_stmt, ordinal);
|
||||
if (type == raw.SQLITE_NULL
|
||||
&& (ordinal < 0 || ordinal >= FieldCount))
|
||||
{
|
||||
// NB: Message is provided by the framework
|
||||
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
protected override T GetNull<T>(int ordinal)
|
||||
=> typeof(T) == typeof(DBNull) || typeof(T) == typeof(object)
|
||||
? (T)(object)DBNull.Value
|
||||
: throw new InvalidOperationException(GetOnNullErrorMsg(ordinal));
|
||||
|
||||
public virtual string GetName(int ordinal)
|
||||
{
|
||||
var name = raw.sqlite3_column_name(_stmt, ordinal);
|
||||
if (name == null
|
||||
&& (ordinal < 0 || ordinal >= FieldCount))
|
||||
{
|
||||
// NB: Message is provided by the framework
|
||||
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public virtual int GetOrdinal(string name)
|
||||
{
|
||||
for (var i = 0; i < FieldCount; i++)
|
||||
{
|
||||
if (GetName(i) == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Message is provided by framework
|
||||
throw new ArgumentOutOfRangeException(nameof(name), name, message: null);
|
||||
}
|
||||
|
||||
public virtual string GetDataTypeName(int ordinal)
|
||||
{
|
||||
var typeName = raw.sqlite3_column_decltype(_stmt, ordinal);
|
||||
if (typeName != null)
|
||||
{
|
||||
var i = typeName.IndexOf('(');
|
||||
|
||||
return i == -1
|
||||
? typeName
|
||||
: typeName.Substring(0, i);
|
||||
}
|
||||
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_INTEGER:
|
||||
return "INTEGER";
|
||||
|
||||
case raw.SQLITE_FLOAT:
|
||||
return "REAL";
|
||||
|
||||
case raw.SQLITE_TEXT:
|
||||
return "TEXT";
|
||||
|
||||
case raw.SQLITE_BLOB:
|
||||
return "BLOB";
|
||||
|
||||
case raw.SQLITE_NULL:
|
||||
return "INTEGER";
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected column type: " + sqliteType);
|
||||
return "INTEGER";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Type GetFieldType(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_INTEGER:
|
||||
return typeof(long);
|
||||
|
||||
case raw.SQLITE_FLOAT:
|
||||
return typeof(double);
|
||||
|
||||
case raw.SQLITE_TEXT:
|
||||
return typeof(string);
|
||||
|
||||
case raw.SQLITE_BLOB:
|
||||
return typeof(byte[]);
|
||||
|
||||
case raw.SQLITE_NULL:
|
||||
return typeof(int);
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected column type: " + sqliteType);
|
||||
return typeof(int);
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetFieldType(string type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "integer":
|
||||
return typeof(long);
|
||||
|
||||
case "real":
|
||||
return typeof(double);
|
||||
|
||||
case "text":
|
||||
return typeof(string);
|
||||
|
||||
case "blob":
|
||||
return typeof(byte[]);
|
||||
|
||||
case null:
|
||||
return typeof(int);
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected column type: " + type);
|
||||
return typeof(int);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
|
||||
{
|
||||
var blob = GetCachedBlob(ordinal);
|
||||
|
||||
long bytesToRead = (long)blob.Length - dataOffset;
|
||||
if (buffer != null)
|
||||
{
|
||||
bytesToRead = System.Math.Min(bytesToRead, length);
|
||||
Array.Copy(blob, dataOffset, buffer, bufferOffset, bytesToRead);
|
||||
}
|
||||
return bytesToRead;
|
||||
}
|
||||
|
||||
public virtual long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
|
||||
{
|
||||
var text = GetString(ordinal);
|
||||
|
||||
int charsToRead = text.Length - (int)dataOffset;
|
||||
charsToRead = System.Math.Min(charsToRead, length);
|
||||
text.CopyTo((int)dataOffset, buffer, bufferOffset, charsToRead);
|
||||
return charsToRead;
|
||||
}
|
||||
|
||||
public virtual Stream GetStream(int ordinal)
|
||||
=> new MemoryStream(GetCachedBlob(ordinal), false);
|
||||
|
||||
internal void Clear()
|
||||
{
|
||||
for (var i = 0; i < _blobCache.Length; i++)
|
||||
{
|
||||
_blobCache[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] GetCachedBlob(int ordinal)
|
||||
{
|
||||
if (ordinal < 0 || ordinal >= FieldCount)
|
||||
{
|
||||
// NB: Message is provided by the framework
|
||||
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
|
||||
}
|
||||
|
||||
var blob = _blobCache[ordinal];
|
||||
if (blob == null)
|
||||
{
|
||||
blob = GetBlob(ordinal);
|
||||
_blobCache[ordinal] = blob;
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a SQLite error.
|
||||
/// </summary>
|
||||
public class SqliteException : DbException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to display for the exception. Can be null.</param>
|
||||
/// <param name="errorCode">The SQLite error code.</param>
|
||||
public SqliteException(string message, int errorCode)
|
||||
: this(message, errorCode, errorCode)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to display for the exception. Can be null.</param>
|
||||
/// <param name="errorCode">The SQLite error code.</param>
|
||||
/// /// <param name="extendedErrorCode">The extended SQLite error code.</param>
|
||||
public SqliteException(string message, int errorCode, int extendedErrorCode)
|
||||
: base(message)
|
||||
{
|
||||
SqliteErrorCode = errorCode;
|
||||
SqliteExtendedErrorCode = extendedErrorCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the SQLite error code.
|
||||
/// </summary>
|
||||
/// <value>The SQLite error code.</value>
|
||||
/// <seealso href="http://sqlite.org/rescode.html">SQLite Result Codes</seealso>
|
||||
public virtual int SqliteErrorCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the extended SQLite error code.
|
||||
/// </summary>
|
||||
/// <value>The SQLite error code.</value>
|
||||
/// <seealso href="https://sqlite.org/rescode.html#extrc">SQLite Result Codes</seealso>
|
||||
public virtual int SqliteExtendedErrorCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception with a specific SQLite error code value.
|
||||
/// </summary>
|
||||
/// <param name="rc">The SQLite error code corresponding to the desired exception.</param>
|
||||
/// <param name="db">A handle to database connection.</param>
|
||||
/// <remarks>
|
||||
/// No exception is thrown for non-error result codes.
|
||||
/// </remarks>
|
||||
public static void ThrowExceptionForRC(int rc, sqlite3 db)
|
||||
{
|
||||
if (rc == raw.SQLITE_OK
|
||||
|| rc == raw.SQLITE_ROW
|
||||
|| rc == raw.SQLITE_DONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string message;
|
||||
int extendedErrorCode;
|
||||
if (db == null || db.ptr == IntPtr.Zero || rc != raw.sqlite3_errcode(db))
|
||||
{
|
||||
message = raw.sqlite3_errstr(rc) + " " + Resources.DefaultNativeError;
|
||||
extendedErrorCode = rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = raw.sqlite3_errmsg(db);
|
||||
extendedErrorCode = raw.sqlite3_extended_errcode(db);
|
||||
}
|
||||
|
||||
throw new SqliteException(Resources.SqliteNativeError(rc, message), rc, extendedErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Data.Common;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates instances of various Microsoft.Data.Sqlite classes.
|
||||
/// </summary>
|
||||
public class SqliteFactory : DbProviderFactory
|
||||
{
|
||||
private SqliteFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The singleton instance.
|
||||
/// </summary>
|
||||
public static readonly SqliteFactory Instance = new SqliteFactory();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new command.
|
||||
/// </summary>
|
||||
/// <returns>The new command.</returns>
|
||||
public override DbCommand CreateCommand()
|
||||
=> new SqliteCommand();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new connection.
|
||||
/// </summary>
|
||||
/// <returns>The new connection.</returns>
|
||||
public override DbConnection CreateConnection()
|
||||
=> new SqliteConnection();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new connection string builder.
|
||||
/// </summary>
|
||||
/// <returns>The new connection string builder.</returns>
|
||||
public override DbConnectionStringBuilder CreateConnectionStringBuilder()
|
||||
=> new SqliteConnectionStringBuilder();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter.
|
||||
/// </summary>
|
||||
/// <returns>The new parameter.</returns>
|
||||
public override DbParameter CreateParameter()
|
||||
=> new SqliteParameter();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the connection modes that can be used when opening a connection.
|
||||
/// </summary>
|
||||
public enum SqliteOpenMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the database for reading and writing, and creates it if it doesn't exist.
|
||||
/// </summary>
|
||||
ReadWriteCreate,
|
||||
|
||||
/// <summary>
|
||||
/// Opens the database for reading and writing.
|
||||
/// </summary>
|
||||
ReadWrite,
|
||||
|
||||
/// <summary>
|
||||
/// Opens the database in read-only mode.
|
||||
/// </summary>
|
||||
ReadOnly,
|
||||
|
||||
/// <summary>
|
||||
/// Opens an in-memory database.
|
||||
/// </summary>
|
||||
Memory
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
// TODO: Truncate to specified size
|
||||
// TODO: Infer type and size from value
|
||||
/// <summary>
|
||||
/// Represents a parameter and its value in a <see cref="SqliteCommand" />.
|
||||
/// </summary>
|
||||
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public class SqliteParameter : DbParameter
|
||||
{
|
||||
private string _parameterName = string.Empty;
|
||||
private object _value;
|
||||
private int? _size;
|
||||
private SqliteType? _sqliteType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
|
||||
/// </summary>
|
||||
public SqliteParameter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter.</param>
|
||||
/// <param name="value">The value of the parameter. Can be null.</param>
|
||||
public SqliteParameter(string name, object value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
_parameterName = name;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter.</param>
|
||||
/// <param name="type">The type of the parameter.</param>
|
||||
public SqliteParameter(string name, SqliteType type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
_parameterName = name;
|
||||
SqliteType = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter.</param>
|
||||
/// <param name="type">The type of the parameter.</param>
|
||||
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
|
||||
public SqliteParameter(string name, SqliteType type, int size)
|
||||
: this(name, type)
|
||||
=> Size = size;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter.</param>
|
||||
/// <param name="type">The type of the parameter.</param>
|
||||
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
|
||||
/// <param name="sourceColumn">The source column used for loading the value. Can be null.</param>
|
||||
public SqliteParameter(string name, SqliteType type, int size, string sourceColumn)
|
||||
: this(name, type, size)
|
||||
=> SourceColumn = sourceColumn;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The type of the parameter.</value>
|
||||
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public override DbType DbType { get; set; } = DbType.String;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the SQLite type of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The SQLite type of the parameter.</value>
|
||||
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public virtual SqliteType SqliteType
|
||||
{
|
||||
get => _sqliteType ?? SqliteValueBinder.GetSqliteType(_value);
|
||||
set => _sqliteType = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the direction of the parameter. Only <see cref="ParameterDirection.Input" /> is supported.
|
||||
/// </summary>
|
||||
/// <value>The direction of the parameter.</value>
|
||||
public override ParameterDirection Direction
|
||||
{
|
||||
get => ParameterDirection.Input;
|
||||
set
|
||||
{
|
||||
if (value != ParameterDirection.Input)
|
||||
{
|
||||
throw new ArgumentException(Resources.InvalidParameterDirection(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the parameter is nullable.
|
||||
/// </summary>
|
||||
/// <value>A value indicating whether the parameter is nullable.</value>
|
||||
public override bool IsNullable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The name of the parameter.</value>
|
||||
public override string ParameterName
|
||||
{
|
||||
get => _parameterName;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
_parameterName = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum size, in bytes, of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The maximum size, in bytes, of the parameter.</value>
|
||||
public override int Size
|
||||
{
|
||||
get => _size
|
||||
?? (_value is string stringValue
|
||||
? stringValue.Length
|
||||
: _value is byte[] byteArray
|
||||
? byteArray.Length
|
||||
: 0);
|
||||
|
||||
set
|
||||
{
|
||||
if (value < -1)
|
||||
{
|
||||
// NB: Message is provided by the framework
|
||||
throw new ArgumentOutOfRangeException(nameof(value), value, message: null);
|
||||
}
|
||||
|
||||
_size = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source column used for loading the value.
|
||||
/// </summary>
|
||||
/// <value>The source column used for loading the value.</value>
|
||||
public override string SourceColumn { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the source column is nullable.
|
||||
/// </summary>
|
||||
/// <value>A value indicating whether the source column is nullable.</value>
|
||||
public override bool SourceColumnNullMapping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the parameter.
|
||||
/// </summary>
|
||||
/// <value>The value of the parameter.</value>
|
||||
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public override object Value
|
||||
{
|
||||
get => _value;
|
||||
set { _value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the <see cref="DbType" /> property to its original value.
|
||||
/// </summary>
|
||||
public override void ResetDbType()
|
||||
=> ResetSqliteType();
|
||||
|
||||
/// <summary>
|
||||
/// Resets the <see cref="SqliteType" /> property to its original value.
|
||||
/// </summary>
|
||||
public virtual void ResetSqliteType()
|
||||
{
|
||||
DbType = DbType.String;
|
||||
SqliteType = SqliteType.Text;
|
||||
}
|
||||
|
||||
internal bool Bind(sqlite3_stmt stmt)
|
||||
{
|
||||
if (_parameterName.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.RequiresSet(nameof(ParameterName)));
|
||||
}
|
||||
|
||||
var index = raw.sqlite3_bind_parameter_index(stmt, _parameterName);
|
||||
if (index == 0
|
||||
&& (index = FindPrefixedParameter(stmt)) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_value == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.RequiresSet(nameof(Value)));
|
||||
}
|
||||
|
||||
new SqliteParameterBinder(stmt, index, _value, _size, _sqliteType).Bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static readonly char[] _parameterPrefixes = { '@', '$', ':' };
|
||||
|
||||
private int FindPrefixedParameter(sqlite3_stmt stmt)
|
||||
{
|
||||
var index = 0;
|
||||
int nextIndex;
|
||||
|
||||
foreach (var prefix in _parameterPrefixes)
|
||||
{
|
||||
if (_parameterName[0] == prefix)
|
||||
{
|
||||
// If name already has a prefix characters, the first call to sqlite3_bind_parameter_index
|
||||
// would have worked if the parameter name was in the statement
|
||||
return 0;
|
||||
}
|
||||
|
||||
nextIndex = raw.sqlite3_bind_parameter_index(stmt, prefix + _parameterName);
|
||||
|
||||
if (nextIndex == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.AmbiguousParameterName(_parameterName));
|
||||
}
|
||||
|
||||
index = nextIndex;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal class SqliteParameterBinder : SqliteValueBinder
|
||||
{
|
||||
private readonly sqlite3_stmt _stmt;
|
||||
private readonly int _index;
|
||||
private readonly int? _size;
|
||||
|
||||
public SqliteParameterBinder(sqlite3_stmt stmt, int index, object value, int? size, SqliteType? sqliteType)
|
||||
: base(value, sqliteType)
|
||||
{
|
||||
_stmt = stmt;
|
||||
_index = index;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
protected override void BindBlob(byte[] value)
|
||||
{
|
||||
var blob = value;
|
||||
if (ShouldTruncate(value.Length))
|
||||
{
|
||||
blob = new byte[_size.Value];
|
||||
Array.Copy(value, blob, _size.Value);
|
||||
}
|
||||
|
||||
raw.sqlite3_bind_blob(_stmt, _index, blob);
|
||||
}
|
||||
|
||||
protected override void BindDoubleCore(double value)
|
||||
=> raw.sqlite3_bind_double(_stmt, _index, value);
|
||||
|
||||
protected override void BindInt64(long value)
|
||||
=> raw.sqlite3_bind_int64(_stmt, _index, value);
|
||||
|
||||
protected override void BindNull()
|
||||
=> raw.sqlite3_bind_null(_stmt, _index);
|
||||
|
||||
protected override void BindText(string value)
|
||||
=> raw.sqlite3_bind_text(
|
||||
_stmt,
|
||||
_index,
|
||||
ShouldTruncate(value.Length)
|
||||
? value.Substring(0, _size.Value)
|
||||
: value);
|
||||
|
||||
private bool ShouldTruncate(int length)
|
||||
=> _size.HasValue
|
||||
&& length > _size.Value
|
||||
&& _size.Value != -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of SQLite parameters.
|
||||
/// </summary>
|
||||
public class SqliteParameterCollection : DbParameterCollection
|
||||
{
|
||||
private readonly List<SqliteParameter> _parameters = new List<SqliteParameter>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteParameterCollection" /> class.
|
||||
/// </summary>
|
||||
protected internal SqliteParameterCollection()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of items in the collection.
|
||||
/// </summary>
|
||||
/// <value>The number of items in the collection.</value>
|
||||
public override int Count
|
||||
=> _parameters.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object used to synchronize access to the collection.
|
||||
/// </summary>
|
||||
/// <value>The object used to synchronize access to the collection.</value>
|
||||
public override object SyncRoot
|
||||
=> ((ICollection)_parameters).SyncRoot;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the parameter.</param>
|
||||
/// <returns>The parameter.</returns>
|
||||
public new virtual SqliteParameter this[int index]
|
||||
{
|
||||
get => _parameters[index];
|
||||
set
|
||||
{
|
||||
if (_parameters[index] == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_parameters[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <returns>The parameter.</returns>
|
||||
public new virtual SqliteParameter this[string parameterName]
|
||||
{
|
||||
get => this[IndexOfChecked(parameterName)];
|
||||
set => this[IndexOfChecked(parameterName)] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to add. Must be a <see cref="SqliteParameter" />.</param>
|
||||
/// <returns>The zero-based index of the parameter that was added.</returns>
|
||||
public override int Add(object value)
|
||||
{
|
||||
_parameters.Add((SqliteParameter)value);
|
||||
|
||||
return Count - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to add.</param>
|
||||
/// <returns>The parameter that was added.</returns>
|
||||
public virtual SqliteParameter Add(SqliteParameter value)
|
||||
{
|
||||
_parameters.Add(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <param name="type">The SQLite type of the parameter.</param>
|
||||
/// <returns>The parameter that was added.</returns>
|
||||
public virtual SqliteParameter Add(string parameterName, SqliteType type)
|
||||
=> Add(new SqliteParameter(parameterName, type));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <param name="type">The SQLite type of the parameter.</param>
|
||||
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
|
||||
/// <returns>The parameter that was added.</returns>
|
||||
public virtual SqliteParameter Add(string parameterName, SqliteType type, int size)
|
||||
=> Add(new SqliteParameter(parameterName, type, size));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <param name="type">The SQLite type of the parameter.</param>
|
||||
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
|
||||
/// <param name="sourceColumn">
|
||||
/// The source column used for loading the value of the parameter. Can be null.
|
||||
/// </param>
|
||||
/// <returns>The parameter that was added.</returns>
|
||||
public virtual SqliteParameter Add(string parameterName, SqliteType type, int size, string sourceColumn)
|
||||
=> Add(new SqliteParameter(parameterName, type, size, sourceColumn));
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple parameters to the collection.
|
||||
/// </summary>
|
||||
/// <param name="values">
|
||||
/// An array of parameters to add. They must be <see cref="SqliteParameter" /> objects.
|
||||
/// </param>
|
||||
public override void AddRange(Array values)
|
||||
=> AddRange(values.Cast<SqliteParameter>());
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple parameters to the collection.
|
||||
/// </summary>
|
||||
/// <param name="values">The parameters to add.</param>
|
||||
public virtual void AddRange(IEnumerable<SqliteParameter> values)
|
||||
=> _parameters.AddRange(values);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter to the collection.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <param name="value">The value of the parameter. Can be null.</param>
|
||||
/// <returns>The parameter that was added.</returns>
|
||||
public virtual SqliteParameter AddWithValue(string parameterName, object value)
|
||||
{
|
||||
var parameter = new SqliteParameter(parameterName, value);
|
||||
Add(parameter);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all parameters from the collection.
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
=> _parameters.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the collection contains the specified parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to look for. Must be a <see cref="SqliteParameter" />.</param>
|
||||
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
|
||||
public override bool Contains(object value)
|
||||
=> Contains((SqliteParameter)value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the collection contains the specified parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to look for.</param>
|
||||
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
|
||||
public virtual bool Contains(SqliteParameter value)
|
||||
=> _parameters.Contains(value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the collection contains a parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="value">The name of the parameter.</param>
|
||||
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
|
||||
public override bool Contains(string value)
|
||||
=> IndexOf(value) != -1;
|
||||
|
||||
/// <summary>
|
||||
/// Copies the collection to an array of parameters.
|
||||
/// </summary>
|
||||
/// <param name="array">
|
||||
/// The array into which the parameters are copied. Must be an array of <see cref="SqliteParameter" /> objects.
|
||||
/// </param>
|
||||
/// <param name="index">The zero-based index to which the parameters are copied.</param>
|
||||
public override void CopyTo(Array array, int index)
|
||||
=> CopyTo((SqliteParameter[])array, index);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the collection to an array of parameters.
|
||||
/// </summary>
|
||||
/// <param name="array">The array into which the parameters are copied.</param>
|
||||
/// <param name="index">The zero-based index to which the parameters are copied.</param>
|
||||
public virtual void CopyTo(SqliteParameter[] array, int index)
|
||||
=> _parameters.CopyTo(array, index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>The enumerator.</returns>
|
||||
public override IEnumerator GetEnumerator()
|
||||
=> _parameters.GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a parameter at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the parameter.</param>
|
||||
/// <returns>The parameter.</returns>
|
||||
protected override DbParameter GetParameter(int index)
|
||||
=> this[index];
|
||||
|
||||
/// <summary>
|
||||
/// Gets a parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <returns>The parameter.</returns>
|
||||
protected override DbParameter GetParameter(string parameterName)
|
||||
=> GetParameter(IndexOfChecked(parameterName));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the specified parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
|
||||
/// <returns>The zero-based index of the parameter.</returns>
|
||||
public override int IndexOf(object value)
|
||||
=> IndexOf((SqliteParameter)value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the specified parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter.</param>
|
||||
/// <returns>The zero-based index of the parameter.</returns>
|
||||
public virtual int IndexOf(SqliteParameter value)
|
||||
=> _parameters.IndexOf(value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter.</param>
|
||||
/// <returns>The zero-based index of the parameter or -1 if not found.</returns>
|
||||
public override int IndexOf(string parameterName)
|
||||
{
|
||||
for (var index = 0; index < _parameters.Count; index++)
|
||||
{
|
||||
if (_parameters[index].ParameterName == parameterName)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a parameter into the collection at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the parameter should be inserted.</param>
|
||||
/// <param name="value">The parameter to insert. Must be a <see cref="SqliteParameter" />.</param>
|
||||
public override void Insert(int index, object value)
|
||||
=> Insert(index, (SqliteParameter)value);
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a parameter into the collection at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the parameter should be inserted.</param>
|
||||
/// <param name="value">The parameter to insert.</param>
|
||||
public virtual void Insert(int index, SqliteParameter value)
|
||||
=> _parameters.Insert(index, value);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a parameter from the collection.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to remove. Must be a <see cref="SqliteParameter" />.</param>
|
||||
public override void Remove(object value)
|
||||
=> Remove((SqliteParameter)value);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a parameter from the collection.
|
||||
/// </summary>
|
||||
/// <param name="value">The parameter to remove.</param>
|
||||
public virtual void Remove(SqliteParameter value)
|
||||
=> _parameters.Remove(value);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a parameter from the collection at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the parameter to remove.</param>
|
||||
public override void RemoveAt(int index)
|
||||
=> _parameters.RemoveAt(index);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a parameter with the specified name from the collection.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter to remove.</param>
|
||||
public override void RemoveAt(string parameterName)
|
||||
=> RemoveAt(IndexOfChecked(parameterName));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the parameter at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the parameter to set.</param>
|
||||
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
|
||||
protected override void SetParameter(int index, DbParameter value)
|
||||
=> this[index] = (SqliteParameter)value;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">The name of the parameter to set.</param>
|
||||
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
|
||||
protected override void SetParameter(string parameterName, DbParameter value)
|
||||
=> SetParameter(IndexOfChecked(parameterName), value);
|
||||
|
||||
internal int Bind(sqlite3_stmt stmt)
|
||||
{
|
||||
var bound = 0;
|
||||
foreach (var parameter in _parameters)
|
||||
{
|
||||
if (parameter.Bind(stmt))
|
||||
{
|
||||
bound++;
|
||||
}
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
private int IndexOfChecked(string parameterName)
|
||||
{
|
||||
var index = IndexOf(parameterName);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Resources.ParameterNotFound(parameterName));
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal class SqliteParameterReader : SqliteValueReader
|
||||
{
|
||||
private readonly string _function;
|
||||
private readonly sqlite3_value[] _values;
|
||||
|
||||
public SqliteParameterReader(string function, sqlite3_value[] values)
|
||||
{
|
||||
_function = function;
|
||||
_values = values;
|
||||
}
|
||||
|
||||
public override int FieldCount
|
||||
=> _values.Length;
|
||||
|
||||
protected override string GetOnNullErrorMsg(int ordinal)
|
||||
=> Resources.UDFCalledWithNull(_function, ordinal);
|
||||
|
||||
protected override double GetDoubleCore(int ordinal)
|
||||
=> raw.sqlite3_value_double(_values[ordinal]);
|
||||
|
||||
protected override long GetInt64Core(int ordinal)
|
||||
=> raw.sqlite3_value_int64(_values[ordinal]);
|
||||
|
||||
protected override string GetStringCore(int ordinal)
|
||||
=> raw.sqlite3_value_text(_values[ordinal]);
|
||||
|
||||
protected override byte[] GetBlobCore(int ordinal)
|
||||
=> raw.sqlite3_value_blob(_values[ordinal]);
|
||||
|
||||
protected override int GetSqliteType(int ordinal)
|
||||
=> raw.sqlite3_value_type(_values[ordinal]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal class SqliteResultBinder : SqliteValueBinder
|
||||
{
|
||||
private readonly sqlite3_context _ctx;
|
||||
|
||||
public SqliteResultBinder(sqlite3_context ctx, object value)
|
||||
: base(value)
|
||||
{
|
||||
_ctx = ctx;
|
||||
}
|
||||
|
||||
protected override void BindBlob(byte[] value)
|
||||
=> raw.sqlite3_result_blob(_ctx, value);
|
||||
|
||||
protected override void BindDoubleCore(double value)
|
||||
=> raw.sqlite3_result_double(_ctx, value);
|
||||
|
||||
protected override void BindInt64(long value)
|
||||
=> raw.sqlite3_result_int64(_ctx, value);
|
||||
|
||||
protected override void BindNull()
|
||||
=> raw.sqlite3_result_null(_ctx);
|
||||
|
||||
protected override void BindText(string value)
|
||||
=> raw.sqlite3_result_text(_ctx, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a transaction made against a SQLite database.
|
||||
/// </summary>
|
||||
public class SqliteTransaction : DbTransaction
|
||||
{
|
||||
private SqliteConnection _connection;
|
||||
private readonly IsolationLevel _isolationLevel;
|
||||
private bool _completed;
|
||||
private bool _externalRollback;
|
||||
|
||||
internal SqliteTransaction(SqliteConnection connection, IsolationLevel isolationLevel)
|
||||
{
|
||||
if ((isolationLevel == IsolationLevel.ReadUncommitted
|
||||
&& connection.ConnectionStringBuilder.Cache != SqliteCacheMode.Shared)
|
||||
|| isolationLevel == IsolationLevel.ReadCommitted
|
||||
|| isolationLevel == IsolationLevel.RepeatableRead)
|
||||
{
|
||||
isolationLevel = IsolationLevel.Serializable;
|
||||
}
|
||||
|
||||
_connection = connection;
|
||||
_isolationLevel = isolationLevel;
|
||||
|
||||
if (isolationLevel == IsolationLevel.ReadUncommitted)
|
||||
{
|
||||
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;");
|
||||
}
|
||||
else if (isolationLevel == IsolationLevel.Serializable)
|
||||
{
|
||||
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 0;");
|
||||
}
|
||||
else if (isolationLevel != IsolationLevel.Unspecified)
|
||||
{
|
||||
throw new ArgumentException(Resources.InvalidIsolationLevel(isolationLevel));
|
||||
}
|
||||
|
||||
connection.ExecuteNonQuery(
|
||||
IsolationLevel == IsolationLevel.Serializable
|
||||
? "BEGIN IMMEDIATE;"
|
||||
: "BEGIN;");
|
||||
raw.sqlite3_rollback_hook(connection.Handle, RollbackExternal, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connection associated with the transaction.
|
||||
/// </summary>
|
||||
/// <value>The connection associated with the transaction.</value>
|
||||
public new virtual SqliteConnection Connection
|
||||
=> _connection;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connection associated with the transaction.
|
||||
/// </summary>
|
||||
/// <value>The connection associated with the transaction.</value>
|
||||
protected override DbConnection DbConnection
|
||||
=> Connection;
|
||||
|
||||
internal bool ExternalRollback
|
||||
=> _externalRollback;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the isolation level for the transaction. This cannot be changed if the transaction is completed or
|
||||
/// closed.
|
||||
/// </summary>
|
||||
/// <value>The isolation level for the transaction.</value>
|
||||
public override IsolationLevel IsolationLevel
|
||||
=> _completed || _connection.State != ConnectionState.Open
|
||||
? throw new InvalidOperationException(Resources.TransactionCompleted)
|
||||
: _isolationLevel != IsolationLevel.Unspecified
|
||||
? _isolationLevel
|
||||
: (_connection.ConnectionStringBuilder.Cache == SqliteCacheMode.Shared
|
||||
&& _connection.ExecuteScalar<long>("PRAGMA read_uncommitted;") != 0)
|
||||
? IsolationLevel.ReadUncommitted
|
||||
: IsolationLevel.Serializable;
|
||||
|
||||
/// <summary>
|
||||
/// Applies the changes made in the transaction.
|
||||
/// </summary>
|
||||
public override void Commit()
|
||||
{
|
||||
if (_externalRollback || _completed || _connection.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.TransactionCompleted);
|
||||
}
|
||||
|
||||
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
|
||||
_connection.ExecuteNonQuery("COMMIT;");
|
||||
Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverts the changes made in the transaction.
|
||||
/// </summary>
|
||||
public override void Rollback()
|
||||
{
|
||||
if (_completed || _connection.State != ConnectionState.Open)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.TransactionCompleted);
|
||||
}
|
||||
|
||||
RollbackInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases any resources used by the transaction and rolls it back.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing
|
||||
&& !_completed
|
||||
&& _connection.State == ConnectionState.Open)
|
||||
{
|
||||
RollbackInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void Complete()
|
||||
{
|
||||
_connection.Transaction = null;
|
||||
_connection = null;
|
||||
_completed = true;
|
||||
}
|
||||
|
||||
private void RollbackInternal()
|
||||
{
|
||||
if (!_externalRollback)
|
||||
{
|
||||
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
|
||||
_connection.ExecuteNonQuery("ROLLBACK;");
|
||||
}
|
||||
|
||||
Complete();
|
||||
}
|
||||
|
||||
private void RollbackExternal(object userData)
|
||||
{
|
||||
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
|
||||
_externalRollback = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the type affinities used by columns in SQLite tables.
|
||||
/// </summary>
|
||||
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
|
||||
public enum SqliteType
|
||||
{
|
||||
/// <summary>
|
||||
/// A signed integer.
|
||||
/// </summary>
|
||||
Integer = raw.SQLITE_INTEGER,
|
||||
|
||||
/// <summary>
|
||||
/// A floating point value.
|
||||
/// </summary>
|
||||
Real = raw.SQLITE_FLOAT,
|
||||
|
||||
/// <summary>
|
||||
/// A text string.
|
||||
/// </summary>
|
||||
Text = raw.SQLITE_TEXT,
|
||||
|
||||
/// <summary>
|
||||
/// A blob of data.
|
||||
/// </summary>
|
||||
Blob = raw.SQLITE_BLOB
|
||||
}
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
// TODO: Make generic
|
||||
internal abstract class SqliteValueBinder
|
||||
{
|
||||
private readonly object _value;
|
||||
private readonly SqliteType? _sqliteType;
|
||||
|
||||
protected SqliteValueBinder(object value)
|
||||
: this(value, null)
|
||||
{
|
||||
}
|
||||
|
||||
protected SqliteValueBinder(object value, SqliteType? sqliteType)
|
||||
{
|
||||
_value = value;
|
||||
_sqliteType = sqliteType;
|
||||
}
|
||||
|
||||
protected abstract void BindInt64(long value);
|
||||
|
||||
protected virtual void BindDouble(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.CannotStoreNaN);
|
||||
}
|
||||
|
||||
BindDoubleCore(value);
|
||||
}
|
||||
|
||||
protected abstract void BindDoubleCore(double value);
|
||||
|
||||
protected abstract void BindText(string value);
|
||||
|
||||
protected abstract void BindBlob(byte[] value);
|
||||
|
||||
protected abstract void BindNull();
|
||||
|
||||
public virtual void Bind()
|
||||
{
|
||||
if (_value == null)
|
||||
{
|
||||
BindNull();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var type = _value.GetType().UnwrapNullableType().UnwrapEnumType();
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
var value = (bool)_value ? 1L : 0;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(byte))
|
||||
{
|
||||
var value = (long)(byte)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(byte[]))
|
||||
{
|
||||
var value = (byte[])_value;
|
||||
BindBlob(value);
|
||||
}
|
||||
else if (type == typeof(char))
|
||||
{
|
||||
var chr = (char)_value;
|
||||
if (_sqliteType == SqliteType.Text)
|
||||
{
|
||||
var value = new string(chr, 1);
|
||||
BindText(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = (long)chr;
|
||||
BindInt64(value);
|
||||
}
|
||||
}
|
||||
else if (type == typeof(DateTime))
|
||||
{
|
||||
var dateTime = (DateTime)_value;
|
||||
if (_sqliteType == SqliteType.Real)
|
||||
{
|
||||
var value = ToJulianDate(dateTime);
|
||||
BindDouble(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = dateTime.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFF", CultureInfo.InvariantCulture);
|
||||
BindText(value);
|
||||
}
|
||||
}
|
||||
else if (type == typeof(DateTimeOffset))
|
||||
{
|
||||
var dateTimeOffset = (DateTimeOffset)_value;
|
||||
if (_sqliteType == SqliteType.Real)
|
||||
{
|
||||
var value = ToJulianDate(dateTimeOffset.DateTime);
|
||||
BindDouble(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = dateTimeOffset.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFFzzz", CultureInfo.InvariantCulture);
|
||||
BindText(value);
|
||||
}
|
||||
}
|
||||
else if (type == typeof(DBNull))
|
||||
{
|
||||
BindNull();
|
||||
}
|
||||
else if (type == typeof(decimal))
|
||||
{
|
||||
var value = ((decimal)_value).ToString("0.0###########################", CultureInfo.InvariantCulture);
|
||||
BindText(value);
|
||||
}
|
||||
else if (type == typeof(double))
|
||||
{
|
||||
var value = (double)_value;
|
||||
BindDouble(value);
|
||||
}
|
||||
else if (type == typeof(float))
|
||||
{
|
||||
var value = (double)(float)_value;
|
||||
BindDouble(value);
|
||||
}
|
||||
else if (type == typeof(Guid))
|
||||
{
|
||||
var guid = (Guid)_value;
|
||||
if (_sqliteType == SqliteType.Text)
|
||||
{
|
||||
var value = guid.ToString().ToUpper();
|
||||
BindText(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = guid.ToByteArray();
|
||||
BindBlob(value);
|
||||
}
|
||||
}
|
||||
else if (type == typeof(int))
|
||||
{
|
||||
var value = (long)(int)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(long))
|
||||
{
|
||||
var value = (long)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(sbyte))
|
||||
{
|
||||
var value = (long)(sbyte)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(short))
|
||||
{
|
||||
var value = (long)(short)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(string))
|
||||
{
|
||||
var value = (string)_value;
|
||||
BindText(value);
|
||||
}
|
||||
else if (type == typeof(TimeSpan))
|
||||
{
|
||||
var timeSpan = (TimeSpan)_value;
|
||||
if (_sqliteType == SqliteType.Real)
|
||||
{
|
||||
var value = timeSpan.TotalDays;
|
||||
BindDouble(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = timeSpan.ToString("c");
|
||||
BindText(value);
|
||||
}
|
||||
}
|
||||
else if (type == typeof(uint))
|
||||
{
|
||||
var value = (long)(uint)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(ulong))
|
||||
{
|
||||
var value = (long)(ulong)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else if (type == typeof(ushort))
|
||||
{
|
||||
var value = (long)(ushort)_value;
|
||||
BindInt64(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(Resources.UnknownDataType(type));
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, SqliteType> _sqliteTypeMapping =
|
||||
new Dictionary<Type, SqliteType>()
|
||||
{
|
||||
{typeof(bool), SqliteType.Integer},
|
||||
{typeof(byte),SqliteType.Integer},
|
||||
{typeof(byte[]), SqliteType.Blob},
|
||||
{typeof(char),SqliteType.Integer},
|
||||
{typeof(DateTime), SqliteType.Text},
|
||||
{typeof(DateTimeOffset), SqliteType.Text},
|
||||
{typeof(DBNull), SqliteType.Text},
|
||||
{typeof(decimal),SqliteType.Text},
|
||||
{typeof(double), SqliteType.Real},
|
||||
{typeof(float), SqliteType.Real},
|
||||
{typeof(Guid), SqliteType.Blob},
|
||||
{typeof(int), SqliteType.Integer},
|
||||
{typeof(long), SqliteType.Integer},
|
||||
{typeof(sbyte),SqliteType.Integer},
|
||||
{typeof(short), SqliteType.Integer},
|
||||
{typeof(string), SqliteType.Integer},
|
||||
{typeof(TimeSpan), SqliteType.Text},
|
||||
{typeof(uint), SqliteType.Integer},
|
||||
{typeof(ulong), SqliteType.Integer},
|
||||
{typeof(ushort), SqliteType.Integer},
|
||||
};
|
||||
|
||||
internal static SqliteType GetSqliteType(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return SqliteType.Text;
|
||||
}
|
||||
|
||||
var type = value.GetType().UnwrapNullableType().UnwrapEnumType();
|
||||
if (_sqliteTypeMapping.TryGetValue(type, out var sqliteType))
|
||||
{
|
||||
return sqliteType;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(Resources.UnknownDataType(type));
|
||||
}
|
||||
}
|
||||
|
||||
private static double ToJulianDate(DateTime dateTime)
|
||||
{
|
||||
// computeJD
|
||||
var Y = dateTime.Year;
|
||||
var M = dateTime.Month;
|
||||
var D = dateTime.Day;
|
||||
|
||||
if (M <= 2)
|
||||
{
|
||||
Y--;
|
||||
M += 12;
|
||||
}
|
||||
|
||||
var A = Y / 100;
|
||||
var B = 2 - A + (A / 4);
|
||||
var X1 = 36525 * (Y + 4716) / 100;
|
||||
var X2 = 306001 * (M + 1) / 10000;
|
||||
var iJD = (long)((X1 + X2 + D + B - 1524.5) * 86400000);
|
||||
|
||||
iJD += dateTime.Hour * 3600000 + dateTime.Minute * 60000 + (long)((dateTime.Second + dateTime.Millisecond / 1000.0) * 1000);
|
||||
|
||||
return iJD / 86400000.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal abstract class SqliteValueReader
|
||||
{
|
||||
public abstract int FieldCount { get; }
|
||||
|
||||
protected abstract int GetSqliteType(int ordinal);
|
||||
|
||||
public virtual bool IsDBNull(int ordinal)
|
||||
=> GetSqliteType(ordinal) == raw.SQLITE_NULL;
|
||||
|
||||
public virtual bool GetBoolean(int ordinal)
|
||||
=> GetInt64(ordinal) != 0;
|
||||
|
||||
public virtual byte GetByte(int ordinal)
|
||||
=> (byte)GetInt64(ordinal);
|
||||
|
||||
public virtual char GetChar(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
if (sqliteType == raw.SQLITE_TEXT)
|
||||
{
|
||||
var val = GetString(ordinal);
|
||||
if (val.Length == 1)
|
||||
{
|
||||
return val[0];
|
||||
}
|
||||
}
|
||||
|
||||
return (char)GetInt64(ordinal);
|
||||
}
|
||||
|
||||
public virtual DateTime GetDateTime(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_FLOAT:
|
||||
case raw.SQLITE_INTEGER:
|
||||
return FromJulianDate(GetDouble(ordinal));
|
||||
|
||||
default:
|
||||
return DateTime.Parse(GetString(ordinal), CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_FLOAT:
|
||||
case raw.SQLITE_INTEGER:
|
||||
return new DateTimeOffset(FromJulianDate(GetDouble(ordinal)));
|
||||
|
||||
default:
|
||||
return DateTimeOffset.Parse(GetString(ordinal), CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual decimal GetDecimal(int ordinal)
|
||||
=> decimal.Parse(GetString(ordinal), NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture);
|
||||
|
||||
public virtual double GetDouble(int ordinal)
|
||||
=> IsDBNull(ordinal)
|
||||
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
|
||||
: GetDoubleCore(ordinal);
|
||||
|
||||
protected abstract double GetDoubleCore(int ordinal);
|
||||
|
||||
public virtual float GetFloat(int ordinal)
|
||||
=> (float)GetDouble(ordinal);
|
||||
|
||||
public virtual Guid GetGuid(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_BLOB:
|
||||
var bytes = GetBlob(ordinal);
|
||||
return bytes.Length == 16
|
||||
? new Guid(bytes)
|
||||
: new Guid(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
|
||||
|
||||
default:
|
||||
return new Guid(GetString(ordinal));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual TimeSpan GetTimeSpan(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_FLOAT:
|
||||
case raw.SQLITE_INTEGER:
|
||||
return TimeSpan.FromDays(GetDouble(ordinal));
|
||||
default:
|
||||
return TimeSpan.Parse(GetString(ordinal));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual short GetInt16(int ordinal)
|
||||
=> (short)GetInt64(ordinal);
|
||||
|
||||
public virtual int GetInt32(int ordinal)
|
||||
=> (int)GetInt64(ordinal);
|
||||
|
||||
public virtual long GetInt64(int ordinal)
|
||||
=> IsDBNull(ordinal)
|
||||
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
|
||||
: GetInt64Core(ordinal);
|
||||
|
||||
protected abstract long GetInt64Core(int ordinal);
|
||||
|
||||
public virtual string GetString(int ordinal)
|
||||
=> IsDBNull(ordinal)
|
||||
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
|
||||
: GetStringCore(ordinal);
|
||||
|
||||
protected abstract string GetStringCore(int ordinal);
|
||||
|
||||
public virtual T GetFieldValue<T>(int ordinal)
|
||||
{
|
||||
if (IsDBNull(ordinal)
|
||||
&& typeof(T).IsNullable())
|
||||
{
|
||||
return GetNull<T>(ordinal);
|
||||
}
|
||||
|
||||
var type = typeof(T).UnwrapNullableType().UnwrapEnumType();
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
return (T)(object)GetBoolean(ordinal);
|
||||
}
|
||||
if (type == typeof(byte))
|
||||
{
|
||||
return (T)(object)GetByte(ordinal);
|
||||
}
|
||||
if (type == typeof(byte[]))
|
||||
{
|
||||
return (T)(object)GetBlob(ordinal);
|
||||
}
|
||||
if (type == typeof(char))
|
||||
{
|
||||
return (T)(object)GetChar(ordinal);
|
||||
}
|
||||
if (type == typeof(DateTime))
|
||||
{
|
||||
return (T)(object)GetDateTime(ordinal);
|
||||
}
|
||||
if (type == typeof(DateTimeOffset))
|
||||
{
|
||||
return (T)(object)GetDateTimeOffset(ordinal);
|
||||
}
|
||||
if (type == typeof(DBNull))
|
||||
{
|
||||
// NB: NULL values handled above
|
||||
throw new InvalidCastException();
|
||||
}
|
||||
if (type == typeof(decimal))
|
||||
{
|
||||
return (T)(object)GetDecimal(ordinal);
|
||||
}
|
||||
if (type == typeof(double))
|
||||
{
|
||||
return (T)(object)GetDouble(ordinal);
|
||||
}
|
||||
if (type == typeof(float))
|
||||
{
|
||||
return (T)(object)GetFloat(ordinal);
|
||||
}
|
||||
if (type == typeof(Guid))
|
||||
{
|
||||
return (T)(object)GetGuid(ordinal);
|
||||
}
|
||||
if (type == typeof(int))
|
||||
{
|
||||
return (T)(object)GetInt32(ordinal);
|
||||
}
|
||||
if (type == typeof(long))
|
||||
{
|
||||
return (T)(object)GetInt64(ordinal);
|
||||
}
|
||||
if (type == typeof(sbyte))
|
||||
{
|
||||
return (T)(object)((sbyte)GetInt64(ordinal));
|
||||
}
|
||||
if (type == typeof(short))
|
||||
{
|
||||
return (T)(object)GetInt16(ordinal);
|
||||
}
|
||||
if (type == typeof(string))
|
||||
{
|
||||
return (T)(object)GetString(ordinal);
|
||||
}
|
||||
if (type == typeof(TimeSpan))
|
||||
{
|
||||
return (T)(object)GetTimeSpan(ordinal);
|
||||
}
|
||||
if (type == typeof(uint))
|
||||
{
|
||||
return (T)(object)((uint)GetInt64(ordinal));
|
||||
}
|
||||
if (type == typeof(ulong))
|
||||
{
|
||||
return (T)(object)((ulong)GetInt64(ordinal));
|
||||
}
|
||||
if (type == typeof(ushort))
|
||||
{
|
||||
return (T)(object)((ushort)GetInt64(ordinal));
|
||||
}
|
||||
|
||||
return (T)GetValue(ordinal);
|
||||
}
|
||||
|
||||
public virtual object GetValue(int ordinal)
|
||||
{
|
||||
var sqliteType = GetSqliteType(ordinal);
|
||||
switch (sqliteType)
|
||||
{
|
||||
case raw.SQLITE_INTEGER:
|
||||
return GetInt64(ordinal);
|
||||
|
||||
case raw.SQLITE_FLOAT:
|
||||
return GetDouble(ordinal);
|
||||
|
||||
case raw.SQLITE_TEXT:
|
||||
return GetString(ordinal);
|
||||
|
||||
case raw.SQLITE_BLOB:
|
||||
return GetBlob(ordinal);
|
||||
|
||||
case raw.SQLITE_NULL:
|
||||
return GetNull<object>(ordinal);
|
||||
|
||||
default:
|
||||
Debug.Assert(false, "Unexpected column type: " + sqliteType);
|
||||
return GetInt32(ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetValues(object[] values)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < FieldCount; i++)
|
||||
{
|
||||
values[i] = GetValue(i);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
protected byte[] GetBlob(int ordinal)
|
||||
=> IsDBNull(ordinal)
|
||||
? GetNull<byte[]>(ordinal)
|
||||
: GetBlobCore(ordinal) ?? Array.Empty<byte>();
|
||||
|
||||
protected abstract byte[] GetBlobCore(int ordinal);
|
||||
|
||||
protected virtual T GetNull<T>(int ordinal)
|
||||
=> typeof(T) == typeof(DBNull)
|
||||
? (T)(object)DBNull.Value
|
||||
: default;
|
||||
|
||||
protected virtual string GetOnNullErrorMsg(int ordinal)
|
||||
=> Resources.CalledOnNullValue(ordinal);
|
||||
|
||||
private static DateTime FromJulianDate(double julianDate)
|
||||
{
|
||||
// computeYMD
|
||||
var iJD = (long)(julianDate * 86400000.0 + 0.5);
|
||||
var Z = (int)((iJD + 43200000) / 86400000);
|
||||
var A = (int)((Z - 1867216.25) / 36524.25);
|
||||
A = Z + 1 + A - (A / 4);
|
||||
var B = A + 1524;
|
||||
var C = (int)((B - 122.1) / 365.25);
|
||||
var D = (36525 * (C & 32767)) / 100;
|
||||
var E = (int)((B - D) / 30.6001);
|
||||
var X1 = (int)(30.6001 * E);
|
||||
var day = B - D - X1;
|
||||
var month = E < 14 ? E - 1 : E - 13;
|
||||
var year = month > 2 ? C - 4716 : C - 4715;
|
||||
|
||||
// computeHMS
|
||||
var s = (int)((iJD + 43200000) % 86400000);
|
||||
var fracSecond = s / 1000.0;
|
||||
s = (int)fracSecond;
|
||||
fracSecond -= s;
|
||||
var hour = s / 3600;
|
||||
s -= hour * 3600;
|
||||
var minute = s / 60;
|
||||
fracSecond += s - minute * 60;
|
||||
|
||||
var second = (int)fracSecond;
|
||||
var millisecond = (int)Math.Round((fracSecond - second) * 1000.0);
|
||||
|
||||
return new DateTime(year, month, day, hour, minute, second, millisecond);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Data.Sqlite.Utilities
|
||||
{
|
||||
internal static class BundleInitializer
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
Assembly assembly;
|
||||
try
|
||||
{
|
||||
assembly = Assembly.Load(new AssemblyName("SQLitePCLRaw.batteries_v2"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assembly.GetType("SQLitePCL.Batteries_V2").GetTypeInfo().GetDeclaredMethod("Init")
|
||||
.Invoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,39 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>SQLite implementation of the System.Data.Common provider model.
|
||||
|
||||
Commonly Used Types:
|
||||
Microsoft.Data.Sqlite.SqliteCommand
|
||||
Microsoft.Data.Sqlite.SqliteConnection
|
||||
Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
|
||||
Microsoft.Data.Sqlite.SqliteDataReader
|
||||
Microsoft.Data.Sqlite.SqliteException
|
||||
Microsoft.Data.Sqlite.SqliteFactory
|
||||
Microsoft.Data.Sqlite.SqliteParameter
|
||||
Microsoft.Data.Sqlite.SqliteTransaction</Description>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<MinClientVersion>3.6</MinClientVersion>
|
||||
<PackageTags>SQLite;Data;ADO.NET</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)">
|
||||
<PrivateAssets>None</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="lib\**\*">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>lib</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
Microsoft.Data.Sqlite
|
||||
=====================
|
||||
|
||||
Contains SQLite implementations of the System.Data.Common interfaces.
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
internal static class SqliteConnectionExtensions
|
||||
{
|
||||
public static SqliteDataReader ExecuteReader(this SqliteConnection connection, string commandText)
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = commandText;
|
||||
|
||||
return command.ExecuteReader();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,883 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
public class SqliteCommandTest
|
||||
{
|
||||
[Fact]
|
||||
public void Ctor_sets_values()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.DefaultTimeout = 1;
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
var command = new SqliteCommand("SELECT 1;", connection, transaction);
|
||||
|
||||
Assert.Equal("SELECT 1;", command.CommandText);
|
||||
Assert.Same(connection, command.Connection);
|
||||
Assert.Equal(1, command.CommandTimeout);
|
||||
Assert.Same(transaction, command.Transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommandText_throws_when_set_when_open_reader()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.CommandText = "SELECT 2;");
|
||||
|
||||
Assert.Equal(Resources.SetRequiresNoOpenReader("CommandText"), ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Connection_can_be_unset()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
command.Prepare();
|
||||
|
||||
command.Connection = null;
|
||||
Assert.Null(command.Connection);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Connection_throws_when_set_when_open_reader()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.Connection = new SqliteConnection());
|
||||
|
||||
Assert.Equal(Resources.SetRequiresNoOpenReader("Connection"), ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommandType_text_by_default()
|
||||
{
|
||||
Assert.Equal(CommandType.Text, new SqliteCommand().CommandType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(CommandType.StoredProcedure)]
|
||||
[InlineData(CommandType.TableDirect)]
|
||||
public void CommandType_validates_value(CommandType commandType)
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentException>(() => new SqliteCommand().CommandType = commandType);
|
||||
|
||||
Assert.Equal(Resources.InvalidCommandType(commandType), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parameters_works()
|
||||
{
|
||||
var command = new SqliteCommand();
|
||||
|
||||
var result = command.Parameters;
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Same(result, command.Parameters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateParameter_works()
|
||||
{
|
||||
Assert.NotNull(new SqliteCommand().CreateParameter());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Prepare_throws_when_no_connection()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().Prepare());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("Prepare"), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Prepare_throws_when_connection_closed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().Prepare());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("Prepare"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Prepare_throws_when_no_command_text()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().Prepare());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresSetCommandText("Prepare"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Prepare_throws_when_command_text_contains_dependent_commands()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "CREATE TABLE Data (Value); SELECT * FROM Data;";
|
||||
var ex = Assert.Throws<SqliteException>(() => command.Prepare());
|
||||
|
||||
Assert.Equal(1, ex.SqliteErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void Multiple_command_executes_works()
|
||||
{
|
||||
const int INSERTS = 3;
|
||||
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
connection.ExecuteNonQuery("CREATE TABLE Data (ID integer PRIMARY KEY, Value integer);");
|
||||
|
||||
using (var command = connection.CreateCommand())
|
||||
{
|
||||
command.CommandText = "INSERT INTO Data (Value) VALUES (@value);";
|
||||
var valueParam = command.Parameters.AddWithValue("@value", -1);
|
||||
|
||||
Assert.Equal(1, command.ExecuteNonQuery());
|
||||
|
||||
for (var i = 0; i < INSERTS; i++)
|
||||
{
|
||||
valueParam.Value = i;
|
||||
Assert.Equal(1, command.ExecuteNonQuery());
|
||||
}
|
||||
|
||||
Assert.Equal(1, command.ExecuteNonQuery());
|
||||
|
||||
command.CommandText = "SELECT Value FROM Data ORDER BY ID";
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal(-1, reader.GetInt32(0));
|
||||
|
||||
for (var i = 0; i < INSERTS; i++)
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal(i, reader.GetInt32(0));
|
||||
}
|
||||
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal(INSERTS - 1, reader.GetInt32(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_no_connection()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteReader());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteReader"), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_connection_closed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteReader());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteReader"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_no_command_text()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteReader());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteReader"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_on_error()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "INVALID";
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<SqliteException>(() => command.ExecuteReader());
|
||||
|
||||
Assert.Equal(raw.SQLITE_ERROR, ex.SqliteErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_throws_when_no_connection()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteScalar());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteScalar"), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_throws_when_connection_closed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteScalar());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteScalar"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_transaction_required()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
using (connection.BeginTransaction())
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
|
||||
|
||||
Assert.Equal(Resources.TransactionRequired, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_throws_when_no_command_text()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteScalar());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteScalar"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_processes_dependent_commands()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "CREATE TABLE Data (Value); SELECT * FROM Data;";
|
||||
|
||||
Assert.Null(command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_null_when_empty()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1 WHERE 0 = 1;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Null(command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_long_when_integer()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(1L, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_double_when_real()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 3.14;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(3.14, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_string_when_text()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 'test';";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal("test", command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_byte_array_when_blob()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT x'7e57';";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(new byte[] { 0x7e, 0x57 }, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_DBNull_when_null()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT NULL;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(DBNull.Value, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_binds_parameters()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
command.Parameters.AddWithValue("@Parameter", 1);
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(1L, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_parameter_unset()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
|
||||
Assert.Equal(Resources.MissingParameters("@Parameter"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_reader_open()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
|
||||
Assert.Equal(Resources.DataReaderOpen, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_long_when_batching()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 42; SELECT 43;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(42L, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_long_when_multiple_columns()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 42, 43;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(42L, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteScalar_returns_long_when_multiple_rows()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 42 UNION SELECT 43;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(42L, command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteNonQuery_throws_when_no_connection()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteNonQuery());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteNonQuery"), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteNonQuery_throws_when_connection_closed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteNonQuery());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteNonQuery"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteNonQuery_throws_when_no_command_text()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteNonQuery());
|
||||
|
||||
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteNonQuery"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_transaction_mismatched()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
using (var otherConnection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
otherConnection.Open();
|
||||
|
||||
using (var transction = otherConnection.BeginTransaction())
|
||||
{
|
||||
command.Transaction = transction;
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
|
||||
|
||||
Assert.Equal(Resources.TransactionConnectionMismatch, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_throws_when_transaction_completed_externally()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("ROLLBACK;");
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => connection.ExecuteNonQuery("SELECT 1;"));
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteNonQuery_works()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
Assert.Equal(-1, command.ExecuteNonQuery());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_works()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.NotNull(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_skips_DML_statements()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
connection.ExecuteNonQuery("CREATE TABLE Test(Value);");
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = @"
|
||||
INSERT INTO Test VALUES(1);
|
||||
SELECT 1;";
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
var hasData = reader.Read();
|
||||
Assert.True(hasData);
|
||||
|
||||
Assert.Equal(1L, reader.GetInt64(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_works_when_comments()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "-- TODO: Write SQL";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.False(reader.HasRows);
|
||||
Assert.Equal(-1, reader.RecordsAffected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_works_when_trailing_comments()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0; -- My favorite number";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
var hasResult = reader.NextResult();
|
||||
Assert.False(hasResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Cancel_does_nothing()
|
||||
{
|
||||
new SqliteCommand().Cancel();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_supports_SequentialAccess()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
|
||||
{
|
||||
var hasResult = reader.NextResult();
|
||||
Assert.False(hasResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_supports_SingleResult()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader(CommandBehavior.SingleResult))
|
||||
{
|
||||
var hasResult = reader.NextResult();
|
||||
Assert.False(hasResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_supports_SingleRow()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
var hasResult = reader.NextResult();
|
||||
Assert.False(hasResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_supports_CloseConnection()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0;";
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
|
||||
{
|
||||
var hasResult = reader.NextResult();
|
||||
Assert.False(hasResult);
|
||||
}
|
||||
Assert.Equal(ConnectionState.Closed, connection.State);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(CommandBehavior.KeyInfo)]
|
||||
[InlineData(CommandBehavior.SchemaOnly)]
|
||||
public void ExecuteReader_throws_for_unsupported_CommandBehavior(CommandBehavior behavior)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 0;";
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() => command.ExecuteReader(behavior));
|
||||
Assert.Equal(Resources.InvalidCommandBehavior(behavior), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public Task ExecuteReader_retries_when_locked(bool extendedErrorCode)
|
||||
{
|
||||
const string connectionString = "Data Source=locked;Mode=Memory;Cache=Shared";
|
||||
|
||||
var selectedSignal = new AutoResetEvent(initialState: false);
|
||||
|
||||
return Task.WhenAll(
|
||||
Task.Run(
|
||||
async () =>
|
||||
{
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
if (extendedErrorCode)
|
||||
{
|
||||
raw.sqlite3_extended_result_codes(connection.Handle, 1);
|
||||
}
|
||||
|
||||
connection.ExecuteNonQuery(
|
||||
"CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
|
||||
|
||||
using (connection.ExecuteReader("SELECT * FROM Data;"))
|
||||
{
|
||||
selectedSignal.Set();
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}),
|
||||
Task.Run(
|
||||
() =>
|
||||
{
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
if (extendedErrorCode)
|
||||
{
|
||||
raw.sqlite3_extended_result_codes(connection.Handle, 1);
|
||||
}
|
||||
|
||||
selectedSignal.WaitOne();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "DROP TABLE Data;";
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteReader_retries_when_busy()
|
||||
{
|
||||
const string connectionString = "Data Source=busy.db";
|
||||
|
||||
var selectedSignal = new AutoResetEvent(initialState: false);
|
||||
|
||||
try
|
||||
{
|
||||
await Task.WhenAll(
|
||||
Task.Run(
|
||||
async () =>
|
||||
{
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
connection.ExecuteNonQuery(
|
||||
"CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
|
||||
|
||||
using (connection.ExecuteReader("SELECT * FROM Data;"))
|
||||
{
|
||||
selectedSignal.Set();
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}),
|
||||
Task.Run(
|
||||
() =>
|
||||
{
|
||||
using (var connection = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
selectedSignal.WaitOne();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "DROP TABLE Data;";
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}));
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete("busy.db");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteReader_honors_CommandTimeout()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
connection.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
|
||||
|
||||
using (connection.ExecuteReader("SELECT * FROM Data;"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "DROP TABLE Data;";
|
||||
command.CommandTimeout = 1;
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
Assert.Throws<SqliteException>(() => command.ExecuteNonQuery());
|
||||
stopwatch.Stop();
|
||||
|
||||
Assert.InRange(stopwatch.ElapsedMilliseconds, 1000, 1999);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Can_get_results_from_nonreadonly_statements()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var result = connection.ExecuteScalar<string>("PRAGMA journal_mode;");
|
||||
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
public class SqliteConnectionStringBuilderTest
|
||||
{
|
||||
[Fact]
|
||||
public void Ctor_parses_options()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
|
||||
|
||||
Assert.Equal("test.db", builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ctor_parses_SharedCache()
|
||||
{
|
||||
Assert.Equal(SqliteCacheMode.Private, new SqliteConnectionStringBuilder("Cache=Private").Cache);
|
||||
Assert.Equal(SqliteCacheMode.Shared, new SqliteConnectionStringBuilder("Cache=Shared").Cache);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ctor_parses_mode()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Mode=Memory");
|
||||
|
||||
Assert.Equal(SqliteOpenMode.Memory, builder.Mode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filename_is_alias_for_DataSource()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Filename=inline.db");
|
||||
Assert.Equal("inline.db", builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_takes_last_alias_specified()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Filename=ignore me.db; Data Source=and me too.db; DataSource=this_one.db");
|
||||
|
||||
Assert.Equal("this_one.db", builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataSource_works()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
|
||||
builder.DataSource = "test.db";
|
||||
|
||||
Assert.Equal("test.db", builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataSource_defaults_to_empty()
|
||||
{
|
||||
Assert.Empty(new SqliteConnectionStringBuilder().DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mode_works()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
|
||||
builder.Mode = SqliteOpenMode.Memory;
|
||||
|
||||
Assert.Equal(SqliteOpenMode.Memory, builder.Mode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mode_defaults_to_ReadWriteCreate()
|
||||
{
|
||||
Assert.Equal(SqliteOpenMode.ReadWriteCreate, new SqliteConnectionStringBuilder().Mode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Cache_defaults()
|
||||
{
|
||||
Assert.Equal(SqliteCacheMode.Default, new SqliteConnectionStringBuilder().Cache);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Keys_works()
|
||||
{
|
||||
var keys = (ICollection<string>)new SqliteConnectionStringBuilder().Keys;
|
||||
|
||||
Assert.True(keys.IsReadOnly);
|
||||
Assert.Equal(3, keys.Count);
|
||||
Assert.Contains("Data Source", keys);
|
||||
Assert.Contains("Mode", keys);
|
||||
Assert.Contains("Cache", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Values_works()
|
||||
{
|
||||
var values = (ICollection<object>)new SqliteConnectionStringBuilder().Values;
|
||||
|
||||
Assert.True(values.IsReadOnly);
|
||||
Assert.Equal(3, values.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Item_validates_argument()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentException>(() => new SqliteConnectionStringBuilder()["Invalid"]);
|
||||
Assert.Equal(Resources.KeywordNotSupported("Invalid"), ex.Message);
|
||||
|
||||
ex = Assert.Throws<ArgumentException>(() => new SqliteConnectionStringBuilder()["Invalid"] = 0);
|
||||
Assert.Equal(Resources.KeywordNotSupported("Invalid"), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Item_resets_value_when_null()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
builder.DataSource = "test.db";
|
||||
|
||||
builder["Data Source"] = null;
|
||||
|
||||
Assert.Empty(builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Item_gets_value()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
builder.DataSource = "test.db";
|
||||
|
||||
Assert.Equal("test.db", builder["Data Source"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Item_sets_value()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
|
||||
builder["Data Source"] = "test.db";
|
||||
|
||||
Assert.Equal("test.db", builder.DataSource);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Shared")]
|
||||
[InlineData("SHARED")]
|
||||
[InlineData(SqliteCacheMode.Shared)]
|
||||
[InlineData((int)SqliteCacheMode.Shared)]
|
||||
public void Item_converts_to_enum_on_set(object value)
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
|
||||
builder["Cache"] = value;
|
||||
|
||||
Assert.Equal(SqliteCacheMode.Shared, builder["Cache"]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(42)]
|
||||
[InlineData("Unknown")]
|
||||
[InlineData((SqliteCacheMode)42)]
|
||||
[InlineData(SqliteOpenMode.ReadOnly)]
|
||||
public void Item_throws_when_cannot_convert_to_enum_on_set(object value)
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder();
|
||||
|
||||
Assert.ThrowsAny<ArgumentException>(() => builder["Cache"] = value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_resets_everything()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Data Source=test.db;Mode=Memory;Cache=Shared");
|
||||
|
||||
builder.Clear();
|
||||
|
||||
Assert.Empty(builder.DataSource);
|
||||
Assert.Equal(SqliteOpenMode.ReadWriteCreate, builder.Mode);
|
||||
Assert.Equal(SqliteCacheMode.Default, builder.Cache);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsKey_returns_true_when_exists()
|
||||
{
|
||||
Assert.True(new SqliteConnectionStringBuilder().ContainsKey("Data Source"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsKey_returns_false_when_not_exists()
|
||||
{
|
||||
Assert.False(new SqliteConnectionStringBuilder().ContainsKey("Invalid"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_returns_false_when_not_exists()
|
||||
{
|
||||
Assert.False(new SqliteConnectionStringBuilder().Remove("Invalid"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_resets_option()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
|
||||
|
||||
var removed = builder.Remove("Data Source");
|
||||
|
||||
Assert.True(removed);
|
||||
Assert.Empty(builder.DataSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldSerialize_returns_false_when_not_exists()
|
||||
{
|
||||
Assert.False(new SqliteConnectionStringBuilder().ShouldSerialize("Invalid"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldSerialize_returns_false_when_unset()
|
||||
{
|
||||
Assert.False(new SqliteConnectionStringBuilder().ShouldSerialize("Data Source"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldSerialize_returns_true_when_set()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
|
||||
|
||||
Assert.True(builder.ShouldSerialize("Data Source"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetValue_returns_false_when_not_exists()
|
||||
{
|
||||
var retrieved = new SqliteConnectionStringBuilder().TryGetValue("Invalid", out var value);
|
||||
|
||||
Assert.False(retrieved);
|
||||
Assert.Null(value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetValue_returns_true_when_exists()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
|
||||
|
||||
var retrieved = builder.TryGetValue("Data Source", out var value);
|
||||
|
||||
Assert.True(retrieved);
|
||||
Assert.Equal("test.db", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_builds_string()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder
|
||||
{
|
||||
DataSource = "test.db",
|
||||
Cache = SqliteCacheMode.Shared,
|
||||
Mode = SqliteOpenMode.Memory
|
||||
};
|
||||
|
||||
Assert.Equal("Data Source=test.db;Mode=Memory;Cache=Shared", builder.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_builds_minimal_string()
|
||||
{
|
||||
var builder = new SqliteConnectionStringBuilder
|
||||
{
|
||||
DataSource = "test.db"
|
||||
};
|
||||
|
||||
Assert.Equal("Data Source=test.db", builder.ToString());
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using SQLitePCL;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
public class SqliteExceptionTest
|
||||
{
|
||||
[Fact]
|
||||
public void Ctor_sets_message_and_errorCode()
|
||||
{
|
||||
var ex = new SqliteException("test", 1);
|
||||
|
||||
Assert.Equal("test", ex.Message);
|
||||
Assert.Equal(1, ex.SqliteErrorCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(raw.SQLITE_OK)]
|
||||
[InlineData(raw.SQLITE_ROW)]
|
||||
[InlineData(raw.SQLITE_DONE)]
|
||||
public void ThrowExceptionForRC_does_nothing_when_non_error(int rc)
|
||||
{
|
||||
SqliteException.ThrowExceptionForRC(rc, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite.Tests
|
||||
{
|
||||
public class SqliteFactoryTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateConnection_works()
|
||||
{
|
||||
Assert.IsType<SqliteConnection>(SqliteFactory.Instance.CreateConnection());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateConnectionStringBuilder_works()
|
||||
{
|
||||
Assert.IsType<SqliteConnectionStringBuilder>(SqliteFactory.Instance.CreateConnectionStringBuilder());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCommand_works()
|
||||
{
|
||||
Assert.IsType<SqliteCommand>(SqliteFactory.Instance.CreateCommand());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateParameter_works()
|
||||
{
|
||||
Assert.IsType<SqliteParameter>(SqliteFactory.Instance.CreateParameter());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,526 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using Microsoft.Data.Sqlite.TestUtilities;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
public class SqliteParameterTest
|
||||
{
|
||||
[Fact]
|
||||
public void Ctor_validates_arguments()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentNullException>(() => new SqliteParameter(null, 1));
|
||||
|
||||
Assert.Equal("name", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ctor_sets_name_and_value()
|
||||
{
|
||||
var result = new SqliteParameter("@Parameter", 1);
|
||||
|
||||
Assert.Equal("@Parameter", result.ParameterName);
|
||||
Assert.Equal(1, result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ctor_sets_other_values()
|
||||
{
|
||||
var result = new SqliteParameter("@Parameter", SqliteType.Integer, 8, "Column");
|
||||
|
||||
Assert.Equal("@Parameter", result.ParameterName);
|
||||
Assert.Equal(SqliteType.Integer, result.SqliteType);
|
||||
Assert.Equal(8, result.Size);
|
||||
Assert.Equal("Column", result.SourceColumn);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DbType_defaults_to_string()
|
||||
{
|
||||
Assert.Equal(DbType.String, new SqliteParameter().DbType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Size_validates_argument()
|
||||
{
|
||||
var parameter = new SqliteParameter();
|
||||
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => parameter.Size = -2);
|
||||
|
||||
Assert.Equal("value", ex.ParamName);
|
||||
Assert.Equal(-2, ex.ActualValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SqliteType_defaults_to_text()
|
||||
{
|
||||
Assert.Equal(SqliteType.Text, new SqliteParameter().SqliteType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Direction_input_by_default()
|
||||
{
|
||||
Assert.Equal(ParameterDirection.Input, new SqliteParameter().Direction);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Direction_validates_value()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentException>(() => new SqliteParameter().Direction = ParameterDirection.Output);
|
||||
Assert.Equal(Resources.InvalidParameterDirection(ParameterDirection.Output), ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterName_validates_value()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentNullException>(() => new SqliteParameter().ParameterName = null);
|
||||
Assert.Equal("value", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResetDbType_works()
|
||||
{
|
||||
var parameter = new SqliteParameter
|
||||
{
|
||||
DbType = DbType.Int64,
|
||||
SqliteType = SqliteType.Integer
|
||||
};
|
||||
|
||||
parameter.ResetDbType();
|
||||
|
||||
Assert.Equal(DbType.String, parameter.DbType);
|
||||
Assert.Equal(SqliteType.Text, parameter.SqliteType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResetSqliteType_works()
|
||||
{
|
||||
var parameter = new SqliteParameter
|
||||
{
|
||||
DbType = DbType.Int64,
|
||||
SqliteType = SqliteType.Integer
|
||||
};
|
||||
|
||||
parameter.ResetSqliteType();
|
||||
|
||||
Assert.Equal(DbType.String, parameter.DbType);
|
||||
Assert.Equal(SqliteType.Text, parameter.SqliteType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_requires_set_name()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
command.Parameters.Add(new SqliteParameter { Value = 1 });
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
|
||||
|
||||
Assert.Equal(Resources.RequiresSet("ParameterName"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_requires_set_value()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
command.Parameters.Add(new SqliteParameter { ParameterName = "@Parameter" });
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
|
||||
|
||||
Assert.Equal(Resources.RequiresSet("Value"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_is_noop_on_unknown_parameter()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1;";
|
||||
command.Parameters.AddWithValue("@Unknown", 1);
|
||||
connection.Open();
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 1L)]
|
||||
[InlineData((byte)1, 1L)]
|
||||
[InlineData('A', 65L)]
|
||||
[InlineData('A', "A", SqliteType.Text)]
|
||||
[InlineData(3.14, 3.14)]
|
||||
[InlineData(3f, 3.0)]
|
||||
[InlineData(1, 1L)]
|
||||
[InlineData(1L, 1L)]
|
||||
[InlineData((sbyte)1, 1L)]
|
||||
[InlineData((short)1, 1L)]
|
||||
[InlineData("test", "test")]
|
||||
[InlineData(1u, 1L)]
|
||||
[InlineData(1ul, 1L)]
|
||||
[InlineData((ushort)1, 1L)]
|
||||
[InlineData("测试测试测试", "测试测试测试")]
|
||||
[InlineData(double.NegativeInfinity, double.NegativeInfinity)]
|
||||
[InlineData(double.PositiveInfinity, double.PositiveInfinity)]
|
||||
[InlineData(float.NegativeInfinity, double.NegativeInfinity)]
|
||||
[InlineData(float.PositiveInfinity, double.PositiveInfinity)]
|
||||
public void Bind_works(object value, object coercedValue, SqliteType? sqliteType = null)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
var sqliteParameter = command.Parameters.AddWithValue("@Parameter", value);
|
||||
if (sqliteType.HasValue)
|
||||
{
|
||||
sqliteParameter.SqliteType = sqliteType.Value;
|
||||
}
|
||||
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal(coercedValue, result);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(double.NaN)]
|
||||
[InlineData(float.NaN)]
|
||||
public void Bind_throws_for_nan(object value)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
command.Parameters.AddWithValue("@Parameter", value);
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
|
||||
Assert.Equal(Resources.CannotStoreNaN, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_byte_array()
|
||||
{
|
||||
var bytes = new byte[] { 0x7E, 0x57 };
|
||||
Bind_works(bytes, bytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_DateTime()
|
||||
=> Bind_works(new DateTime(2014, 4, 14, 11, 13, 59), "2014-04-14 11:13:59");
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_DateTime_with_SqliteType_Real()
|
||||
=> Bind_works(new DateTime(2014, 4, 14, 11, 13, 59), 2456761.9680439816, SqliteType.Real);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_DateTimeOffset()
|
||||
=> Bind_works(new DateTimeOffset(2014, 4, 14, 11, 13, 59, new TimeSpan(-8, 0, 0)), "2014-04-14 11:13:59-08:00");
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_DateTimeOffset_with_SqliteType_Real()
|
||||
=> Bind_works(
|
||||
new DateTimeOffset(new DateTime(2014, 4, 14, 11, 13, 59)),
|
||||
2456761.9680439816,
|
||||
SqliteType.Real);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_DBNull()
|
||||
=> Bind_works(DBNull.Value, DBNull.Value);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_decimal()
|
||||
=> Bind_works(3.14m, "3.14");
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_decimal_with_integral_value()
|
||||
=> Bind_works(3m, "3.0");
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_Enum()
|
||||
=> Bind_works(MyEnum.One, 1L);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_Guid()
|
||||
=> Bind_works(
|
||||
new Guid("1c902ddb-f4b6-4945-af38-0dc1b0760465"),
|
||||
new byte[] { 0xDB, 0x2D, 0x90, 0x1C, 0xB6, 0xF4, 0x45, 0x49, 0xAF, 0x38, 0x0D, 0xC1, 0xB0, 0x76, 0x04, 0x65 });
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_Guid_with_SqliteType_Text()
|
||||
=> Bind_works(
|
||||
new Guid("1c902ddb-f4b6-4945-af38-0dc1b0760465"),
|
||||
"1C902DDB-F4B6-4945-AF38-0DC1B0760465",
|
||||
SqliteType.Text);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_Nullable()
|
||||
=> Bind_works((int?)1, 1L);
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_TimeSpan()
|
||||
=> Bind_works(new TimeSpan(11, 19, 32), "11:19:32");
|
||||
|
||||
[Fact]
|
||||
public void Bind_works_when_TimeSpan_with_SqliteType_Real()
|
||||
=> Bind_works(new TimeSpan(11, 19, 32), 0.47189814814814812, SqliteType.Real);
|
||||
|
||||
[Fact]
|
||||
public void Bind_throws_when_unknown()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Parameter;";
|
||||
command.Parameters.AddWithValue("@Parameter", new object());
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
|
||||
|
||||
Assert.Equal(Resources.UnknownDataType(typeof(object)), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_binds_string_values_without_embedded_nulls()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Text || 'ing';";
|
||||
command.Parameters.AddWithValue("@Text", "test");
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal("testing", result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_with_restricted_size_works_on_string_values()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Text;";
|
||||
command.Parameters.AddWithValue("@Text", "ABCDE").Size = 3;
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal("ABC", result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_with_sentinel_size_works_on_string_values()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT $value;";
|
||||
command.Parameters.AddWithValue("$value", "TEST").Size = -1;
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal("TEST", result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_with_restricted_size_works_on_blob_values()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Blob;";
|
||||
command.Parameters.AddWithValue("@Blob", new byte[] { 1, 2, 3, 4, 5 }).Size = 3;
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal(new byte[] { 1, 2, 3 }, result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_with_sentinel_size_works_on_blob_values()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT $value;";
|
||||
command.Parameters.AddWithValue("$value", new byte[] { 0x7E, 0x57 }).Size = -1;
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal(new byte[] { 0x7E, 0x57 }, result);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("@Parameter")]
|
||||
[InlineData("$Parameter")]
|
||||
[InlineData(":Parameter")]
|
||||
public void Bind_does_not_require_prefix(string parameterName)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT " + parameterName;
|
||||
command.Parameters.AddWithValue("Parameter", "harvest");
|
||||
connection.Open();
|
||||
|
||||
var result = command.ExecuteScalar();
|
||||
|
||||
Assert.Equal("harvest", result);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_throws_for_ambiguous_parameters()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Param, $Param";
|
||||
command.Parameters.AddWithValue("Param", 1);
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
|
||||
|
||||
Assert.Equal(Resources.AmbiguousParameterName("Param"), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_with_prefixed_names()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT @Param, $Param, :Param";
|
||||
command.Parameters.AddWithValue("@Param", 1);
|
||||
command.Parameters.AddWithValue("$Param", 2);
|
||||
command.Parameters.AddWithValue(":Param", 3);
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal(1, reader.GetFieldValue<int>(0));
|
||||
Assert.Equal(2, reader.GetFieldValue<int>(1));
|
||||
Assert.Equal(3, reader.GetFieldValue<int>(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact, UseCulture("ar-SA")]
|
||||
public void Bind_DateTime_with_Arabic_Culture()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
connection.ExecuteNonQuery("CREATE TABLE Person(DateOfBirth datetime);");
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "INSERT INTO Person(DateOfBirth) VALUES (@DateOfBirth);";
|
||||
var date = new DateTime(2018, 3, 25);
|
||||
command.Parameters.AddWithValue("DateOfBirth", date);
|
||||
Assert.Equal(1, command.ExecuteNonQuery());
|
||||
|
||||
command.CommandText = "SELECT DateOfBirth FROM Person;";
|
||||
var result = command.ExecuteScalar();
|
||||
Assert.Equal("2018-03-25 00:00:00", (string)result);
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal("2018-03-25 00:00:00", reader.GetString(0));
|
||||
Assert.Equal(date, reader.GetDateTime(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact, UseCulture("ar-SA")]
|
||||
public void Bind_DateTimeOffset_with_Arabic_Culture()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
connection.ExecuteNonQuery("CREATE TABLE Test(date TEXT);");
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "INSERT INTO Test(date) VALUES (@date);";
|
||||
var date = new DateTimeOffset(new DateTime(2018, 3, 25), new TimeSpan());
|
||||
command.Parameters.AddWithValue("date", date);
|
||||
Assert.Equal(1, command.ExecuteNonQuery());
|
||||
|
||||
command.CommandText = "SELECT date FROM Test;";
|
||||
var result = command.ExecuteScalar();
|
||||
Assert.Equal("2018-03-25 00:00:00+00:00", (string)result);
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal("2018-03-25 00:00:00+00:00", reader.GetString(0));
|
||||
Assert.Equal(date, reader.GetDateTimeOffset(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_range_of_parameters_using_DbCommand_base_class()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
var command = connection.CreateCommand() as DbCommand;
|
||||
command.CommandText = "SELECT @Value1, @Value2;";
|
||||
|
||||
var parameterValue1 = new SqliteParameter("@Value1", SqliteType.Text);
|
||||
parameterValue1.Value = "ABCDE";
|
||||
|
||||
var parameterValue2 = new SqliteParameter("@Value2", SqliteType.Text);
|
||||
parameterValue2.Value = "FGHIJ";
|
||||
|
||||
var parameters = new[] { parameterValue1, parameterValue2 };
|
||||
|
||||
command.Parameters.AddRange(parameters);
|
||||
connection.Open();
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
Assert.True(reader.Read());
|
||||
Assert.Equal(parameterValue1.Value, reader.GetString(0));
|
||||
Assert.Equal(parameterValue2.Value, reader.GetString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum MyEnum
|
||||
{
|
||||
One = 1
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using Microsoft.Data.Sqlite.Properties;
|
||||
using SQLitePCL;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Data.Sqlite
|
||||
{
|
||||
public class SqliteTransactionTest
|
||||
{
|
||||
[Fact]
|
||||
public void Ctor_sets_read_uncommitted()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:;Cache=Shared"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (connection.BeginTransaction(IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
Assert.Equal(1L, connection.ExecuteScalar<long>("PRAGMA read_uncommitted;"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ctor_unsets_read_uncommitted_when_serializable()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (connection.BeginTransaction(IsolationLevel.Serializable))
|
||||
{
|
||||
Assert.Equal(0L, connection.ExecuteScalar<long>("PRAGMA read_uncommitted;"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(IsolationLevel.Chaos)]
|
||||
[InlineData(IsolationLevel.Snapshot)]
|
||||
public void Ctor_throws_when_invalid_isolation_level(IsolationLevel isolationLevel)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() => connection.BeginTransaction(isolationLevel));
|
||||
|
||||
Assert.Equal(Resources.InvalidIsolationLevel(isolationLevel), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadUncommitted_allows_dirty_reads()
|
||||
{
|
||||
const string connectionString = "Data Source=read-uncommitted;Mode=Memory;Cache=Shared";
|
||||
|
||||
using (var connection1 = new SqliteConnection(connectionString))
|
||||
using (var connection2 = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection1.Open();
|
||||
connection2.Open();
|
||||
|
||||
connection1.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
|
||||
|
||||
using (connection1.BeginTransaction())
|
||||
using (connection2.BeginTransaction(IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
connection1.ExecuteNonQuery("UPDATE Data SET Value = 1;");
|
||||
|
||||
var value = connection2.ExecuteScalar<long>("SELECT * FROM Data;");
|
||||
|
||||
Assert.Equal(1, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serialized_disallows_dirty_reads()
|
||||
{
|
||||
const string connectionString = "Data Source=serialized;Mode=Memory;Cache=Shared";
|
||||
|
||||
using (var connection1 = new SqliteConnection(connectionString))
|
||||
using (var connection2 = new SqliteConnection(connectionString))
|
||||
{
|
||||
connection1.Open();
|
||||
connection2.Open();
|
||||
|
||||
connection1.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
|
||||
|
||||
using (connection1.BeginTransaction())
|
||||
{
|
||||
connection1.ExecuteNonQuery("UPDATE Data SET Value = 1;");
|
||||
|
||||
connection2.DefaultTimeout = 0;
|
||||
|
||||
var ex = Assert.Throws<SqliteException>(
|
||||
() =>
|
||||
{
|
||||
using (connection2.BeginTransaction(IsolationLevel.Serializable))
|
||||
{
|
||||
connection2.ExecuteScalar<long>("SELECT * FROM Data;");
|
||||
}
|
||||
});
|
||||
|
||||
Assert.Equal(raw.SQLITE_LOCKED, ex.SqliteErrorCode);
|
||||
Assert.Equal(raw.SQLITE_LOCKED_SHAREDCACHE, ex.SqliteExtendedErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsolationLevel_throws_when_completed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var transaction = connection.BeginTransaction();
|
||||
transaction.Dispose();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.IsolationLevel);
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsolationLevel_is_inferred_when_unspecified()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:;Cache=Shared"))
|
||||
{
|
||||
connection.Open();
|
||||
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;");
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
Assert.Equal(IsolationLevel.ReadUncommitted, transaction.IsolationLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(IsolationLevel.ReadUncommitted)]
|
||||
[InlineData(IsolationLevel.ReadCommitted)]
|
||||
[InlineData(IsolationLevel.RepeatableRead)]
|
||||
public void IsolationLevel_is_increased_when_unsupported(IsolationLevel isolationLevel)
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction(isolationLevel))
|
||||
{
|
||||
Assert.Equal(IsolationLevel.Serializable, transaction.IsolationLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Commit_throws_when_completed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var transaction = connection.BeginTransaction();
|
||||
transaction.Dispose();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Commit_throws_when_completed_externally()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("ROLLBACK;");
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Commit_throws_when_connection_closed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.Close();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Commit_works()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
CreateTestTable(connection);
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
|
||||
|
||||
transaction.Commit();
|
||||
|
||||
Assert.Null(connection.Transaction);
|
||||
Assert.Null(transaction.Connection);
|
||||
}
|
||||
|
||||
Assert.Equal(1L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rollback_noops_once_when_completed_externally()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("ROLLBACK;");
|
||||
|
||||
transaction.Rollback();
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Rollback());
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rollback_throws_when_completed()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var transaction = connection.BeginTransaction();
|
||||
transaction.Dispose();
|
||||
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Rollback());
|
||||
|
||||
Assert.Equal(Resources.TransactionCompleted, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rollback_works()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
CreateTestTable(connection);
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
|
||||
|
||||
transaction.Rollback();
|
||||
|
||||
Assert.Null(connection.Transaction);
|
||||
Assert.Null(transaction.Connection);
|
||||
}
|
||||
|
||||
Assert.Equal(0L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_works()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
CreateTestTable(connection);
|
||||
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
|
||||
|
||||
transaction.Dispose();
|
||||
|
||||
Assert.Null(connection.Transaction);
|
||||
Assert.Null(transaction.Connection);
|
||||
}
|
||||
|
||||
Assert.Equal(0L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_can_be_called_more_than_once()
|
||||
{
|
||||
using (var connection = new SqliteConnection("Data Source=:memory:"))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var transaction = connection.BeginTransaction();
|
||||
|
||||
transaction.Dispose();
|
||||
transaction.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateTestTable(SqliteConnection connection)
|
||||
{
|
||||
connection.ExecuteNonQuery(
|
||||
@"
|
||||
CREATE TABLE TestTable (
|
||||
TestColumn INTEGER
|
||||
)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Data.Sqlite.TestUtilities
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public sealed class UseCultureAttribute : BeforeAfterTestAttribute
|
||||
{
|
||||
private CultureInfo _originalCulture;
|
||||
private CultureInfo _originalUICulture;
|
||||
|
||||
public UseCultureAttribute(string culture)
|
||||
: this(culture, culture)
|
||||
{
|
||||
}
|
||||
|
||||
public UseCultureAttribute(string culture, string uiCulture)
|
||||
{
|
||||
Culture = new CultureInfo(culture);
|
||||
UICulture = new CultureInfo(uiCulture);
|
||||
}
|
||||
|
||||
public CultureInfo Culture { get; }
|
||||
|
||||
public CultureInfo UICulture { get; }
|
||||
|
||||
public override void Before(MethodInfo methodUnderTest)
|
||||
{
|
||||
_originalCulture = CultureInfo.CurrentCulture;
|
||||
_originalUICulture = CultureInfo.CurrentUICulture;
|
||||
CultureInfo.CurrentCulture = Culture;
|
||||
CultureInfo.CurrentUICulture = UICulture;
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodUnderTest)
|
||||
{
|
||||
CultureInfo.CurrentCulture = _originalCulture;
|
||||
CultureInfo.CurrentUICulture = _originalUICulture;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
<#@ template hostspecific="true" #>
|
||||
<#@ assembly name="EnvDTE" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ assembly name="System.Windows.Forms" #>
|
||||
<#@ import namespace="System.Collections" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ import namespace="System.IO" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Resources" #>
|
||||
<#@ import namespace="System.Text.RegularExpressions" #>
|
||||
<#@ import namespace="EnvDTE" #>
|
||||
<#
|
||||
var model = LoadResources();
|
||||
#>
|
||||
// <auto-generated />
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
namespace <#= model.Namespace #>
|
||||
{
|
||||
internal static class <#= model.Class #>
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("<#= model.ResourceName #>", typeof(<#= model.Class #>).GetTypeInfo().Assembly);
|
||||
<#
|
||||
foreach (var resource in model.Resources)
|
||||
{
|
||||
#>
|
||||
|
||||
/// <summary>
|
||||
<#
|
||||
foreach (var line in Lines(resource.Value))
|
||||
{
|
||||
#>
|
||||
/// <#= Xml(line) #>
|
||||
<#
|
||||
}
|
||||
#>
|
||||
/// </summary>
|
||||
<#
|
||||
if (resource.Parameters.Any())
|
||||
{
|
||||
#>
|
||||
public static string <#= resource.Name #>(<#= List("object ", resource.Parameters) #>)
|
||||
=> string.Format(
|
||||
GetString("<#= resource.Name #>", <#= List("nameof(", resource.Parameters, ")") #>),
|
||||
<#= List(resource.Parameters) #>);
|
||||
<#
|
||||
}
|
||||
else
|
||||
{
|
||||
#>
|
||||
public static string <#= resource.Name #>
|
||||
=> GetString("<#= resource.Name #>");
|
||||
<#
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
for (var i = 0; i < formatterNames.Length; i++)
|
||||
{
|
||||
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
<#+
|
||||
ResourceFile LoadResources()
|
||||
{
|
||||
var result = new ResourceFile();
|
||||
|
||||
var services = (IServiceProvider)Host;
|
||||
var dte = (DTE)services.GetService(typeof(DTE));
|
||||
|
||||
var resourceFile = (string)Session["ResourceFile"];
|
||||
if (!Path.IsPathRooted(resourceFile))
|
||||
{
|
||||
resourceFile = Host.ResolvePath(resourceFile);
|
||||
}
|
||||
|
||||
var resourceProjectItem = dte.Solution.FindProjectItem(resourceFile);
|
||||
var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
|
||||
var project = templateProjectItem.ContainingProject;
|
||||
var rootNamespace = (string)project.Properties.Item("RootNamespace").Value;
|
||||
var resourceDir = Path.GetDirectoryName(resourceFile);
|
||||
var projectDir = (string)project.Properties.Item("FullPath").Value;
|
||||
var resourceNamespace = rootNamespace + "." + resourceDir.Substring(projectDir.Length)
|
||||
.Replace(Path.DirectorySeparatorChar, '.');
|
||||
|
||||
result.Namespace = (string)resourceProjectItem.Properties.Item("CustomToolNamespace")?.Value;
|
||||
if (string.IsNullOrEmpty(result.Namespace))
|
||||
{
|
||||
result.Namespace = resourceNamespace;
|
||||
}
|
||||
|
||||
result.Class = Path.GetFileNameWithoutExtension(resourceFile);
|
||||
|
||||
result.ResourceName = resourceNamespace + "." + result.Class;
|
||||
|
||||
using (var reader = new ResXResourceReader(resourceFile))
|
||||
{
|
||||
result.Resources = Enumerable.ToList(
|
||||
from DictionaryEntry r in reader
|
||||
let value = (string)r.Value
|
||||
select new Resource
|
||||
{
|
||||
Name = (string)r.Key,
|
||||
Value = value,
|
||||
Parameters = Regex.Matches(value, @"\{(\w+)\}").Cast<Match>().Select(m => m.Groups[1].Value)
|
||||
.Distinct().ToList()
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IEnumerable<string> Lines(string value)
|
||||
=> value.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
|
||||
string Xml(string value)
|
||||
=> value.Replace("<", "<").Replace(">", ">");
|
||||
|
||||
string List(IEnumerable<string> items)
|
||||
=> List(null, items);
|
||||
|
||||
string List(string prefix, IEnumerable<string> items, string suffix = null)
|
||||
=> string.Join(", ", items.Select(i => prefix + i + suffix));
|
||||
|
||||
class ResourceFile
|
||||
{
|
||||
public string Namespace { get; set; }
|
||||
public string Class { get; set; }
|
||||
public string ResourceName { get; set; }
|
||||
public IEnumerable<Resource> Resources { get; set; }
|
||||
}
|
||||
|
||||
class Resource
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public IEnumerable<string> Parameters { get; set; }
|
||||
}
|
||||
#>
|
Загрузка…
Ссылка в новой задаче